Skip to content

history ls: fix '--format' flag to accept go templates#3683

Draft
thaJeztah wants to merge 3 commits intodocker:masterfrom
thaJeztah:history_ls_format
Draft

history ls: fix '--format' flag to accept go templates#3683
thaJeztah wants to merge 3 commits intodocker:masterfrom
thaJeztah:history_ls_format

Conversation

@thaJeztah
Copy link
Member

Before this PR, attempting to use a format template would always fail;

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).

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;

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;

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

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 <[email protected]>
@thaJeztah
Copy link
Member Author

Ugh; we should disable this linter; it's too opinionated; in this case it's also .. wrong because there's fields being shadowed by wrappers 🤔

#23 125.4 commands/history/ls.go:190:24: QF1008: could remove embedded field "historyRecord" from selector (staticcheck)
#23 125.4 		"total_steps":     c.historyRecord.NumTotalSteps,
#23 125.4 		                     ^

I'll push a "WIP" commit, but may open a PR to disable this linter (I know we disabled it elsewhere).

@thaJeztah thaJeztah force-pushed the history_ls_format branch from 4e31781 to db5f3fc Compare March 3, 2026 17:07
@thaJeztah thaJeztah marked this pull request as draft March 3, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant