Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
73 changes: 37 additions & 36 deletions commands/history/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
)
Expand All @@ -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()
Expand All @@ -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
}
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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
}
Expand All @@ -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)
Expand All @@ -177,66 +178,66 @@ type lsContext struct {
isTerm bool
trunc bool
format formatter.Format
record *historyRecord
*historyRecord
}

func (c *lsContext) MarshalJSON() ([]byte, error) {
m := map[string]any{
"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)
}
return name
}

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"
}
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
Expand Down
16 changes: 8 additions & 8 deletions docs/reference/buildx_history_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>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 |


<!---MARKER_GEN_END-->
Expand Down
Loading