Skip to content

Commit 4e31781

Browse files
committed
history ls: fix '--format' flag to accept go templates
Before this PR, attempting to use a format template would always fail; ```bash docker buildx history ls --no-trunc --format 'table {{.Status}}\t{{.NumTotalSteps}}\t{{.Duration}}\t{{.Name}}' ERROR: template parsing error: template: :1:14: executing "" at <.NumTotalSteps>: can't evaluate field NumTotalSteps in type *history.lsContext ``` With this PR, formatting works (mostly); the formatting templates don't match the JSON response (which can be confusing), and not all fields have a table defined (which can result in `<no value>` used). ```bash docker buildx history ls --no-trunc --format 'table {{.Status}}\t{{.NumTotalSteps}}\t{{.Duration}}\t{{.Name}}' STATUS <no value> DURATION NAME Completed 16 17.1s buildx (binaries) Completed 12 19.9s buildkit/hack/dockerfiles/vendor.Dockerfile (update) Completed 123 28.7s docker (dev-base) Completed 26 7.9s Completed 12 2m 41s cli/dockerfiles/Dockerfile.vendor (update) ``` Or a slightly more adventurous; ```bash docker buildx history ls --no-trunc --format '{{printf "{\"status\":%s,\"steps\":%s,\"duration\":%s,\"name\":%s}" (json .Status) (json .NumTotalSteps) (json .Duration) (json .Name)}}' {"status":"Completed","steps":16,"duration":"17.1s","name":"buildx (binaries)"} {"status":"Completed","steps":12,"duration":"19.9s","name":"buildkit/hack/dockerfiles/vendor.Dockerfile (update)"} {"status":"Completed","steps":123,"duration":"28.7s","name":"docker (dev-base)"} {"status":"Completed","steps":26,"duration":"7.9s","name":""} {"status":"Completed","steps":12,"duration":"2m 41s","name":"cli/dockerfiles/Dockerfile.vendor (update)"} {"status":"Error","steps":11,"duration":"3m 14s","name":"cli/dockerfiles/Dockerfile.vendor (update)"} ``` The flag description has been updated to align with other `--format` flags; ```bash docker buildx history ls --help Usage: docker buildx history ls [OPTIONS] List build records Options: --builder string Override the configured builder instance -D, --debug Enable debug logging --filter stringArray Provide filter values (e.g., "status=error") --format string 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 (default "table") --local List records for current repository only --no-trunc Don't truncate output ``` Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent 06b1d87 commit 4e31781

File tree

3 files changed

+34
-33
lines changed

3 files changed

+34
-33
lines changed

commands/history/ls.go

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/docker/cli/cli"
1919
"github.com/docker/cli/cli/command"
2020
"github.com/docker/cli/cli/command/formatter"
21+
cliflags "github.com/docker/cli/cli/flags"
2122
"github.com/docker/go-units"
2223
"github.com/pkg/errors"
2324
"github.com/spf13/cobra"
@@ -85,7 +86,7 @@ func runLs(ctx context.Context, dockerCli command.Cli, opts lsOptions) error {
8586

8687
for i, rec := range out {
8788
st, _ := ls.ReadRef(rec.node.Builder, rec.node.Name, rec.Ref)
88-
rec.name = BuildName(rec.FrontendAttrs, st)
89+
rec.Name = BuildName(rec.FrontendAttrs, st)
8990
out[i] = rec
9091
}
9192

@@ -108,7 +109,7 @@ func lsCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
108109
}
109110

110111
flags := cmd.Flags()
111-
flags.StringVar(&options.format, "format", formatter.TableFormatKey, "Format the output")
112+
flags.StringVar(&options.format, "format", formatter.TableFormatKey, cliflags.FormatHelp)
112113
flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output")
113114
flags.StringArrayVar(&options.filters, "filter", nil, `Provide filter values (e.g., "status=error")`)
114115
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
144145
render := func(format func(subContext formatter.SubContext) error) error {
145146
for _, r := range records {
146147
if err := format(&lsContext{
147-
format: formatter.Format(in.format),
148-
isTerm: term,
149-
trunc: !in.noTrunc,
150-
record: &r,
148+
format: formatter.Format(in.format),
149+
isTerm: term,
150+
trunc: !in.noTrunc,
151+
historyRecord: &r,
151152
}); err != nil {
152153
return err
153154
}
@@ -177,44 +178,44 @@ type lsContext struct {
177178
isTerm bool
178179
trunc bool
179180
format formatter.Format
180-
record *historyRecord
181+
*historyRecord
181182
}
182183

183184
func (c *lsContext) MarshalJSON() ([]byte, error) {
184185
m := map[string]any{
185186
"ref": c.FullRef(),
186187
"name": c.Name(),
187188
"status": c.Status(),
188-
"created_at": c.record.CreatedAt.AsTime().Format(time.RFC3339Nano),
189-
"total_steps": c.record.NumTotalSteps,
190-
"completed_steps": c.record.NumCompletedSteps,
191-
"cached_steps": c.record.NumCachedSteps,
189+
"created_at": c.historyRecord.CreatedAt.AsTime().Format(time.RFC3339Nano),
190+
"total_steps": c.historyRecord.NumTotalSteps,
191+
"completed_steps": c.historyRecord.NumCompletedSteps,
192+
"cached_steps": c.historyRecord.NumCachedSteps,
192193
}
193-
if c.record.CompletedAt != nil {
194-
m["completed_at"] = c.record.CompletedAt.AsTime().Format(time.RFC3339Nano)
194+
if c.historyRecord.CompletedAt != nil {
195+
m["completed_at"] = c.historyRecord.CompletedAt.AsTime().Format(time.RFC3339Nano)
195196
}
196197
return json.Marshal(m)
197198
}
198199

199200
func (c *lsContext) Ref() string {
200-
return c.record.Ref
201+
return c.historyRecord.Ref
201202
}
202203

203204
func (c *lsContext) FullRef() string {
204-
return fmt.Sprintf("%s/%s/%s", c.record.node.Builder, c.record.node.Name, c.record.Ref)
205+
return fmt.Sprintf("%s/%s/%s", c.historyRecord.node.Builder, c.historyRecord.node.Name, c.historyRecord.Ref)
205206
}
206207

207208
func (c *lsContext) Name() string {
208-
name := c.record.name
209+
name := c.historyRecord.Name
209210
if c.trunc && c.format.IsTable() {
210211
return trimBeginning(name, 36)
211212
}
212213
return name
213214
}
214215

215216
func (c *lsContext) Status() string {
216-
if c.record.CompletedAt != nil {
217-
if c.record.Error != nil {
217+
if c.historyRecord.CompletedAt != nil {
218+
if c.historyRecord.Error != nil {
218219
return "Error"
219220
}
220221
return "Completed"
@@ -223,20 +224,20 @@ func (c *lsContext) Status() string {
223224
}
224225

225226
func (c *lsContext) CreatedAt() string {
226-
return units.HumanDuration(time.Since(c.record.CreatedAt.AsTime())) + " ago"
227+
return units.HumanDuration(time.Since(c.historyRecord.CreatedAt.AsTime())) + " ago"
227228
}
228229

229230
func (c *lsContext) Duration() string {
230-
lastTime := c.record.currentTimestamp
231-
if c.record.CompletedAt != nil {
232-
tm := c.record.CompletedAt.AsTime()
231+
lastTime := c.historyRecord.currentTimestamp
232+
if c.historyRecord.CompletedAt != nil {
233+
tm := c.historyRecord.CompletedAt.AsTime()
233234
lastTime = &tm
234235
}
235236
if lastTime == nil {
236237
return ""
237238
}
238-
v := formatDuration(lastTime.Sub(c.record.CreatedAt.AsTime()))
239-
if c.record.CompletedAt == nil {
239+
v := formatDuration(lastTime.Sub(c.historyRecord.CreatedAt.AsTime()))
240+
if c.historyRecord.CompletedAt == nil {
240241
v += "+"
241242
}
242243
return v

commands/history/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ type historyRecord struct {
120120
*controlapi.BuildHistoryRecord
121121
currentTimestamp *time.Time
122122
node *builder.Node
123-
name string
123+
Name string
124124
}
125125

126126
type queryOptions struct {

docs/reference/buildx_history_ls.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ List build records
99

1010
### Options
1111

12-
| Name | Type | Default | Description |
13-
|:--------------------------|:--------------|:--------|:---------------------------------------------|
14-
| `--builder` | `string` | | Override the configured builder instance |
15-
| `-D`, `--debug` | `bool` | | Enable debug logging |
16-
| [`--filter`](#filter) | `stringArray` | | Provide filter values (e.g., `status=error`) |
17-
| [`--format`](#format) | `string` | `table` | Format the output |
18-
| [`--local`](#local) | `bool` | | List records for current repository only |
19-
| [`--no-trunc`](#no-trunc) | `bool` | | Don't truncate output |
12+
| Name | Type | Default | Description |
13+
|:--------------------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
14+
| `--builder` | `string` | | Override the configured builder instance |
15+
| `-D`, `--debug` | `bool` | | Enable debug logging |
16+
| [`--filter`](#filter) | `stringArray` | | Provide filter values (e.g., `status=error`) |
17+
| [`--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 |
18+
| [`--local`](#local) | `bool` | | List records for current repository only |
19+
| [`--no-trunc`](#no-trunc) | `bool` | | Don't truncate output |
2020

2121

2222
<!---MARKER_GEN_END-->

0 commit comments

Comments
 (0)