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 @@ -19,6 +19,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 @@ -32,7 +33,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 @@ -52,7 +53,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 @@ -70,11 +71,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 @@ -109,7 +110,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 @@ -145,10 +146,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 @@ -161,12 +162,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,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a way for us to keep Ref and CreatedAt in here and maybe add a deprecated message? If this is a direct field access, maybe we can put it into the context as something like deprecatedAttribute which prints the name to stderr when its String() method is accessed? If it's a method, we can just add the print to the method itself.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, I can have a look; probably could also add both as template function, pointing to the same implementation .

"Name": lsHeaderName,
"Status": lsHeaderStatus,
"Created": lsHeaderCreated,
"Duration": lsHeaderDuration,
"Link": lsHeaderLink,
}

return ctx.Write(&lsCtx, render)
Expand All @@ -178,66 +179,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