Add TUI add and preview commands

Use charmbracelet/huh for an interactive add flow. Add a preview
subcommand to enter/exit per-project pre-release tags. Move stamp.toml
into .stamp/ and add ConfigPath helper. Prefer --snapshot then project
PreTag when computing versions and promote bumps to pre-release when
appropriate. Export CurrentVersion and add required TUI deps to go.mod.
This commit is contained in:
Thomas
2026-03-12 22:59:20 +01:00
parent fb347eaa54
commit 8049c505a0
12 changed files with 323 additions and 87 deletions

View File

@@ -11,7 +11,6 @@ import (
const validTOML = `
[config]
base_branch = "main"
changeset_dir = ".stamp"
[[projects]]
name = "my-app"
@@ -24,11 +23,20 @@ path = "libs/my-lib"
version = "0.1.0"
`
func TestLoad_Valid(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "stamp.toml"), []byte(validTOML), 0o644); err != nil {
func writeConfig(t *testing.T, dir, content string) {
t.Helper()
stampDir := filepath.Join(dir, ".stamp")
if err := os.MkdirAll(stampDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(stampDir, "stamp.toml"), []byte(content), 0o644); err != nil {
t.Fatal(err)
}
}
func TestLoad_Valid(t *testing.T) {
dir := t.TempDir()
writeConfig(t, dir, validTOML)
cfg, err := config.Load(dir)
if err != nil {
@@ -42,16 +50,14 @@ func TestLoad_Valid(t *testing.T) {
t.Errorf("expected base_branch=main, got %s", cfg.BaseBranch())
}
if cfg.ChangesetDir() != ".stamp" {
t.Errorf("expected changeset_dir=.stamp, got %s", cfg.ChangesetDir())
t.Errorf("expected ChangesetDir=.stamp, got %s", cfg.ChangesetDir())
}
}
func TestLoad_Defaults(t *testing.T) {
dir := t.TempDir()
minimal := "[[projects]]\nname = \"app\"\npath = \".\"\nversion = \"1.0.0\"\n"
if err := os.WriteFile(filepath.Join(dir, "stamp.toml"), []byte(minimal), 0o644); err != nil {
t.Fatal(err)
}
writeConfig(t, dir, minimal)
cfg, err := config.Load(dir)
if err != nil {
@@ -75,9 +81,7 @@ func TestLoad_MissingFile(t *testing.T) {
func TestLoad_NoProjects(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "stamp.toml"), []byte("[config]\n"), 0o644); err != nil {
t.Fatal(err)
}
writeConfig(t, dir, "[config]\n")
_, err := config.Load(dir)
if err == nil {
t.Fatal("expected error for config with no projects")
@@ -97,9 +101,7 @@ name = "app"
path = "other"
version = "2.0.0"
`
if err := os.WriteFile(filepath.Join(dir, "stamp.toml"), []byte(dup), 0o644); err != nil {
t.Fatal(err)
}
writeConfig(t, dir, dup)
_, err := config.Load(dir)
if err == nil {
t.Fatal("expected error for duplicate project name")
@@ -108,9 +110,7 @@ version = "2.0.0"
func TestFindProject(t *testing.T) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "stamp.toml"), []byte(validTOML), 0o644); err != nil {
t.Fatal(err)
}
writeConfig(t, dir, validTOML)
cfg, _ := config.Load(dir)
if p := cfg.FindProject("my-app"); p == nil {