From 1efab474c97b6e7bcedeca3636098d6d1c0e50d1 Mon Sep 17 00:00:00 2001 From: alicenstar <67430892+alicenstar@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:28:43 -0600 Subject: [PATCH 1/2] unhide release create --required flag, update tests, docs --- cli/cmd/release_create.go | 11 +++++++-- cli/cmd/release_create_test.go | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/cli/cmd/release_create.go b/cli/cmd/release_create.go index 789ab683..af3a22ab 100644 --- a/cli/cmd/release_create.go +++ b/cli/cmd/release_create.go @@ -51,7 +51,10 @@ func (r *runners) InitReleaseCreate(parent *cobra.Command) error { - ./manifests/*.yaml With this config, simply run: - replicated release create --version 1.0.0 --promote Unstable`, + replicated release create --version 1.0.0 --promote Unstable + + To mark a release as required during upgrades: + replicated release create --version 1.0.0 --promote Unstable --required`, SilenceUsage: false, SilenceErrors: true, // this command uses custom error printing } @@ -78,7 +81,6 @@ func (r *runners) InitReleaseCreate(parent *cobra.Command) error { cmd.Flags().StringVarP(&r.outputFormat, "output", "o", "table", "The output format to use. One of: json|table") // not supported for KOTS - cmd.Flags().MarkHidden("required") cmd.Flags().MarkHidden("yaml-file") cmd.Flags().MarkHidden("yaml") cmd.Flags().MarkHidden("chart") @@ -506,6 +508,11 @@ func (r *runners) validateReleaseCreateParams() error { return errors.Errorf("the flag --ensure-channel is only supported for KOTS applications, app %q is of type %q", r.appID, r.appType) } + // can't mark a release as required if you didn't pass a promote channel + if r.args.createReleasePromoteRequired && r.args.createReleasePromote == "" { + return errors.New("--required can only be used with --promote ") + } + return nil } diff --git a/cli/cmd/release_create_test.go b/cli/cmd/release_create_test.go index 2986cfb4..709d8e60 100644 --- a/cli/cmd/release_create_test.go +++ b/cli/cmd/release_create_test.go @@ -220,3 +220,47 @@ func TestSetKOTSDefaultReleaseParams_SetsEnsureChannelAndLint(t *testing.T) { assert.True(t, args.createReleasePromoteEnsureChannel, "ensure-channel should be set to true") assert.True(t, args.createReleaseLint, "lint should be set to true") } + +// TestRequiredFlagRequiresPromote tests that --required fails without --promote +func TestRequiredFlagRequiresPromote(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromoteRequired: true, + createReleasePromote: "", // No promote channel + createReleaseYamlDir: "./manifests", + }, + appType: "kots", + } + + err := r.validateReleaseCreateParams() + assert.Error(t, err) + assert.Contains(t, err.Error(), "--required can only be used with --promote") +} + +// TestRequiredFlagWithPromote tests that --required works with --promote +func TestRequiredFlagWithPromote(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromoteRequired: true, + createReleasePromote: "Unstable", + createReleaseYamlDir: "./manifests", + }, + appType: "kots", + } + + err := r.validateReleaseCreateParams() + assert.NoError(t, err) +} + +// TestRequiredFlagDefaultsFalse tests that --required defaults to false +func TestRequiredFlagDefaultsFalse(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromote: "Unstable", + createReleaseYamlDir: "./manifests", + }, + } + + assert.False(t, r.args.createReleasePromoteRequired, + "--required should default to false") +} From b368ac5d3ae39ccfe7908bb4bfc4744e54f71328 Mon Sep 17 00:00:00 2001 From: alicenstar <67430892+alicenstar@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:39:30 -0600 Subject: [PATCH 2/2] address cursor feedback, add test --- cli/cmd/release_create.go | 10 +++++----- cli/cmd/release_create_test.go | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cli/cmd/release_create.go b/cli/cmd/release_create.go index af3a22ab..9c8eb297 100644 --- a/cli/cmd/release_create.go +++ b/cli/cmd/release_create.go @@ -470,6 +470,11 @@ func (r *runners) validateReleaseCreateParams() error { } } + // can't mark a release as required if you didn't pass a promote channel + if r.args.createReleasePromoteRequired && r.args.createReleasePromote == "" { + return errors.New("--required can only be used with --promote ") + } + // If no sources specified, config-based flow will be used (validated elsewhere) if numSources == 0 { return nil @@ -508,11 +513,6 @@ func (r *runners) validateReleaseCreateParams() error { return errors.Errorf("the flag --ensure-channel is only supported for KOTS applications, app %q is of type %q", r.appID, r.appType) } - // can't mark a release as required if you didn't pass a promote channel - if r.args.createReleasePromoteRequired && r.args.createReleasePromote == "" { - return errors.New("--required can only be used with --promote ") - } - return nil } diff --git a/cli/cmd/release_create_test.go b/cli/cmd/release_create_test.go index 709d8e60..05ed05ca 100644 --- a/cli/cmd/release_create_test.go +++ b/cli/cmd/release_create_test.go @@ -264,3 +264,20 @@ func TestRequiredFlagDefaultsFalse(t *testing.T) { assert.False(t, r.args.createReleasePromoteRequired, "--required should default to false") } + +// TestRequiredFlagRequiresPromoteInConfigBasedFlow tests that --required fails +// without --promote even in config-based flow (no explicit yaml sources) +func TestRequiredFlagRequiresPromoteInConfigBasedFlow(t *testing.T) { + r := &runners{ + args: runnerArgs{ + createReleasePromoteRequired: true, + createReleasePromote: "", // No promote channel + // No yaml sources specified - simulates config-based flow + }, + appType: "kots", + } + + err := r.validateReleaseCreateParams() + assert.Error(t, err) + assert.Contains(t, err.Error(), "--required can only be used with --promote") +}