diff --git a/cli/create.go b/cli/create.go
index c9da10f49d..5ad4cbf317 100644
--- a/cli/create.go
+++ b/cli/create.go
@@ -46,6 +46,7 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
autoUpdates string
copyParametersFrom string
useParameterDefaults bool
+ noWait bool
// Organization context is only required if more than 1 template
// shares the same name across multiple organizations.
orgContext = NewOrganizationContext()
@@ -372,6 +373,14 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
cliutil.WarnMatchedProvisioners(inv.Stderr, workspace.LatestBuild.MatchedProvisioners, workspace.LatestBuild.Job)
+ if noWait {
+ _, _ = fmt.Fprintf(inv.Stdout,
+ "\nThe %s workspace has been created and is building in the background.\n",
+ cliui.Keyword(workspace.Name),
+ )
+ return nil
+ }
+
err = cliui.WorkspaceBuild(inv.Context(), inv.Stdout, client, workspace.LatestBuild.ID)
if err != nil {
return xerrors.Errorf("watch build: %w", err)
@@ -445,6 +454,12 @@ func (r *RootCmd) Create(opts CreateOptions) *serpent.Command {
Description: "Automatically accept parameter defaults when no value is provided.",
Value: serpent.BoolOf(&useParameterDefaults),
},
+ serpent.Option{
+ Flag: "no-wait",
+ Env: "CODER_CREATE_NO_WAIT",
+ Description: "Return immediately after creating the workspace. The build will run in the background.",
+ Value: serpent.BoolOf(&noWait),
+ },
cliui.SkipPromptOption(),
)
cmd.Options = append(cmd.Options, parameterFlags.cliParameters()...)
diff --git a/cli/create_test.go b/cli/create_test.go
index e97539b195..e7f387584e 100644
--- a/cli/create_test.go
+++ b/cli/create_test.go
@@ -603,6 +603,81 @@ func TestCreate(t *testing.T) {
assert.Nil(t, ws.AutostartSchedule, "expected workspace autostart schedule to be nil")
}
})
+
+ t.Run("NoWait", func(t *testing.T) {
+ t.Parallel()
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ owner := coderdtest.CreateFirstUser(t, client)
+ member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
+
+ ctx := testutil.Context(t, testutil.WaitLong)
+ inv, root := clitest.New(t, "create", "my-workspace",
+ "--template", template.Name,
+ "-y",
+ "--no-wait",
+ )
+ clitest.SetupConfig(t, member, root)
+ doneChan := make(chan struct{})
+ pty := ptytest.New(t).Attach(inv)
+ go func() {
+ defer close(doneChan)
+ err := inv.Run()
+ assert.NoError(t, err)
+ }()
+
+ pty.ExpectMatchContext(ctx, "building in the background")
+ _ = testutil.TryReceive(ctx, t, doneChan)
+
+ // Verify workspace was actually created.
+ ws, err := member.WorkspaceByOwnerAndName(ctx, codersdk.Me, "my-workspace", codersdk.WorkspaceOptions{})
+ require.NoError(t, err)
+ assert.Equal(t, ws.TemplateName, template.Name)
+ })
+
+ t.Run("NoWaitWithParameterDefaults", func(t *testing.T) {
+ t.Parallel()
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ owner := coderdtest.CreateFirstUser(t, client)
+ member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, prepareEchoResponses([]*proto.RichParameter{
+ {Name: "region", Type: "string", DefaultValue: "us-east-1"},
+ {Name: "instance_type", Type: "string", DefaultValue: "t3.micro"},
+ }))
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
+
+ ctx := testutil.Context(t, testutil.WaitLong)
+ inv, root := clitest.New(t, "create", "my-workspace",
+ "--template", template.Name,
+ "-y",
+ "--use-parameter-defaults",
+ "--no-wait",
+ )
+ clitest.SetupConfig(t, member, root)
+ doneChan := make(chan struct{})
+ pty := ptytest.New(t).Attach(inv)
+ go func() {
+ defer close(doneChan)
+ err := inv.Run()
+ assert.NoError(t, err)
+ }()
+
+ pty.ExpectMatchContext(ctx, "building in the background")
+ _ = testutil.TryReceive(ctx, t, doneChan)
+
+ // Verify workspace was created and parameters were applied.
+ ws, err := member.WorkspaceByOwnerAndName(ctx, codersdk.Me, "my-workspace", codersdk.WorkspaceOptions{})
+ require.NoError(t, err)
+ assert.Equal(t, ws.TemplateName, template.Name)
+
+ buildParams, err := member.WorkspaceBuildParameters(ctx, ws.LatestBuild.ID)
+ require.NoError(t, err)
+ assert.Contains(t, buildParams, codersdk.WorkspaceBuildParameter{Name: "region", Value: "us-east-1"})
+ assert.Contains(t, buildParams, codersdk.WorkspaceBuildParameter{Name: "instance_type", Value: "t3.micro"})
+ })
}
func prepareEchoResponses(parameters []*proto.RichParameter, presets ...*proto.Preset) *echo.Responses {
diff --git a/cli/testdata/coder_create_--help.golden b/cli/testdata/coder_create_--help.golden
index 1292af1777..b1f5968c7a 100644
--- a/cli/testdata/coder_create_--help.golden
+++ b/cli/testdata/coder_create_--help.golden
@@ -20,6 +20,10 @@ OPTIONS:
--copy-parameters-from string, $CODER_WORKSPACE_COPY_PARAMETERS_FROM
Specify the source workspace name to copy parameters from.
+ --no-wait bool, $CODER_CREATE_NO_WAIT
+ Return immediately after creating the workspace. The build will run in
+ the background.
+
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".
diff --git a/docs/reference/cli/create.md b/docs/reference/cli/create.md
index c3a2cbe352..0b13a4c94b 100644
--- a/docs/reference/cli/create.md
+++ b/docs/reference/cli/create.md
@@ -92,6 +92,15 @@ Specify the source workspace name to copy parameters from.
Automatically accept parameter defaults when no value is provided.
+### --no-wait
+
+| | |
+|-------------|------------------------------------|
+| Type | bool |
+| Environment | $CODER_CREATE_NO_WAIT |
+
+Return immediately after creating the workspace. The build will run in the background.
+
### -y, --yes
| | |
diff --git a/docs/reference/cli/external-workspaces_create.md b/docs/reference/cli/external-workspaces_create.md
index 6d1f21df8f..86a33c2e48 100644
--- a/docs/reference/cli/external-workspaces_create.md
+++ b/docs/reference/cli/external-workspaces_create.md
@@ -92,6 +92,15 @@ Specify the source workspace name to copy parameters from.
Automatically accept parameter defaults when no value is provided.
+### --no-wait
+
+| | |
+|-------------|------------------------------------|
+| Type | bool |
+| Environment | $CODER_CREATE_NO_WAIT |
+
+Return immediately after creating the workspace. The build will run in the background.
+
### -y, --yes
| | |
diff --git a/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden b/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden
index 9ec3834235..6f33cda59b 100644
--- a/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden
+++ b/enterprise/cli/testdata/coder_external-workspaces_create_--help.golden
@@ -20,6 +20,10 @@ OPTIONS:
--copy-parameters-from string, $CODER_WORKSPACE_COPY_PARAMETERS_FROM
Specify the source workspace name to copy parameters from.
+ --no-wait bool, $CODER_CREATE_NO_WAIT
+ Return immediately after creating the workspace. The build will run in
+ the background.
+
--parameter string-array, $CODER_RICH_PARAMETER
Rich parameter value in the format "name=value".