Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/exp.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func (r *RootCmd) expCmd() *serpent.Command {
r.mcpCommand(),
r.promptExample(),
r.rptyCommand(),
r.tasksCommand(),
},
}
return cmd
Expand Down
20 changes: 20 additions & 0 deletions cli/exp_task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cli

import (
"github.com/coder/serpent"
)

func (r *RootCmd) tasksCommand() *serpent.Command {
cmd := &serpent.Command{
Use: "task",
Aliases: []string{"tasks"},
Short: "Experimental task commands.",
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
Children: []*serpent.Command{
r.taskList(),
},
}
return cmd
}
142 changes: 142 additions & 0 deletions cli/exp_tasklist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package cli

import (
"fmt"
"strings"
"time"

"golang.org/x/xerrors"

"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)

type taskListRow struct {
Task codersdk.Task `table:"t,recursive_inline"`

StateChanged string `table:"state changed"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: suggest naming StateChangedAt or similar so that the semantics are clearer

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is relative, how about StateChangeAgo?

}

func taskListRowFromTask(now time.Time, t codersdk.Task) taskListRow {
var stateAgo string
if t.CurrentState != nil {
stateAgo = now.UTC().Sub(t.CurrentState.Timestamp).Truncate(time.Second).String() + " ago"
}

return taskListRow{
Task: t,

StateChanged: stateAgo,
}
}

func (r *RootCmd) taskList() *serpent.Command {
var (
statusFilter string
all bool
user string

client = new(codersdk.Client)
formatter = cliui.NewOutputFormatter(
cliui.TableFormat(
[]taskListRow{},
[]string{
"id",
"name",
"status",
"state",
"state changed",
"message",
},
),
cliui.ChangeFormatterData(
cliui.JSONFormat(),
func(data any) (any, error) {
rows, ok := data.([]taskListRow)
if !ok {
return nil, xerrors.Errorf("expected []taskListRow, got %T", data)
}
out := make([]codersdk.Task, len(rows))
for i := range rows {
out[i] = rows[i].Task
}
return out, nil
},
),
)
)

cmd := &serpent.Command{
Use: "list",
Short: "List experimental tasks",
Aliases: []string{"ls"},
Middleware: serpent.Chain(
serpent.RequireNArgs(0),
r.InitClient(client),
),
Options: serpent.OptionSet{
{
Name: "status",
Description: "Filter by task status (e.g. running, failed, etc).",
Flag: "status",
Default: "",
Value: serpent.StringOf(&statusFilter),
},
{
Name: "all",
Description: "List tasks for all users you can view.",
Flag: "all",
FlagShorthand: "a",
Default: "false",
Value: serpent.BoolOf(&all),
},
{
Name: "user",
Description: "List tasks for the specified user (username, \"me\").",
Flag: "user",
Default: "",
Value: serpent.StringOf(&user),
},
},
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
exp := codersdk.NewExperimentalClient(client)

targetUser := strings.TrimSpace(user)
if targetUser == "" && !all {
targetUser = codersdk.Me
}

tasks, err := exp.Tasks(ctx, &codersdk.TasksFilter{
Owner: targetUser,
Status: statusFilter,
})
if err != nil {
return xerrors.Errorf("list tasks: %w", err)
}

// If no rows and not JSON, show a friendly message.
if len(tasks) == 0 && formatter.FormatID() != cliui.JSONFormat().ID() {
_, _ = fmt.Fprintln(inv.Stderr, "No tasks found.")
return nil
}

rows := make([]taskListRow, len(tasks))
now := time.Now()
for i := range tasks {
rows[i] = taskListRowFromTask(now, tasks[i])
}

out, err := formatter.Format(ctx, rows)
if err != nil {
return xerrors.Errorf("format tasks: %w", err)
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
},
}

formatter.AttachOptions(&cmd.Options)
return cmd
}
Loading
Loading