Skip to content

Commit ad8ba4a

Browse files
authored
feat(cli): promote tasks commands from experimental to GA (#20916)
## Overview This change promotes the tasks CLI commands from `coder exp task` to `coder task`, marking them as generally available (GA). ## Migration Users will need to update their scripts from: ```shell coder exp task create "my task" ``` To: ```shell coder task create "my task" ``` --- 🤖 This change was written by Claude Sonnet 4.5 Thinking using [mux](https://github.com/coder/mux) and reviewed by a human 🏄🏻‍♂️
1 parent 3011207 commit ad8ba4a

33 files changed

+697
-277
lines changed

cli/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ func (r *RootCmd) CoreSubcommands() []*serpent.Command {
104104
r.resetPassword(),
105105
r.sharing(),
106106
r.state(),
107+
r.tasksCommand(),
107108
r.templates(),
108109
r.tokens(),
109110
r.users(),
@@ -149,7 +150,6 @@ func (r *RootCmd) AGPLExperimental() []*serpent.Command {
149150
r.mcpCommand(),
150151
r.promptExample(),
151152
r.rptyCommand(),
152-
r.tasksCommand(),
153153
r.boundary(),
154154
}
155155
}

cli/exp_task.go renamed to cli/task.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ func (r *RootCmd) tasksCommand() *serpent.Command {
88
cmd := &serpent.Command{
99
Use: "task",
1010
Aliases: []string{"tasks"},
11-
Short: "Experimental task commands.",
11+
Short: "Manage tasks",
1212
Handler: func(i *serpent.Invocation) error {
1313
return i.Command.HelpHandler(i)
1414
},
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,27 @@ func (r *RootCmd) taskCreate() *serpent.Command {
2828

2929
cmd := &serpent.Command{
3030
Use: "create [input]",
31-
Short: "Create an experimental task",
31+
Short: "Create a task",
3232
Long: FormatExamples(
3333
Example{
3434
Description: "Create a task with direct input",
35-
Command: "coder exp task create \"Add authentication to the user service\"",
35+
Command: "coder task create \"Add authentication to the user service\"",
3636
},
3737
Example{
3838
Description: "Create a task with stdin input",
39-
Command: "echo \"Add authentication to the user service\" | coder exp task create",
39+
Command: "echo \"Add authentication to the user service\" | coder task create",
4040
},
4141
Example{
4242
Description: "Create a task with a specific name",
43-
Command: "coder exp task create --name task1 \"Add authentication to the user service\"",
43+
Command: "coder task create --name task1 \"Add authentication to the user service\"",
4444
},
4545
Example{
4646
Description: "Create a task from a specific template / preset",
47-
Command: "coder exp task create --template backend-dev --preset \"My Preset\" \"Add authentication to the user service\"",
47+
Command: "coder task create --template backend-dev --preset \"My Preset\" \"Add authentication to the user service\"",
4848
},
4949
Example{
5050
Description: "Create a task for another user (requires appropriate permissions)",
51-
Command: "coder exp task create --owner user@example.com \"Add authentication to the user service\"",
51+
Command: "coder task create --owner user@example.com \"Add authentication to the user service\"",
5252
},
5353
),
5454
Middleware: serpent.Chain(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ func TestTaskCreate(t *testing.T) {
329329
ctx = testutil.Context(t, testutil.WaitShort)
330330
srv = httptest.NewServer(tt.handler(t, ctx))
331331
client = codersdk.New(testutil.MustURL(t, srv.URL))
332-
args = []string{"exp", "task", "create"}
332+
args = []string{"task", "create"}
333333
sb strings.Builder
334334
err error
335335
)
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ import (
1717
func (r *RootCmd) taskDelete() *serpent.Command {
1818
cmd := &serpent.Command{
1919
Use: "delete <task> [<task> ...]",
20-
Short: "Delete experimental tasks",
20+
Short: "Delete tasks",
2121
Long: FormatExamples(
2222
Example{
2323
Description: "Delete a single task.",
24-
Command: "$ coder exp task delete task1",
24+
Command: "$ coder task delete task1",
2525
},
2626
Example{
2727
Description: "Delete multiple tasks.",
28-
Command: "$ coder exp task delete task1 task2 task3",
28+
Command: "$ coder task delete task1 task2 task3",
2929
},
3030
Example{
3131
Description: "Delete a task without confirmation.",
32-
Command: "$ coder exp task delete task4 --yes",
32+
Command: "$ coder task delete task4 --yes",
3333
},
3434
),
3535
Middleware: serpent.Chain(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func TestExpTaskDelete(t *testing.T) {
193193

194194
client := codersdk.New(testutil.MustURL(t, srv.URL))
195195

196-
args := append([]string{"exp", "task", "delete"}, tc.args...)
196+
args := append([]string{"task", "delete"}, tc.args...)
197197
inv, root := clitest.New(t, args...)
198198
inv = inv.WithContext(ctx)
199199
clitest.SetupConfig(t, client, root)
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,27 +69,27 @@ func (r *RootCmd) taskList() *serpent.Command {
6969

7070
cmd := &serpent.Command{
7171
Use: "list",
72-
Short: "List experimental tasks",
72+
Short: "List tasks",
7373
Long: FormatExamples(
7474
Example{
7575
Description: "List tasks for the current user.",
76-
Command: "coder exp task list",
76+
Command: "coder task list",
7777
},
7878
Example{
7979
Description: "List tasks for a specific user.",
80-
Command: "coder exp task list --user someone-else",
80+
Command: "coder task list --user someone-else",
8181
},
8282
Example{
8383
Description: "List all tasks you can view.",
84-
Command: "coder exp task list --all",
84+
Command: "coder task list --all",
8585
},
8686
Example{
8787
Description: "List all your running tasks.",
88-
Command: "coder exp task list --status running",
88+
Command: "coder task list --status running",
8989
},
9090
Example{
9191
Description: "As above, but only show IDs.",
92-
Command: "coder exp task list --status running --quiet",
92+
Command: "coder task list --status running --quiet",
9393
},
9494
),
9595
Aliases: []string{"ls"},
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func TestExpTaskList(t *testing.T) {
6969
owner := coderdtest.CreateFirstUser(t, client)
7070
memberClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
7171

72-
inv, root := clitest.New(t, "exp", "task", "list")
72+
inv, root := clitest.New(t, "task", "list")
7373
clitest.SetupConfig(t, memberClient, root)
7474

7575
pty := ptytest.New(t).Attach(inv)
@@ -93,7 +93,7 @@ func TestExpTaskList(t *testing.T) {
9393
wantPrompt := "build me a web app"
9494
task := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStart, wantPrompt)
9595

96-
inv, root := clitest.New(t, "exp", "task", "list", "--column", "id,name,status,initial prompt")
96+
inv, root := clitest.New(t, "task", "list", "--column", "id,name,status,initial prompt")
9797
clitest.SetupConfig(t, memberClient, root)
9898

9999
pty := ptytest.New(t).Attach(inv)
@@ -122,7 +122,7 @@ func TestExpTaskList(t *testing.T) {
122122
pausedTask := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStop, "stop me please")
123123

124124
// Use JSON output to reliably validate filtering.
125-
inv, root := clitest.New(t, "exp", "task", "list", "--status=paused", "--output=json")
125+
inv, root := clitest.New(t, "task", "list", "--status=paused", "--output=json")
126126
clitest.SetupConfig(t, memberClient, root)
127127

128128
ctx := testutil.Context(t, testutil.WaitShort)
@@ -153,7 +153,7 @@ func TestExpTaskList(t *testing.T) {
153153
_ = makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStart, "other-task")
154154
task := makeAITask(t, db, owner.OrganizationID, owner.UserID, owner.UserID, database.WorkspaceTransitionStart, "me-task")
155155

156-
inv, root := clitest.New(t, "exp", "task", "list", "--user", "me")
156+
inv, root := clitest.New(t, "task", "list", "--user", "me")
157157
//nolint:gocritic // Owner client is intended here smoke test the member task not showing up.
158158
clitest.SetupConfig(t, client, root)
159159

@@ -180,7 +180,7 @@ func TestExpTaskList(t *testing.T) {
180180
task2 := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStop, "stop me please")
181181

182182
// Given: We add the `--quiet` flag
183-
inv, root := clitest.New(t, "exp", "task", "list", "--quiet")
183+
inv, root := clitest.New(t, "task", "list", "--quiet")
184184
clitest.SetupConfig(t, memberClient, root)
185185

186186
ctx := testutil.Context(t, testutil.WaitShort)
@@ -224,7 +224,7 @@ func TestExpTaskList_OwnerCanListOthers(t *testing.T) {
224224
t.Parallel()
225225

226226
// As the owner, list only member A tasks.
227-
inv, root := clitest.New(t, "exp", "task", "list", "--user", memberAUser.Username, "--output=json")
227+
inv, root := clitest.New(t, "task", "list", "--user", memberAUser.Username, "--output=json")
228228
//nolint:gocritic // Owner client is intended here to allow member tasks to be listed.
229229
clitest.SetupConfig(t, ownerClient, root)
230230

@@ -252,7 +252,7 @@ func TestExpTaskList_OwnerCanListOthers(t *testing.T) {
252252

253253
// As the owner, list all tasks to verify both member tasks are present.
254254
// Use JSON output to reliably validate filtering.
255-
inv, root := clitest.New(t, "exp", "task", "list", "--all", "--output=json")
255+
inv, root := clitest.New(t, "task", "list", "--all", "--output=json")
256256
//nolint:gocritic // Owner client is intended here to allow all tasks to be listed.
257257
clitest.SetupConfig(t, ownerClient, root)
258258

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (r *RootCmd) taskLogs() *serpent.Command {
2828
Long: FormatExamples(
2929
Example{
3030
Description: "Show logs for a given task.",
31-
Command: "coder exp task logs task1",
31+
Command: "coder task logs task1",
3232
}),
3333
Middleware: serpent.Chain(
3434
serpent.RequireNArgs(1),
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func Test_TaskLogs(t *testing.T) {
4646
userClient := client // user already has access to their own workspace
4747

4848
var stdout strings.Builder
49-
inv, root := clitest.New(t, "exp", "task", "logs", task.Name, "--output", "json")
49+
inv, root := clitest.New(t, "task", "logs", task.Name, "--output", "json")
5050
inv.Stdout = &stdout
5151
clitest.SetupConfig(t, userClient, root)
5252

@@ -72,7 +72,7 @@ func Test_TaskLogs(t *testing.T) {
7272
userClient := client
7373

7474
var stdout strings.Builder
75-
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String(), "--output", "json")
75+
inv, root := clitest.New(t, "task", "logs", task.ID.String(), "--output", "json")
7676
inv.Stdout = &stdout
7777
clitest.SetupConfig(t, userClient, root)
7878

@@ -98,7 +98,7 @@ func Test_TaskLogs(t *testing.T) {
9898
userClient := client
9999

100100
var stdout strings.Builder
101-
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String())
101+
inv, root := clitest.New(t, "task", "logs", task.ID.String())
102102
inv.Stdout = &stdout
103103
clitest.SetupConfig(t, userClient, root)
104104

@@ -121,7 +121,7 @@ func Test_TaskLogs(t *testing.T) {
121121
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
122122

123123
var stdout strings.Builder
124-
inv, root := clitest.New(t, "exp", "task", "logs", "doesnotexist")
124+
inv, root := clitest.New(t, "task", "logs", "doesnotexist")
125125
inv.Stdout = &stdout
126126
clitest.SetupConfig(t, userClient, root)
127127

@@ -139,7 +139,7 @@ func Test_TaskLogs(t *testing.T) {
139139
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
140140

141141
var stdout strings.Builder
142-
inv, root := clitest.New(t, "exp", "task", "logs", uuid.Nil.String())
142+
inv, root := clitest.New(t, "task", "logs", uuid.Nil.String())
143143
inv.Stdout = &stdout
144144
clitest.SetupConfig(t, userClient, root)
145145

@@ -155,7 +155,7 @@ func Test_TaskLogs(t *testing.T) {
155155
client, task := setupCLITaskTest(ctx, t, fakeAgentAPITaskLogsErr(assert.AnError))
156156
userClient := client
157157

158-
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String())
158+
inv, root := clitest.New(t, "task", "logs", task.ID.String())
159159
clitest.SetupConfig(t, userClient, root)
160160

161161
err := inv.WithContext(ctx).Run()

0 commit comments

Comments
 (0)