From 0fb9d8ef1331b7fdccbe94a1afe5dfd5c81aac1a Mon Sep 17 00:00:00 2001 From: Marko Bevc Date: Fri, 29 May 2026 16:47:39 +0100 Subject: [PATCH] feat: remove visibility flag and warn on deprecated flow endpoint The legacy PUT /api/v2/flows/{org} endpoint is deprecated. The `--visibility` flag was only meaningful for that endpoint, so remove it from `create flow`. Emit a deprecation warning when neither `--template-file` nor `--use-empty-template` is provided, since that path still uses the deprecated endpoint. --- cmd/kosli/createFlow.go | 5 +---- cmd/kosli/createFlow_test.go | 7 ++++--- cmd/kosli/root.go | 1 - cmd/kosli/testHelpers.go | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/cmd/kosli/createFlow.go b/cmd/kosli/createFlow.go index 9cc9d2bd9..300e59e4c 100644 --- a/cmd/kosli/createFlow.go +++ b/cmd/kosli/createFlow.go @@ -26,7 +26,6 @@ const createFlowExample = ` # create/update a Kosli flow (with empty template): kosli create flow yourFlowName \ --description yourFlowDescription \ - --visibility private OR public \ --use-empty-template \ --api-token yourAPIToken \ --org yourOrgName @@ -34,7 +33,6 @@ kosli create flow yourFlowName \ # create/update a Kosli flow (with template file): kosli create flow yourFlowName \ --description yourFlowDescription \ - --visibility private OR public \ --template-file /path/to/your/template/file.yml \ --api-token yourAPIToken \ --org yourOrgName @@ -49,7 +47,6 @@ type createFlowOptions struct { type FlowPayload struct { Name string `json:"name"` Description string `json:"description"` - Visibility string `json:"visibility"` Template []string `json:"template,omitempty"` } @@ -85,7 +82,6 @@ func newCreateFlowCmd(out io.Writer) *cobra.Command { } cmd.Flags().StringVar(&o.payload.Description, "description", "", flowDescriptionFlag) - cmd.Flags().StringVar(&o.payload.Visibility, "visibility", "private", visibilityFlag) cmd.Flags().StringSliceVarP(&o.payload.Template, "template", "t", []string{}, templateFlag) cmd.Flags().StringVarP(&o.TemplateFile, "template-file", "f", "", templateFileFlag) cmd.Flags().BoolVar(&o.UseEmptyTemplate, "use-empty-template", false, useEmptyTemplateFlag) @@ -137,6 +133,7 @@ func (o *createFlowOptions) run(args []string) error { } } else { // legacy flows + logger.Warn("creating a flow without --template-file or --use-empty-template uses a deprecated API endpoint and will stop working in a future release; please provide a template") url, err = neturl.JoinPath(global.Host, "api/v2/flows", global.Org) if err != nil { return err diff --git a/cmd/kosli/createFlow_test.go b/cmd/kosli/createFlow_test.go index 6e4e76582..73c964e2b 100644 --- a/cmd/kosli/createFlow_test.go +++ b/cmd/kosli/createFlow_test.go @@ -25,6 +25,7 @@ func (suite *CreateFlowCommandTestSuite) SetupTest() { } func (suite *CreateFlowCommandTestSuite) TestCreateFlowCmd() { + deprecationWarning := "[warning] creating a flow without --template-file or --use-empty-template uses a deprecated API endpoint and will stop working in a future release; please provide a template\n" tests := []cmdTestCase{ { wantError: true, @@ -36,17 +37,17 @@ func (suite *CreateFlowCommandTestSuite) TestCreateFlowCmd() { wantError: true, name: "fails when name is considered invalid by the server", cmd: "create flow 'foo bar'" + suite.defaultKosliArguments, - goldenRegex: "^Error: .*foo bar", + goldenRegex: "Error: .*foo bar", }, { name: "can create a flow (by default legacy template is used)", cmd: "create flow newFlow --description \"my new flow\" " + suite.defaultKosliArguments, - golden: "flow 'newFlow' was created\n", + golden: deprecationWarning + "flow 'newFlow' was created\n", }, { name: "re-creating a flow updates its metadata", cmd: "create flow newFlow --description \"changed description\" " + suite.defaultKosliArguments, - golden: "flow 'newFlow' was updated\n", + golden: deprecationWarning + "flow 'newFlow' was updated\n", }, { wantError: true, diff --git a/cmd/kosli/root.go b/cmd/kosli/root.go index 0bd1b4177..1ff9cef0d 100644 --- a/cmd/kosli/root.go +++ b/cmd/kosli/root.go @@ -129,7 +129,6 @@ The ^.kosli_ignore^ will be treated as part of the artifact like any other file, envDescriptionFlag = "[optional] The environment description." flowDescriptionFlag = "[optional] The Kosli flow description." trailDescriptionFlag = "[optional] The Kosli trail description." - visibilityFlag = "[defaulted] The visibility of the Kosli flow. Valid visibilities are [public, private]." templateFlag = "[defaulted] The comma-separated list of required compliance controls names." templateFileFlag = "[optional] The path to a yaml template file. Cannot be used together with --use-empty-template" templateFileSimpleFlag = "[optional] The path to a yaml template file." diff --git a/cmd/kosli/testHelpers.go b/cmd/kosli/testHelpers.go index 8d5ccabc6..a0dd95581 100644 --- a/cmd/kosli/testHelpers.go +++ b/cmd/kosli/testHelpers.go @@ -341,8 +341,8 @@ func CreateFlow(flowName string, t *testing.T) { payload: FlowPayload{ Name: flowName, Description: "test flow", - Visibility: "private", }, + UseEmptyTemplate: true, } err := o.run([]string{flowName}) @@ -356,7 +356,6 @@ func CreateFlowWithTemplate(flowName, templatePath string, t *testing.T) { payload: FlowPayload{ Name: flowName, Description: "test flow", - Visibility: "private", }, TemplateFile: templatePath, }