Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit836324e

Browse files
authored
feat(cli): add coder exp tasks list (#19496)
Fixescoder/internal#892Fixescoder/internal#896Example output:```❯ coder exp task listID NAME STATUS STATE STATE CHANGED MESSAGEa7a27450-ca16-4553-a6c5-9d6f04808569 task-hardcore-herschel-bd08 running idle 5h22m3s ago Listed root directory contents, working directory reset50f92138-f463-4f2b-abad-1816264b065f task-musing-dewdney-f058 running idle 6h3m8s ago Completed arithmetic calculation```
1 parentcef2904 commit836324e

File tree

7 files changed

+474
-23
lines changed

7 files changed

+474
-23
lines changed

‎cli/exp.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func (r *RootCmd) expCmd() *serpent.Command {
1616
r.mcpCommand(),
1717
r.promptExample(),
1818
r.rptyCommand(),
19+
r.tasksCommand(),
1920
},
2021
}
2122
returncmd

‎cli/exp_task.go‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cli
2+
3+
import (
4+
"github.com/coder/serpent"
5+
)
6+
7+
func (r*RootCmd)tasksCommand()*serpent.Command {
8+
cmd:=&serpent.Command{
9+
Use:"task",
10+
Aliases: []string{"tasks"},
11+
Short:"Experimental task commands.",
12+
Handler:func(i*serpent.Invocation)error {
13+
returni.Command.HelpHandler(i)
14+
},
15+
Children: []*serpent.Command{
16+
r.taskList(),
17+
},
18+
}
19+
returncmd
20+
}

‎cli/exp_tasklist.go‎

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"time"
7+
8+
"golang.org/x/xerrors"
9+
10+
"github.com/coder/coder/v2/cli/cliui"
11+
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/serpent"
13+
)
14+
15+
typetaskListRowstruct {
16+
Task codersdk.Task`table:"t,recursive_inline"`
17+
18+
StateChangedAgostring`table:"state changed"`
19+
}
20+
21+
functaskListRowFromTask(now time.Time,t codersdk.Task)taskListRow {
22+
varstateAgostring
23+
ift.CurrentState!=nil {
24+
stateAgo=now.UTC().Sub(t.CurrentState.Timestamp).Truncate(time.Second).String()+" ago"
25+
}
26+
27+
returntaskListRow{
28+
Task:t,
29+
30+
StateChangedAgo:stateAgo,
31+
}
32+
}
33+
34+
func (r*RootCmd)taskList()*serpent.Command {
35+
var (
36+
statusFilterstring
37+
allbool
38+
userstring
39+
40+
client=new(codersdk.Client)
41+
formatter=cliui.NewOutputFormatter(
42+
cliui.TableFormat(
43+
[]taskListRow{},
44+
[]string{
45+
"id",
46+
"name",
47+
"status",
48+
"state",
49+
"state changed",
50+
"message",
51+
},
52+
),
53+
cliui.ChangeFormatterData(
54+
cliui.JSONFormat(),
55+
func(dataany) (any,error) {
56+
rows,ok:=data.([]taskListRow)
57+
if!ok {
58+
returnnil,xerrors.Errorf("expected []taskListRow, got %T",data)
59+
}
60+
out:=make([]codersdk.Task,len(rows))
61+
fori:=rangerows {
62+
out[i]=rows[i].Task
63+
}
64+
returnout,nil
65+
},
66+
),
67+
)
68+
)
69+
70+
cmd:=&serpent.Command{
71+
Use:"list",
72+
Short:"List experimental tasks",
73+
Aliases: []string{"ls"},
74+
Middleware:serpent.Chain(
75+
serpent.RequireNArgs(0),
76+
r.InitClient(client),
77+
),
78+
Options: serpent.OptionSet{
79+
{
80+
Name:"status",
81+
Description:"Filter by task status (e.g. running, failed, etc).",
82+
Flag:"status",
83+
Default:"",
84+
Value:serpent.StringOf(&statusFilter),
85+
},
86+
{
87+
Name:"all",
88+
Description:"List tasks for all users you can view.",
89+
Flag:"all",
90+
FlagShorthand:"a",
91+
Default:"false",
92+
Value:serpent.BoolOf(&all),
93+
},
94+
{
95+
Name:"user",
96+
Description:"List tasks for the specified user (username,\"me\").",
97+
Flag:"user",
98+
Default:"",
99+
Value:serpent.StringOf(&user),
100+
},
101+
},
102+
Handler:func(inv*serpent.Invocation)error {
103+
ctx:=inv.Context()
104+
exp:=codersdk.NewExperimentalClient(client)
105+
106+
targetUser:=strings.TrimSpace(user)
107+
iftargetUser==""&&!all {
108+
targetUser=codersdk.Me
109+
}
110+
111+
tasks,err:=exp.Tasks(ctx,&codersdk.TasksFilter{
112+
Owner:targetUser,
113+
Status:statusFilter,
114+
})
115+
iferr!=nil {
116+
returnxerrors.Errorf("list tasks: %w",err)
117+
}
118+
119+
// If no rows and not JSON, show a friendly message.
120+
iflen(tasks)==0&&formatter.FormatID()!=cliui.JSONFormat().ID() {
121+
_,_=fmt.Fprintln(inv.Stderr,"No tasks found.")
122+
returnnil
123+
}
124+
125+
rows:=make([]taskListRow,len(tasks))
126+
now:=time.Now()
127+
fori:=rangetasks {
128+
rows[i]=taskListRowFromTask(now,tasks[i])
129+
}
130+
131+
out,err:=formatter.Format(ctx,rows)
132+
iferr!=nil {
133+
returnxerrors.Errorf("format tasks: %w",err)
134+
}
135+
_,_=fmt.Fprintln(inv.Stdout,out)
136+
returnnil
137+
},
138+
}
139+
140+
formatter.AttachOptions(&cmd.Options)
141+
returncmd
142+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp