From a44b1fc55735ed610e8a103c4c9faa97c3a32c12 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 10:28:05 -0500 Subject: [PATCH 01/15] feat: Add confirm prompts to some cli actions - Workspace start/stop - Add optional -y skip. Standardize -y flag across commands --- cli/cliui/prompt.go | 13 +++++++++++++ cli/create.go | 1 + cli/start.go | 12 +++++++++++- cli/stop.go | 12 +++++++++++- cli/templatecreate.go | 17 +++++++---------- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/cli/cliui/prompt.go b/cli/cliui/prompt.go index ac39404e27d3f..16f0c438f4007 100644 --- a/cli/cliui/prompt.go +++ b/cli/cliui/prompt.go @@ -24,8 +24,21 @@ type PromptOptions struct { Validate func(string) error } +func AllowSkipPrompt(cmd *cobra.Command) { + cmd.Flags().BoolP("yes", "y", false, "Bypass prompts") +} + // Prompt asks the user for input. func Prompt(cmd *cobra.Command, opts PromptOptions) (string, error) { + // If the cmd has a "yes" flag for skipping confirm prompts, honor it. + // If it's not a "Confirm" prompt, then don't skip. As the default value of + // "yes" makes no sense. + if opts.IsConfirm && cmd.Flags().Lookup("yes") != nil { + if skip, _ := cmd.Flags().GetBool("yes"); skip { + return "yes", nil + } + } + _, _ = fmt.Fprint(cmd.OutOrStdout(), Styles.FocusedPrompt.String()+opts.Text+" ") if opts.IsConfirm { opts.Default = "yes" diff --git a/cli/create.go b/cli/create.go index aa6930e8151f6..6b73ec375b81a 100644 --- a/cli/create.go +++ b/cli/create.go @@ -194,6 +194,7 @@ func create() *cobra.Command { }, } + cliui.AllowSkipPrompt(cmd) cliflag.StringVarP(cmd.Flags(), &templateName, "template", "t", "CODER_TEMPLATE_NAME", "", "Specify a template name.") return cmd } diff --git a/cli/start.go b/cli/start.go index 223731045e38f..31a95188c583b 100644 --- a/cli/start.go +++ b/cli/start.go @@ -11,12 +11,20 @@ import ( ) func start() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Annotations: workspaceCommand, Use: "start ", Short: "Build a workspace with the start state", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + _, err := cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm start workspace?", + IsConfirm: true, + }) + if err != nil { + return err + } + client, err := createClient(cmd) if err != nil { return err @@ -39,4 +47,6 @@ func start() *cobra.Command { return cliui.WorkspaceBuild(cmd.Context(), cmd.OutOrStdout(), client, build.ID, before) }, } + cliui.AllowSkipPrompt(cmd) + return cmd } diff --git a/cli/stop.go b/cli/stop.go index 1125901608413..053cfb4689bb7 100644 --- a/cli/stop.go +++ b/cli/stop.go @@ -11,12 +11,20 @@ import ( ) func stop() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Annotations: workspaceCommand, Use: "stop ", Short: "Build a workspace with the stop state", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + _, err := cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm stop workspace?", + IsConfirm: true, + }) + if err != nil { + return err + } + client, err := createClient(cmd) if err != nil { return err @@ -39,4 +47,6 @@ func stop() *cobra.Command { return cliui.WorkspaceBuild(cmd.Context(), cmd.OutOrStdout(), client, build.ID, before) }, } + cliui.AllowSkipPrompt(cmd) + return cmd } diff --git a/cli/templatecreate.go b/cli/templatecreate.go index 0f6977a674a8e..9ff49dfa0ded7 100644 --- a/cli/templatecreate.go +++ b/cli/templatecreate.go @@ -21,7 +21,6 @@ import ( func templateCreate() *cobra.Command { var ( - yes bool directory string provisioner string ) @@ -84,14 +83,12 @@ func templateCreate() *cobra.Command { return err } - if !yes { - _, err = cliui.Prompt(cmd, cliui.PromptOptions{ - Text: "Confirm create?", - IsConfirm: true, - }) - if err != nil { - return err - } + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm create?", + IsConfirm: true, + }) + if err != nil { + return err } _, err = client.CreateTemplate(cmd.Context(), organization.ID, codersdk.CreateTemplateRequest{ @@ -121,7 +118,7 @@ func templateCreate() *cobra.Command { if err != nil { panic(err) } - cmd.Flags().BoolVarP(&yes, "yes", "y", false, "Bypass prompts") + cliui.AllowSkipPrompt(cmd) return cmd } From 664ea38f998bae1dabbd632255386b2d2d4fbd7d Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 10:32:17 -0500 Subject: [PATCH 02/15] Add confirm prompt to delete workspace --- cli/delete.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cli/delete.go b/cli/delete.go index 0f795c06c5435..8e2ce56b616d8 100644 --- a/cli/delete.go +++ b/cli/delete.go @@ -12,13 +12,21 @@ import ( // nolint func delete() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Annotations: workspaceCommand, Use: "delete ", Short: "Delete a workspace", Aliases: []string{"rm"}, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + _, err := cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm delete workspace?", + IsConfirm: true, + }) + if err != nil { + return err + } + client, err := createClient(cmd) if err != nil { return err @@ -41,4 +49,6 @@ func delete() *cobra.Command { return cliui.WorkspaceBuild(cmd.Context(), cmd.OutOrStdout(), client, build.ID, before) }, } + cliui.AllowSkipPrompt(cmd) + return cmd } From 373cb23ae89644d05e273faf2b285c004578c02f Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 11:32:33 -0500 Subject: [PATCH 03/15] Add unit test for prompt skipping --- cli/cliui/prompt_test.go | 50 +++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/cli/cliui/prompt_test.go b/cli/cliui/prompt_test.go index 1926349c2d1fc..4d1b7370cf9fd 100644 --- a/cli/cliui/prompt_test.go +++ b/cli/cliui/prompt_test.go @@ -1,7 +1,9 @@ package cliui_test import ( + "bytes" "context" + "io" "os" "os/exec" "testing" @@ -24,7 +26,7 @@ func TestPrompt(t *testing.T) { go func() { resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", - }) + }, nil) require.NoError(t, err) msgChan <- resp }() @@ -41,7 +43,7 @@ func TestPrompt(t *testing.T) { resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", IsConfirm: true, - }) + }, nil) require.NoError(t, err) doneChan <- resp }() @@ -50,6 +52,37 @@ func TestPrompt(t *testing.T) { require.Equal(t, "yes", <-doneChan) }) + t.Run("Skip", func(t *testing.T) { + t.Parallel() + ptty := ptytest.New(t) + var buf bytes.Buffer + + // Copy all data written out to a buffer. When we close the ptty, we can + // no longer read from the ptty.Output(), but we can read what was + // written to the buffer. + go func() { + _, err := io.Copy(&buf, ptty.Output()) + require.NoError(t, err, "copy") + }() + + doneChan := make(chan string) + go func() { + resp, err := newPrompt(ptty, cliui.PromptOptions{ + Text: "ShouldNotSeeThis", + IsConfirm: true, + }, func(cmd *cobra.Command) { + cliui.AllowSkipPrompt(cmd) + cmd.SetArgs([]string{"-y"}) + }) + require.NoError(t, err) + doneChan <- resp + }() + + require.Equal(t, "yes", <-doneChan) + require.NoError(t, ptty.Close(), "close ptty") + require.Len(t, buf.Bytes(), 0, "expect no output") + }) + t.Run("JSON", func(t *testing.T) { t.Parallel() ptty := ptytest.New(t) @@ -57,7 +90,7 @@ func TestPrompt(t *testing.T) { go func() { resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", - }) + }, nil) require.NoError(t, err) doneChan <- resp }() @@ -71,9 +104,10 @@ func TestPrompt(t *testing.T) { ptty := ptytest.New(t) doneChan := make(chan string) go func() { + resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", - }) + }, nil) require.NoError(t, err) doneChan <- resp }() @@ -89,7 +123,7 @@ func TestPrompt(t *testing.T) { go func() { resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", - }) + }, nil) require.NoError(t, err) doneChan <- resp }() @@ -101,7 +135,7 @@ func TestPrompt(t *testing.T) { }) } -func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions) (string, error) { +func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions, cmdOpt func(cmd *cobra.Command)) (string, error) { value := "" cmd := &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { @@ -110,6 +144,10 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions) (string, error) { return err }, } + // Optionally modify the cmd + if cmdOpt != nil { + cmdOpt(cmd) + } cmd.SetOutput(ptty.Output()) cmd.SetIn(ptty.Input()) return value, cmd.ExecuteContext(context.Background()) From 3b6cea6461684314fc947094a904288d8b682f75 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 14:06:25 -0500 Subject: [PATCH 04/15] Fix test flakes --- cli/cliui/prompt_test.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cli/cliui/prompt_test.go b/cli/cliui/prompt_test.go index 4d1b7370cf9fd..4b83fe17449b5 100644 --- a/cli/cliui/prompt_test.go +++ b/cli/cliui/prompt_test.go @@ -53,16 +53,21 @@ func TestPrompt(t *testing.T) { }) t.Run("Skip", func(t *testing.T) { - t.Parallel() ptty := ptytest.New(t) var buf bytes.Buffer // Copy all data written out to a buffer. When we close the ptty, we can // no longer read from the ptty.Output(), but we can read what was // written to the buffer. + dataRead, doneReading := context.WithTimeout(context.Background(), time.Second*2) go func() { - _, err := io.Copy(&buf, ptty.Output()) - require.NoError(t, err, "copy") + // This will throw an error sometimes. The underlying ptty + // has its own cleanup routines in t.Cleanup. Instead of + // trying to control the close perfectly, just let the ptty + // double close. This error isn't important, we just + // want to know the ptty is done sending output. + _, _ = io.Copy(&buf, ptty.Output()) + doneReading() }() doneChan := make(chan string) @@ -79,10 +84,14 @@ func TestPrompt(t *testing.T) { }() require.Equal(t, "yes", <-doneChan) - require.NoError(t, ptty.Close(), "close ptty") + // Close the reader to end the io.Copy + require.NoError(t, ptty.Close(), "close eof reader") + // Wait for the IO copy to finish + <-dataRead.Done() + // Timeout error means the output was hanging + require.ErrorIs(t, dataRead.Err(), context.Canceled, "should be cancelled") require.Len(t, buf.Bytes(), 0, "expect no output") }) - t.Run("JSON", func(t *testing.T) { t.Parallel() ptty := ptytest.New(t) @@ -104,7 +113,6 @@ func TestPrompt(t *testing.T) { ptty := ptytest.New(t) doneChan := make(chan string) go func() { - resp, err := newPrompt(ptty, cliui.PromptOptions{ Text: "Example", }, nil) From 843dd21daeae7f693ed889e4831e848577f8bf45 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 14:08:54 -0500 Subject: [PATCH 05/15] Add skip test for workspace create --- cli/create_test.go | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index b9746df993196..c8b416c8f84f3 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -46,7 +46,7 @@ func TestCreate(t *testing.T) { <-doneChan }) - t.Run("CreateFromList", func(t *testing.T) { + t.Run("CreateFromListWithSkip", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) @@ -54,7 +54,7 @@ func TestCreate(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) _ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - cmd, root := clitest.New(t, "create", "my-workspace") + cmd, root := clitest.New(t, "create", "my-workspace", "-y") clitest.SetupConfig(t, client, root) doneChan := make(chan struct{}) pty := ptytest.New(t) @@ -65,15 +65,7 @@ func TestCreate(t *testing.T) { err := cmd.Execute() require.NoError(t, err) }() - matches := []string{ - "Confirm create", "yes", - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) - pty.WriteLine(value) - } + // No pty interaction needed since we use the -y skip prompt flag <-doneChan }) From 9c09a084761a0032fab977d40671e82cabc88f0e Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 19 May 2022 14:53:29 -0500 Subject: [PATCH 06/15] Make test parallel --- cli/cliui/prompt_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/cliui/prompt_test.go b/cli/cliui/prompt_test.go index 4b83fe17449b5..d61c7d2eaabbd 100644 --- a/cli/cliui/prompt_test.go +++ b/cli/cliui/prompt_test.go @@ -53,6 +53,7 @@ func TestPrompt(t *testing.T) { }) t.Run("Skip", func(t *testing.T) { + t.Parallel() ptty := ptytest.New(t) var buf bytes.Buffer @@ -89,7 +90,7 @@ func TestPrompt(t *testing.T) { // Wait for the IO copy to finish <-dataRead.Done() // Timeout error means the output was hanging - require.ErrorIs(t, dataRead.Err(), context.Canceled, "should be cancelled") + require.ErrorIs(t, dataRead.Err(), context.Canceled, "should be canceled") require.Len(t, buf.Bytes(), 0, "expect no output") }) t.Run("JSON", func(t *testing.T) { From 6a4682a4d92de301255b0ef83921bcef59b7c999 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 08:42:50 -0500 Subject: [PATCH 07/15] Allow -y to template update --- cli/templateupdate.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/templateupdate.go b/cli/templateupdate.go index 70c2611cea687..32902aab3b518 100644 --- a/cli/templateupdate.go +++ b/cli/templateupdate.go @@ -108,6 +108,7 @@ func templateUpdate() *cobra.Command { currentDirectory, _ := os.Getwd() cmd.Flags().StringVarP(&directory, "directory", "d", currentDirectory, "Specify the directory to create from") cmd.Flags().StringVarP(&provisioner, "test.provisioner", "", "terraform", "Customize the provisioner backend") + cliui.AllowSkipPrompt(cmd) // This is for testing! err := cmd.Flags().MarkHidden("test.provisioner") if err != nil { From e334b22b452405e42c0d0a5e50550787125f2d11 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 09:14:09 -0500 Subject: [PATCH 08/15] Fix delete test --- cli/delete_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/delete_test.go b/cli/delete_test.go index f9e1102a0eb39..e7af61b40cd82 100644 --- a/cli/delete_test.go +++ b/cli/delete_test.go @@ -20,7 +20,7 @@ func TestDelete(t *testing.T) { template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) - cmd, root := clitest.New(t, "delete", workspace.Name) + cmd, root := clitest.New(t, "delete", workspace.Name, "-y") clitest.SetupConfig(t, client, root) doneChan := make(chan struct{}) pty := ptytest.New(t) From 2ecf6649e40ef8ba01868497baa7ded67c365a98 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:01:46 -0500 Subject: [PATCH 09/15] Do not use deprecated function --- cli/cliui/prompt_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/cliui/prompt_test.go b/cli/cliui/prompt_test.go index d61c7d2eaabbd..9c9167ad09708 100644 --- a/cli/cliui/prompt_test.go +++ b/cli/cliui/prompt_test.go @@ -157,7 +157,8 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions, cmdOpt func(cmd *cob if cmdOpt != nil { cmdOpt(cmd) } - cmd.SetOutput(ptty.Output()) + cmd.SetOut(ptty.Output()) + cmd.SetErr(ptty.Output()) cmd.SetIn(ptty.Input()) return value, cmd.ExecuteContext(context.Background()) } From e1b6bfb7e46186d470cf56e9d807ab6dfe70dfc7 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:17:15 -0500 Subject: [PATCH 10/15] Add timeout to cmd execute --- cli/create_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/create_test.go b/cli/create_test.go index 84117155d8fba..3d2790536f007 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -1,8 +1,10 @@ package cli_test import ( + "context" "fmt" "testing" + "time" "github.com/stretchr/testify/require" @@ -59,8 +61,10 @@ func TestCreate(t *testing.T) { cmd.SetIn(pty.Input()) cmd.SetOut(pty.Output()) go func() { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) + defer cancel() defer close(doneChan) - err := cmd.Execute() + err := cmd.ExecuteContext(ctx) require.NoError(t, err) }() // No pty interaction needed since we use the -y skip prompt flag From 0101e6d1be728d5a0aad2e948127a47320a8f007 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:29:03 -0500 Subject: [PATCH 11/15] revert test back to pre-skip --- cli/create_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 3d2790536f007..46b84d0bdbb3d 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -54,7 +54,7 @@ func TestCreate(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) _ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - cmd, root := clitest.New(t, "create", "my-workspace", "-y") + cmd, root := clitest.New(t, "create", "my-workspace") clitest.SetupConfig(t, client, root) doneChan := make(chan struct{}) pty := ptytest.New(t) @@ -67,7 +67,15 @@ func TestCreate(t *testing.T) { err := cmd.ExecuteContext(ctx) require.NoError(t, err) }() - // No pty interaction needed since we use the -y skip prompt flag + matches := []string{ + "Confirm create", "yes", + } + for i := 0; i < len(matches); i += 2 { + match := matches[i] + value := matches[i+1] + pty.ExpectMatch(match) + pty.WriteLine(value) + } <-doneChan }) From d31fbc26eb3b9efe6b1655351dae21f1b6097b31 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:30:37 -0500 Subject: [PATCH 12/15] Remove set input --- cli/create_test.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 46b84d0bdbb3d..61801025bb217 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -54,11 +54,10 @@ func TestCreate(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) _ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - cmd, root := clitest.New(t, "create", "my-workspace") + cmd, root := clitest.New(t, "create", "my-workspace", "-y") clitest.SetupConfig(t, client, root) doneChan := make(chan struct{}) pty := ptytest.New(t) - cmd.SetIn(pty.Input()) cmd.SetOut(pty.Output()) go func() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) @@ -67,15 +66,7 @@ func TestCreate(t *testing.T) { err := cmd.ExecuteContext(ctx) require.NoError(t, err) }() - matches := []string{ - "Confirm create", "yes", - } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) - pty.WriteLine(value) - } + // No pty interaction needed since we use the -y skip prompt flag <-doneChan }) From bed1d44600d34ad7080e3cbda0038ffd43993773 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:33:00 -0500 Subject: [PATCH 13/15] Do not use ptty --- cli/create_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 61801025bb217..6ea66d1ac1524 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -57,8 +57,8 @@ func TestCreate(t *testing.T) { cmd, root := clitest.New(t, "create", "my-workspace", "-y") clitest.SetupConfig(t, client, root) doneChan := make(chan struct{}) - pty := ptytest.New(t) - cmd.SetOut(pty.Output()) + //var output bytes.Buffer + //cmd.SetOut(&output) go func() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() From 9d527bd3cc058376d42f796b572b5b25c3d12c18 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:45:39 -0500 Subject: [PATCH 14/15] use ctx over don channel --- cli/create_test.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/cli/create_test.go b/cli/create_test.go index 6ea66d1ac1524..cd466cafa98a5 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -56,18 +56,15 @@ func TestCreate(t *testing.T) { _ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) cmd, root := clitest.New(t, "create", "my-workspace", "-y") clitest.SetupConfig(t, client, root) - doneChan := make(chan struct{}) - //var output bytes.Buffer - //cmd.SetOut(&output) + cmdCtx, done := context.WithTimeout(context.Background(), time.Second*3) go func() { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) - defer cancel() - defer close(doneChan) - err := cmd.ExecuteContext(ctx) + defer done() + err := cmd.ExecuteContext(cmdCtx) require.NoError(t, err) }() // No pty interaction needed since we use the -y skip prompt flag - <-doneChan + <-cmdCtx.Done() + require.ErrorIs(t, cmdCtx.Err(), context.Canceled) }) t.Run("FromNothing", func(t *testing.T) { From 7cdb06e68087f08724657a548e1a08d4eef7f4b9 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 10:47:59 -0500 Subject: [PATCH 15/15] Remove unused flag --- cli/templatecreate.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/templatecreate.go b/cli/templatecreate.go index aa84a0129db56..06205aa008eb2 100644 --- a/cli/templatecreate.go +++ b/cli/templatecreate.go @@ -21,7 +21,6 @@ import ( func templateCreate() *cobra.Command { var ( - yes bool directory string provisioner string parameterFile string