Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions cli/cmd/release_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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")
Expand Down Expand Up @@ -468,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 <channel>")
}

// If no sources specified, config-based flow will be used (validated elsewhere)
if numSources == 0 {
return nil
Expand Down
61 changes: 61 additions & 0 deletions cli/cmd/release_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,64 @@ 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")
}

// 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")
}
Loading