From 29c5ba172a5b07e3c73ef6cce91d984db075fda4 Mon Sep 17 00:00:00 2001 From: Marc Campbell Date: Wed, 17 Dec 2025 05:59:49 -0800 Subject: [PATCH 1/2] Support --auto without a .replicated config --- cli/cmd/release_create.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cli/cmd/release_create.go b/cli/cmd/release_create.go index b6e4dd29..b07a9813 100644 --- a/cli/cmd/release_create.go +++ b/cli/cmd/release_create.go @@ -89,10 +89,12 @@ func (r *runners) InitReleaseCreate(parent *cobra.Command) error { originalPreRun := parent.PersistentPreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { // Check if we're using config-based flow + // Note: --auto flag will set yaml-dir later, so don't use config flow when --auto is specified useConfigFlow := r.args.createReleaseYaml == "" && r.args.createReleaseYamlFile == "" && r.args.createReleaseYamlDir == "" && - r.args.createReleaseChart == "" + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults if useConfigFlow { // For config flow, temporarily clear app state before calling parent prerun @@ -233,10 +235,12 @@ func (r *runners) releaseCreate(cmd *cobra.Command, args []string) (err error) { } // Check if we should use config-based flow (no explicit source flags provided) + // Note: --auto flag will set yaml-dir later, so don't use config flow when --auto is specified useConfigFlow := r.args.createReleaseYaml == "" && r.args.createReleaseYamlFile == "" && r.args.createReleaseYamlDir == "" && - r.args.createReleaseChart == "" + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults var config *tools.Config var stagingDir string From 7f1e0dc17eaa193d7b462effee031d5433892227 Mon Sep 17 00:00:00 2001 From: Marc Campbell Date: Wed, 17 Dec 2025 06:04:05 -0800 Subject: [PATCH 2/2] add unit --- cli/cmd/release_create_test.go | 222 +++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 cli/cmd/release_create_test.go diff --git a/cli/cmd/release_create_test.go b/cli/cmd/release_create_test.go new file mode 100644 index 00000000..2986cfb4 --- /dev/null +++ b/cli/cmd/release_create_test.go @@ -0,0 +1,222 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// TestUseConfigFlow_WithAutoFlag tests that --auto flag prevents config-based flow +func TestUseConfigFlow_WithAutoFlag(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseAutoDefaults: true, + // All source flags empty + createReleaseYaml: "", + createReleaseYamlFile: "", + createReleaseYamlDir: "", + createReleaseChart: "", + }, + } + + useConfigFlow := r.args.createReleaseYaml == "" && + r.args.createReleaseYamlFile == "" && + r.args.createReleaseYamlDir == "" && + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults + + assert.False(t, useConfigFlow, "--auto flag should prevent config flow") +} + +// TestUseConfigFlow_WithoutAutoFlag tests that config flow is used when no flags are provided +func TestUseConfigFlow_WithoutAutoFlag(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseAutoDefaults: false, + // All source flags empty + createReleaseYaml: "", + createReleaseYamlFile: "", + createReleaseYamlDir: "", + createReleaseChart: "", + }, + } + + useConfigFlow := r.args.createReleaseYaml == "" && + r.args.createReleaseYamlFile == "" && + r.args.createReleaseYamlDir == "" && + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults + + assert.True(t, useConfigFlow, "config flow should be used when no flags provided") +} + +// TestUseConfigFlow_WithYamlDir tests that providing --yaml-dir prevents config flow +func TestUseConfigFlow_WithYamlDir(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseAutoDefaults: false, + createReleaseYamlDir: "./manifests", + }, + } + + useConfigFlow := r.args.createReleaseYaml == "" && + r.args.createReleaseYamlFile == "" && + r.args.createReleaseYamlDir == "" && + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults + + assert.False(t, useConfigFlow, "--yaml-dir flag should prevent config flow") +} + +// TestUseConfigFlow_WithAutoAndYamlDir tests that both --auto and --yaml-dir prevents config flow +func TestUseConfigFlow_WithAutoAndYamlDir(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseAutoDefaults: true, + createReleaseYamlDir: "./custom", + }, + } + + useConfigFlow := r.args.createReleaseYaml == "" && + r.args.createReleaseYamlFile == "" && + r.args.createReleaseYamlDir == "" && + r.args.createReleaseChart == "" && + !r.args.createReleaseAutoDefaults + + assert.False(t, useConfigFlow, "--auto and --yaml-dir should prevent config flow") +} + +// TestSetKOTSDefaultReleaseParams_WithEmptyYamlDir tests that yaml-dir defaults to ./manifests +func TestSetKOTSDefaultReleaseParams_WithEmptyYamlDir(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseYamlDir: "", + }, + } + + // Mock git operations would fail, so we only test the yaml-dir setting + // which happens before git operations + if r.args.createReleaseYamlDir == "" { + r.args.createReleaseYamlDir = "./manifests" + } + + assert.Equal(t, "./manifests", r.args.createReleaseYamlDir, "yaml-dir should default to ./manifests") +} + +// TestSetKOTSDefaultReleaseParams_WithExistingYamlDir tests that existing yaml-dir is preserved +func TestSetKOTSDefaultReleaseParams_WithExistingYamlDir(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleaseYamlDir: "./custom", + }, + } + + // Same logic as in setKOTSDefaultReleaseParams + if r.args.createReleaseYamlDir == "" { + r.args.createReleaseYamlDir = "./manifests" + } + + assert.Equal(t, "./custom", r.args.createReleaseYamlDir, "existing yaml-dir should be preserved") +} + +// TestSetKOTSDefaultReleaseParams_PromoteMapsMainToUnstable tests branch name mapping +func TestSetKOTSDefaultReleaseParams_PromoteMapsMainToUnstable(t *testing.T) { + tests := []struct { + name string + branch string + wantPromote string + }{ + { + name: "main branch maps to Unstable", + branch: "main", + wantPromote: "Unstable", + }, + { + name: "master branch maps to Unstable", + branch: "master", + wantPromote: "Unstable", + }, + { + name: "feature branch uses branch name", + branch: "feature-xyz", + wantPromote: "feature-xyz", + }, + { + name: "release branch uses branch name", + branch: "release-1.0", + wantPromote: "release-1.0", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Simulate the logic from setKOTSDefaultReleaseParams + promote := tt.branch + if tt.branch == "master" || tt.branch == "main" { + promote = "Unstable" + } + + assert.Equal(t, tt.wantPromote, promote) + }) + } +} + +// TestSetKOTSDefaultReleaseParams_PreservesExistingPromote tests that user-provided values are preserved +func TestSetKOTSDefaultReleaseParams_PreservesExistingPromote(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromote: "Beta", + }, + } + + // Simulate the logic from setKOTSDefaultReleaseParams + if r.args.createReleasePromote == "" { + r.args.createReleasePromote = "auto-generated" + } + + assert.Equal(t, "Beta", r.args.createReleasePromote, "user-provided promote value should be preserved") +} + +// TestSetKOTSDefaultReleaseParams_PreservesExistingVersion tests that user-provided version is preserved +func TestSetKOTSDefaultReleaseParams_PreservesExistingVersion(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromoteVersion: "v1.2.3", + }, + } + + // Simulate the logic from setKOTSDefaultReleaseParams + if r.args.createReleasePromoteVersion == "" { + r.args.createReleasePromoteVersion = "auto-generated" + } + + assert.Equal(t, "v1.2.3", r.args.createReleasePromoteVersion, "user-provided version should be preserved") +} + +// TestSetKOTSDefaultReleaseParams_PreservesExistingReleaseNotes tests that user-provided release notes are preserved +func TestSetKOTSDefaultReleaseParams_PreservesExistingReleaseNotes(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromoteNotes: "Custom release notes", + }, + } + + // Simulate the logic from setKOTSDefaultReleaseParams + if r.args.createReleasePromoteNotes == "" { + r.args.createReleasePromoteNotes = "auto-generated" + } + + assert.Equal(t, "Custom release notes", r.args.createReleasePromoteNotes, "user-provided release notes should be preserved") +} + +// TestSetKOTSDefaultReleaseParams_SetsEnsureChannelAndLint tests that flags are automatically set +func TestSetKOTSDefaultReleaseParams_SetsEnsureChannelAndLint(t *testing.T) { + args := runnerArgs{} + + // Simulate the logic from setKOTSDefaultReleaseParams + args.createReleasePromoteEnsureChannel = true + args.createReleaseLint = true + + assert.True(t, args.createReleasePromoteEnsureChannel, "ensure-channel should be set to true") + assert.True(t, args.createReleaseLint, "lint should be set to true") +}