From d60909007d2bcfeffe9a48d4c3a86471599cab2c Mon Sep 17 00:00:00 2001 From: Albertone Quentin Date: Tue, 3 Feb 2026 17:27:14 +0100 Subject: [PATCH 1/4] feat(cli scaffold): allow deprecated flags --- cmd/cmd.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 8868722e5..07b81c2fe 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -208,7 +208,9 @@ func MustCLICommandFlagName(c cliCommand, field interface{}) string { // - cli-usage:"": an optional string to use as flag usage // help message. For positional arguments, this field is used as argument // label for the "use" command help. -// - cli-hidden:"": mark the corresponding flag "hidden". +// - cli-hidden:"": mark the corresponding flag "hidden" +// - cli-deprecated:"": mark the corresponding flag as hidden +// and display the deprecation message when used. func cliCommandFlagSet(c cliCommand) (*pflag.FlagSet, error) { fs := pflag.NewFlagSet("", pflag.ExitOnError) cv := reflect.ValueOf(c) @@ -247,6 +249,11 @@ func cliCommandFlagSet(c cliCommand) (*pflag.FlagSet, error) { flagUsage = v } + var deprecatedMsg *string + if v, ok := cTypeField.Tag.Lookup("cli-deprecated"); ok { + deprecatedMsg = &v + } + flagDefaultValue := cv.Field(i).Interface() switch t := cTypeField.Type.Kind(); t { @@ -285,6 +292,13 @@ func cliCommandFlagSet(c cliCommand) (*pflag.FlagSet, error) { default: return nil, cliCommandImplemError{fmt.Sprintf("unsupported type %s", t)} } + if deprecatedMsg != nil { + if err := fs.MarkDeprecated(flagName, *deprecatedMsg); err != nil { + return nil, cliCommandImplemError{ + reason: fmt.Sprintf("unable to deprecate flag: %s, err: %s", flagName, err.Error()), + } + } + } if _, ok := cTypeField.Tag.Lookup("cli-hidden"); ok { if err := fs.MarkHidden(flagName); err != nil { From ab97563d346b403312b1a79939e88029008ec70e Mon Sep 17 00:00:00 2001 From: Albertone Quentin Date: Tue, 3 Feb 2026 17:33:20 +0100 Subject: [PATCH 2/4] chores: edit changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ebc69c66..77155b98c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Bug fixes - fix(instance): create instance with an IPv6 #788 +## Features +- feat(cli scaffold): allow deprecated flags #789 + ### Breaking changes - instance create: merge --ipv6 and --private-instance into --public-ip #788 - nodepool: replace --ipv6 and --nodepool-ipv6 with --public-ip and --nodepool-public-ip #788 From cca9f0948acc89cf79f35c54ea93f50dd2dd7f33 Mon Sep 17 00:00:00 2001 From: Albertone Quentin Date: Fri, 6 Feb 2026 10:24:44 +0100 Subject: [PATCH 3/4] add unit test for deprecated flags --- cmd/cmd_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 63e09f2e3..715b47549 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -20,6 +20,7 @@ type testCLICmd struct { Bool bool MultiStrings []string `cli-flag:"multi-string-value" cli-usage:"multiple strings"` StringsMap map[string]string + Deprecated string `cli-flags:"deprecated" cli-deprecated:"use another flag instead"` aliases []string `cli:"-"` short string `cli:"-"` @@ -49,6 +50,7 @@ func Test_cliCommandFlagName(t *testing.T) { func Test_cliCommandFlagSet(t *testing.T) { var ( testSingleStringValue = "test" + testDeprecatedValue = "deprecated" testInt64Value int64 = 42 testBoolValue = true testMultiStringsValue = []string{"a", "b", "c"} @@ -61,14 +63,17 @@ func Test_cliCommandFlagSet(t *testing.T) { Bool: testBoolValue, MultiStrings: testMultiStringsValue, StringsMap: testStringsMap, + Deprecated: testDeprecatedValue, } expected := pflag.NewFlagSet("", pflag.ExitOnError) expected.StringP("single-string", "s", testSingleStringValue, "") + expected.StringP("deprecated", "", testDeprecatedValue, "") expected.Int64P("int64", "i", testInt64Value, "") expected.BoolP("bool", "", testBoolValue, "") expected.StringSliceP("multi-string-value", "", testMultiStringsValue, "multiple strings") expected.StringToStringP("strings-map", "", testStringsMap, "") + require.NoError(t, expected.MarkDeprecated("deprecated", "use another flag instead")) actual, err := cliCommandFlagSet(cmd) require.NoError(t, err) @@ -100,6 +105,7 @@ func Test_cliCommandUse(t *testing.T) { func Test_cliCommandDefaultPreRun(t *testing.T) { var ( testRequiredArg = "required-arg" + testDeprecatedValue = "deprecated" testOptionalArgs = []string{"optional-arg1", "optional-arg2"} testSingleStringValue = "test" testInt64Value int64 = 42 @@ -114,6 +120,7 @@ func Test_cliCommandDefaultPreRun(t *testing.T) { testFlags.BoolP("bool", "", false, "") testFlags.StringSliceP("multi-string-value", "", nil, "multiple strings") testFlags.StringToStringP("strings-map", "", nil, "") + testFlags.StringP("deprecated", "", "", "") type args struct { cmd *cobra.Command @@ -182,6 +189,7 @@ func Test_cliCommandDefaultPreRun(t *testing.T) { flags.BoolP("bool", "", testBoolValue, "") flags.StringSliceP("multi-string-value", "", testMultiStringsValue, "") flags.StringToStringP("strings-map", "", testStringsMap, "") + flags.StringP("deprecated", "", testDeprecatedValue, "") testCmd := new(cobra.Command) flags.VisitAll(func(flag *pflag.Flag) { testCmd.Flags().AddFlag(flag) }) @@ -192,6 +200,7 @@ func Test_cliCommandDefaultPreRun(t *testing.T) { expected: &testCLICmd{ RequiredArg: testRequiredArg, SingleString: testSingleStringValue, + Deprecated: testDeprecatedValue, Int64: testInt64Value, Bool: testBoolValue, MultiStrings: testMultiStringsValue, From bb5921d6990ec50db66c7da1000f3632a433167d Mon Sep 17 00:00:00 2001 From: Albertone Quentin Date: Fri, 6 Feb 2026 11:45:25 +0100 Subject: [PATCH 4/4] feat: upgrade go versoin to prevent crypto/tls vulnerability --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 240b69ab4..844eb9140 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/exoscale/cli -go 1.24.12 +go 1.24.13 require ( github.com/aws/aws-sdk-go-v2 v1.2.0