Merge pull request #3665 from crazy-max/builder-timeout

commands: make builder status timeouts configurable across cli flows
This commit is contained in:
CrazyMax
2026-02-24 18:35:17 +01:00
committed by GitHub
14 changed files with 97 additions and 45 deletions
+5 -2
View File
@@ -346,6 +346,7 @@ type CreateOpts struct {
Use bool
Endpoint string
Append bool
Timeout time.Duration
}
func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts CreateOpts) (*Builder, error) {
@@ -525,8 +526,10 @@ func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Cre
return nil, err
}
cancelCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
timeoutCtx, cancel := context.WithCancelCause(ctx)
if opts.Timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, WithData())
+4
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"time"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/driver"
@@ -27,6 +28,7 @@ type createOptions struct {
buildkitdFlags string
buildkitdConfigFile string
bootstrap bool
timeout time.Duration
// upgrade bool // perform upgrade of the driver
}
@@ -61,6 +63,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
Use: in.use,
Endpoint: ep,
Append: in.actionAppend,
Timeout: in.timeout,
})
if err != nil {
return err
@@ -120,6 +123,7 @@ func createCmd(dockerCli command.Cli) *cobra.Command {
flags.BoolVar(&options.actionAppend, "append", false, "Append a node to builder instead of changing it")
flags.BoolVar(&options.actionLeave, "leave", false, "Remove a node from builder instead of changing it")
flags.BoolVar(&options.use, "use", false, "Set the current builder instance")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
// hide builder persistent flag for this command
cobrautil.HideInheritedFlags(cmd, "builder")
+9 -1
View File
@@ -65,6 +65,7 @@ type duOptions struct {
filter opts.FilterOpt
verbose bool
format string
timeout time.Duration
}
func runDiskUsage(ctx context.Context, dockerCli command.Cli, opts duOptions) error {
@@ -92,7 +93,13 @@ func runDiskUsage(ctx context.Context, dockerCli command.Cli, opts duOptions) er
return err
}
nodes, err := b.LoadNodes(ctx)
timeoutCtx, cancel := context.WithCancelCause(ctx)
if opts.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx)
if err != nil {
return err
}
@@ -197,6 +204,7 @@ func duCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.Var(&options.filter, "filter", "Provide filter values")
flags.BoolVar(&options.verbose, "verbose", false, `Shorthand for "--format=pretty"`)
flags.StringVar(&options.format, "format", "", "Format the output")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
return cmd
}
+5 -1
View File
@@ -24,6 +24,7 @@ import (
type inspectOptions struct {
bootstrap bool
builder string
timeout time.Duration
}
func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) error {
@@ -36,7 +37,9 @@ func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) e
}
timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
if in.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, builder.WithData())
@@ -188,6 +191,7 @@ func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags := cmd.Flags()
flags.BoolVar(&options.bootstrap, "bootstrap", false, "Ensure builder has booted before inspecting")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
return cmd
}
+5 -1
View File
@@ -40,6 +40,7 @@ const (
type lsOptions struct {
format string
noTrunc bool
timeout time.Duration
}
func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
@@ -60,7 +61,9 @@ func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
}
timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
if in.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx)
@@ -114,6 +117,7 @@ func lsCmd(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.StringVar(&options.format, "format", formatter.TableFormatKey, "Format the output")
flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
// hide builder persistent flag for this command
cobrautil.HideInheritedFlags(cmd, "builder")
+9 -1
View File
@@ -36,6 +36,7 @@ type pruneOptions struct {
minFreeSpace opts.MemBytes
force bool
verbose bool
timeout time.Duration
}
const (
@@ -68,7 +69,13 @@ func runPrune(ctx context.Context, dockerCli command.Cli, opts pruneOptions) err
return err
}
nodes, err := b.LoadNodes(ctx)
timeoutCtx, cancel := context.WithCancelCause(ctx)
if opts.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx)
if err != nil {
return err
}
@@ -182,6 +189,7 @@ func pruneCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.Var(&options.maxUsedSpace, "max-used-space", "Maximum amount of disk space allowed to keep for cache")
flags.BoolVar(&options.verbose, "verbose", false, "Provide a more verbose output")
flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
flags.Var(&options.reservedSpace, "keep-storage", "Amount of disk space to keep for cache")
flags.MarkDeprecated("keep-storage", "keep-storage flag has been changed to reserved-space")
+13 -3
View File
@@ -21,6 +21,7 @@ type rmOptions struct {
keepDaemon bool
allInactive bool
force bool
timeout time.Duration
}
const (
@@ -46,7 +47,13 @@ func runRm(ctx context.Context, dockerCli command.Cli, in rmOptions) error {
return rmAllInactive(ctx, txn, dockerCli, in)
}
eg, _ := errgroup.WithContext(ctx)
timeoutCtx, cancel := context.WithCancelCause(ctx)
if in.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx)
for _, name := range in.builders {
func(name string) {
eg.Go(func() (err error) {
@@ -67,7 +74,7 @@ func runRm(ctx context.Context, dockerCli command.Cli, in rmOptions) error {
return err
}
nodes, err := b.LoadNodes(ctx)
nodes, err := b.LoadNodes(timeoutCtx)
if err != nil {
return err
}
@@ -120,6 +127,7 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.BoolVar(&options.keepDaemon, "keep-daemon", false, "Keep the BuildKit daemon running")
flags.BoolVar(&options.allInactive, "all-inactive", false, "Remove all inactive builders")
flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
setBuilderStatusTimeoutFlag(flags, &options.timeout)
return cmd
}
@@ -152,7 +160,9 @@ func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, i
}
timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
if in.timeout > 0 {
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent
}
defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx)
+5
View File
@@ -3,6 +3,7 @@ package commands
import (
"fmt"
"os"
"time"
historycmd "github.com/docker/buildx/commands/history"
imagetoolscmd "github.com/docker/buildx/commands/imagetools"
@@ -142,3 +143,7 @@ func rootFlags(options *rootOptions, flags *pflag.FlagSet) {
flags.StringVar(&options.builder, "builder", os.Getenv("BUILDX_BUILDER"), "Override the configured builder instance")
flags.BoolVarP(&options.debug, "debug", "D", debug.IsEnabled(), "Enable debug logging")
}
func setBuilderStatusTimeoutFlag(flags *pflag.FlagSet, target *time.Duration) {
flags.DurationVar(target, "timeout", 20*time.Second, "Override the default timeout for loading builder status")
}
+1
View File
@@ -22,6 +22,7 @@ Create a new builder instance
| [`--name`](#name) | `string` | | Builder instance name |
| [`--node`](#node) | `string` | | Create/modify node with given name |
| [`--platform`](#platform) | `stringArray` | | Fixed platforms for current node |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
| [`--use`](#use) | `bool` | | Set the current builder instance |
+2 -1
View File
@@ -10,11 +10,12 @@ Disk usage
### Options
| Name | Type | Default | Description |
|:------------------------|:---------|:--------|:-----------------------------------------|
|:------------------------|:-----------|:--------|:--------------------------------------------------------|
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
| `-D`, `--debug` | `bool` | | Enable debug logging |
| [`--filter`](#filter) | `filter` | | Provide filter values |
| [`--format`](#format) | `string` | | Format the output |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
| [`--verbose`](#verbose) | `bool` | | Shorthand for `--format=pretty` |
+2 -1
View File
@@ -10,10 +10,11 @@ Inspect current builder instance
### Options
| Name | Type | Default | Description |
|:----------------------------|:---------|:--------|:--------------------------------------------|
|:----------------------------|:-----------|:--------|:--------------------------------------------------------|
| [`--bootstrap`](#bootstrap) | `bool` | | Ensure builder has booted before inspecting |
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
| `-D`, `--debug` | `bool` | | Enable debug logging |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
<!---MARKER_GEN_END-->
+2 -1
View File
@@ -10,10 +10,11 @@ List builder instances
### Options
| Name | Type | Default | Description |
|:----------------------|:---------|:--------|:----------------------|
|:----------------------|:-----------|:--------|:--------------------------------------------------------|
| `-D`, `--debug` | `bool` | | Enable debug logging |
| [`--format`](#format) | `string` | `table` | Format the output |
| `--no-trunc` | `bool` | | Don't truncate output |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
<!---MARKER_GEN_END-->
+2 -1
View File
@@ -10,7 +10,7 @@ Remove build cache
### Options
| Name | Type | Default | Description |
|:--------------------------------------|:---------|:--------|:-------------------------------------------------------|
|:--------------------------------------|:-----------|:--------|:--------------------------------------------------------|
| [`-a`](#all), [`--all`](#all) | `bool` | | Include internal/frontend images |
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
| `-D`, `--debug` | `bool` | | Enable debug logging |
@@ -19,6 +19,7 @@ Remove build cache
| [`--max-used-space`](#max-used-space) | `bytes` | `0` | Maximum amount of disk space allowed to keep for cache |
| [`--min-free-space`](#min-free-space) | `bytes` | `0` | Target amount of free disk space after pruning |
| [`--reserved-space`](#reserved-space) | `bytes` | `0` | Amount of disk space always allowed to keep for cache |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
| `--verbose` | `bool` | | Provide a more verbose output |
+2 -1
View File
@@ -10,13 +10,14 @@ Remove one or more builder instances
### Options
| Name | Type | Default | Description |
|:------------------------------------|:---------|:--------|:-----------------------------------------|
|:------------------------------------|:-----------|:--------|:--------------------------------------------------------|
| [`--all-inactive`](#all-inactive) | `bool` | | Remove all inactive builders |
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
| `-D`, `--debug` | `bool` | | Enable debug logging |
| [`-f`](#force), [`--force`](#force) | `bool` | | Do not prompt for confirmation |
| [`--keep-daemon`](#keep-daemon) | `bool` | | Keep the BuildKit daemon running |
| [`--keep-state`](#keep-state) | `bool` | | Keep BuildKit state |
| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |
<!---MARKER_GEN_END-->