Skip to content

Commit 6d0558e

Browse files
authored
Merge branch 'main' into aqandrew/coder-app-hostname-too-long-error
2 parents bf0c8d1 + 9b7d41d commit 6d0558e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1716
-297
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trim_trailing_whitespace = true
77
insert_final_newline = true
88
indent_style = tab
99

10-
[*.{yaml,yml,tf,tfvars,nix}]
10+
[*.{yaml,yml,tf,tftpl,tfvars,nix}]
1111
indent_style = space
1212
indent_size = 2
1313

.github/actions/setup-tf/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ runs:
77
- name: Install Terraform
88
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
99
with:
10-
terraform_version: 1.12.2
10+
terraform_version: 1.13.0
1111
terraform_wrapper: false

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
return cmd

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+
return i.Command.HelpHandler(i)
14+
},
15+
Children: []*serpent.Command{
16+
r.taskList(),
17+
},
18+
}
19+
return cmd
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+
type taskListRow struct {
16+
Task codersdk.Task `table:"t,recursive_inline"`
17+
18+
StateChangedAgo string `table:"state changed"`
19+
}
20+
21+
func taskListRowFromTask(now time.Time, t codersdk.Task) taskListRow {
22+
var stateAgo string
23+
if t.CurrentState != nil {
24+
stateAgo = now.UTC().Sub(t.CurrentState.Timestamp).Truncate(time.Second).String() + " ago"
25+
}
26+
27+
return taskListRow{
28+
Task: t,
29+
30+
StateChangedAgo: stateAgo,
31+
}
32+
}
33+
34+
func (r *RootCmd) taskList() *serpent.Command {
35+
var (
36+
statusFilter string
37+
all bool
38+
user string
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(data any) (any, error) {
56+
rows, ok := data.([]taskListRow)
57+
if !ok {
58+
return nil, xerrors.Errorf("expected []taskListRow, got %T", data)
59+
}
60+
out := make([]codersdk.Task, len(rows))
61+
for i := range rows {
62+
out[i] = rows[i].Task
63+
}
64+
return out, 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+
if targetUser == "" && !all {
108+
targetUser = codersdk.Me
109+
}
110+
111+
tasks, err := exp.Tasks(ctx, &codersdk.TasksFilter{
112+
Owner: targetUser,
113+
Status: statusFilter,
114+
})
115+
if err != nil {
116+
return xerrors.Errorf("list tasks: %w", err)
117+
}
118+
119+
// If no rows and not JSON, show a friendly message.
120+
if len(tasks) == 0 && formatter.FormatID() != cliui.JSONFormat().ID() {
121+
_, _ = fmt.Fprintln(inv.Stderr, "No tasks found.")
122+
return nil
123+
}
124+
125+
rows := make([]taskListRow, len(tasks))
126+
now := time.Now()
127+
for i := range tasks {
128+
rows[i] = taskListRowFromTask(now, tasks[i])
129+
}
130+
131+
out, err := formatter.Format(ctx, rows)
132+
if err != nil {
133+
return xerrors.Errorf("format tasks: %w", err)
134+
}
135+
_, _ = fmt.Fprintln(inv.Stdout, out)
136+
return nil
137+
},
138+
}
139+
140+
formatter.AttachOptions(&cmd.Options)
141+
return cmd
142+
}

0 commit comments

Comments
 (0)