diff --git a/commands/history/ls.go b/commands/history/ls.go index 9153d8fca094..c79d73740058 100644 --- a/commands/history/ls.go +++ b/commands/history/ls.go @@ -18,6 +18,7 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/formatter" + cliflags "github.com/docker/cli/cli/flags" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -31,7 +32,7 @@ const ( lsHeaderDuration = "DURATION" lsHeaderLink = "" - lsDefaultTableFormat = "table {{.Ref}}\t{{.Name}}\t{{.Status}}\t{{.CreatedAt}}\t{{.Duration}}\t{{.Link}}" + lsDefaultTableFormat = "table {{.BuildID}}\t{{.Name}}\t{{.Status}}\t{{.Created}}\t{{.Duration}}\t{{.Link}}" headerKeyTimestamp = "buildkit-current-timestamp" ) @@ -51,7 +52,7 @@ func runLs(ctx context.Context, dockerCli command.Cli, opts lsOptions) error { return err } - queryOptions := &queryOptions{} + queryOpts := &queryOptions{} if opts.local { wd, err := os.Getwd() @@ -69,11 +70,11 @@ func runLs(ctx context.Context, dockerCli command.Cli, opts lsOptions) error { if err != nil { return errors.Wrapf(err, "could not get remote URL for local filter") } - queryOptions.Filters = append(queryOptions.Filters, fmt.Sprintf("repository=%s", remote)) + queryOpts.Filters = append(queryOpts.Filters, fmt.Sprintf("repository=%s", remote)) } - queryOptions.Filters = append(queryOptions.Filters, opts.filters...) + queryOpts.Filters = append(queryOpts.Filters, opts.filters...) - out, err := queryRecords(ctx, "", nodes, queryOptions) + out, err := queryRecords(ctx, "", nodes, queryOpts) if err != nil { return err } @@ -108,7 +109,7 @@ func lsCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command { } flags := cmd.Flags() - flags.StringVar(&options.format, "format", formatter.TableFormatKey, "Format the output") + flags.StringVar(&options.format, "format", formatter.TableFormatKey, cliflags.FormatHelp) flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") flags.StringArrayVar(&options.filters, "filter", nil, `Provide filter values (e.g., "status=error")`) flags.BoolVar(&options.local, "local", false, "List records for current repository only") @@ -144,10 +145,10 @@ func lsPrint(dockerCli command.Cli, records []historyRecord, in lsOptions) error render := func(format func(subContext formatter.SubContext) error) error { for _, r := range records { if err := format(&lsContext{ - format: formatter.Format(in.format), - isTerm: term, - trunc: !in.noTrunc, - record: &r, + format: formatter.Format(in.format), + isTerm: term, + trunc: !in.noTrunc, + historyRecord: &r, }); err != nil { return err } @@ -160,12 +161,12 @@ func lsPrint(dockerCli command.Cli, records []historyRecord, in lsOptions) error trunc: !in.noTrunc, } lsCtx.Header = formatter.SubHeaderContext{ - "Ref": lsHeaderBuildID, - "Name": lsHeaderName, - "Status": lsHeaderStatus, - "CreatedAt": lsHeaderCreated, - "Duration": lsHeaderDuration, - "Link": lsHeaderLink, + "BuildID": lsHeaderBuildID, + "Name": lsHeaderName, + "Status": lsHeaderStatus, + "Created": lsHeaderCreated, + "Duration": lsHeaderDuration, + "Link": lsHeaderLink, } return ctx.Write(&lsCtx, render) @@ -177,7 +178,7 @@ type lsContext struct { isTerm bool trunc bool format formatter.Format - record *historyRecord + *historyRecord } func (c *lsContext) MarshalJSON() ([]byte, error) { @@ -185,27 +186,27 @@ func (c *lsContext) MarshalJSON() ([]byte, error) { "ref": c.FullRef(), "name": c.Name(), "status": c.Status(), - "created_at": c.record.CreatedAt.AsTime().Format(time.RFC3339Nano), - "total_steps": c.record.NumTotalSteps, - "completed_steps": c.record.NumCompletedSteps, - "cached_steps": c.record.NumCachedSteps, + "created_at": c.CreatedAt.AsTime().Format(time.RFC3339Nano), + "total_steps": c.NumTotalSteps, + "completed_steps": c.NumCompletedSteps, + "cached_steps": c.NumCachedSteps, } - if c.record.CompletedAt != nil { - m["completed_at"] = c.record.CompletedAt.AsTime().Format(time.RFC3339Nano) + if c.CompletedAt != nil { + m["completed_at"] = c.CompletedAt.AsTime().Format(time.RFC3339Nano) } return json.Marshal(m) } -func (c *lsContext) Ref() string { - return c.record.Ref +func (c *lsContext) BuildID() string { + return c.Ref } func (c *lsContext) FullRef() string { - return fmt.Sprintf("%s/%s/%s", c.record.node.Builder, c.record.node.Name, c.record.Ref) + return fmt.Sprintf("%s/%s/%s", c.node.Builder, c.node.Name, c.Ref) } func (c *lsContext) Name() string { - name := c.record.name + name := c.name if c.trunc && c.format.IsTable() { return trimBeginning(name, 36) } @@ -213,8 +214,8 @@ func (c *lsContext) Name() string { } func (c *lsContext) Status() string { - if c.record.CompletedAt != nil { - if c.record.Error != nil { + if c.CompletedAt != nil { + if c.Error != nil { return "Error" } return "Completed" @@ -222,21 +223,21 @@ func (c *lsContext) Status() string { return "Running" } -func (c *lsContext) CreatedAt() string { - return units.HumanDuration(time.Since(c.record.CreatedAt.AsTime())) + " ago" +func (c *lsContext) Created() string { + return units.HumanDuration(time.Since(c.CreatedAt.AsTime())) + " ago" } func (c *lsContext) Duration() string { - lastTime := c.record.currentTimestamp - if c.record.CompletedAt != nil { - tm := c.record.CompletedAt.AsTime() + lastTime := c.currentTimestamp + if c.CompletedAt != nil { + tm := c.CompletedAt.AsTime() lastTime = &tm } if lastTime == nil { return "" } - v := formatDuration(lastTime.Sub(c.record.CreatedAt.AsTime())) - if c.record.CompletedAt == nil { + v := formatDuration(lastTime.Sub(c.CreatedAt.AsTime())) + if c.CompletedAt == nil { v += "+" } return v diff --git a/docs/reference/buildx_history_ls.md b/docs/reference/buildx_history_ls.md index 9f27d238df12..75bae00f4e07 100644 --- a/docs/reference/buildx_history_ls.md +++ b/docs/reference/buildx_history_ls.md @@ -9,14 +9,14 @@ List build records ### Options -| Name | Type | Default | Description | -|:--------------------------|:--------------|:--------|:---------------------------------------------| -| `--builder` | `string` | | Override the configured builder instance | -| `-D`, `--debug` | `bool` | | Enable debug logging | -| [`--filter`](#filter) | `stringArray` | | Provide filter values (e.g., `status=error`) | -| [`--format`](#format) | `string` | `table` | Format the output | -| [`--local`](#local) | `bool` | | List records for current repository only | -| [`--no-trunc`](#no-trunc) | `bool` | | Don't truncate output | +| Name | Type | Default | Description | +|:--------------------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--builder` | `string` | | Override the configured builder instance | +| `-D`, `--debug` | `bool` | | Enable debug logging | +| [`--filter`](#filter) | `stringArray` | | Provide filter values (e.g., `status=error`) | +| [`--format`](#format) | `string` | `table` | Format output using a custom template:
'table': Print output in table format with column headers (default)
'table TEMPLATE': Print output in table format using the given Go template
'json': Print in JSON format
'TEMPLATE': Print output using the given Go template.
Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates | +| [`--local`](#local) | `bool` | | List records for current repository only | +| [`--no-trunc`](#no-trunc) | `bool` | | Don't truncate output |