Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

monitor: on-error: support long-form for allowing configuring the container #1917

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
52 changes: 41 additions & 11 deletions commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
return err
}
options.invoke = &invoke
options.noBuild = invokeFlag == "debug-shell"
options.noBuild = invoke.isNoBuild()
}
return runBuild(dockerCli, options)
},
Expand Down Expand Up @@ -681,34 +681,59 @@ func updateLastActivity(dockerCli command.Cli, ng *store.NodeGroup) error {

type invokeConfig struct {
controllerapi.InvokeConfig
invokeFlag string
invokeType string
}

const (
// invokeTypeDefault is a type of invoking that runs the monitor and the interactive container
// with the default configuration of the build step, after the build finished.
invokeTypeDefault = "default"

// invokeTypeConfig is a type of invoking that runs the monitor and the interactive container
// with the specified configuration of the build step, after the build finished.
invokeTypeConfig = "config"

// invokeTypeDebugShell is a type of invoking that doesn't perform a build but immediately
// launch the monitor.
invokeTypeDebugShell = "debug-shell"

// invokeTypeOnError is a type of invoking that starts the monitor and the interactive container
// when the build finished with error.
invokeTypeOnError = "on-error"
)

func (cfg *invokeConfig) isNoBuild() bool {
return cfg.invokeType == invokeTypeDebugShell
}

func (cfg *invokeConfig) needsMonitor(retErr error) bool {
switch cfg.invokeFlag {
case "debug-shell":
switch cfg.invokeType {
case invokeTypeDebugShell:
return true
case "on-error":
case invokeTypeOnError:
return retErr != nil
default:
return cfg.invokeFlag != ""
return cfg.invokeType != ""
}
}

func parseInvokeConfig(invoke string) (cfg invokeConfig, err error) {
cfg.invokeFlag = invoke
cfg.Tty = true
switch invoke {
case "default", "debug-shell":
case invokeTypeDefault, invokeTypeDebugShell:
cfg.invokeType = invoke
return cfg, nil
case "on-error":
// NOTE: we overwrite the command to run because the original one should fail on the failed step.
// TODO: make this configurable via flags or restorable from LLB.
case invokeTypeOnError:
// NOTE: We overwrite the command to run because the original one should fail on the failed step.
// User can use long-form (w/ "type=on-error") to customize the command.
// TODO: make this restorable from LLB if needed.
// Discussion: https://github.com/docker/buildx/pull/1640#discussion_r1113295900
cfg.Cmd = []string{"/bin/sh"}
cfg.invokeType = invoke
return cfg, nil
}

cfg.invokeType = invokeTypeConfig
csvReader := csv.NewReader(strings.NewReader(invoke))
csvReader.LazyQuotes = true
fields, err := csvReader.Read()
Expand Down Expand Up @@ -749,6 +774,11 @@ func parseInvokeConfig(invoke string) (cfg invokeConfig, err error) {
if err != nil {
return cfg, errors.Errorf("failed to parse tty: %v", err)
}
case "type":
if value != invokeTypeOnError && value != invokeTypeConfig {
return cfg, errors.Errorf("\"on-error\" or \"config\" are only supported as the custom type")
}
cfg.invokeType = value
default:
return cfg, errors.Errorf("unknown key %q", key)
}
Expand Down
15 changes: 13 additions & 2 deletions docs/guides/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ dev home media opt root sbin sys usr work

Optional long form allows you specifying detailed configurations of the process.
It must be CSV-styled comma-separated key-value pairs.
Supported keys are `args` (can be JSON array format), `entrypoint` (can be JSON array format), `env` (can be JSON array format), `user`, `cwd` and `tty` (bool).
Supported keys for configuring containers are `args` (can be JSON array format), `entrypoint` (can be JSON array format), `env` (can be JSON array format), `user`, `cwd` and `tty` (bool).
You can also specify `type=on-error` if you want to change the configuration of the container (e.g. commands to execute) that will be executed from the failed step.

Example:
Examples:

```
$ docker buildx build --invoke 'entrypoint=["sh"],"args=[""-c"", ""env | grep -e FOO -e AAA""]","env=[""FOO=bar"", ""AAA=bbb""]"' .
```

```
$ docker buildx build --invoke 'type=on-error,args=bash' .
```

#### `on-error`

If you want to start a debug session when a build fails, you can use
Expand All @@ -85,6 +90,12 @@ Interactive container was restarted with process "edmzor60nrag7rh1mbi4o9lm8". Pr

This allows you to explore the state of the image when the build failed.

You can also use long-form flag with `type=on-error` option.

```
$ docker buildx build --invoke 'type=on-error,args=bash' .
```

#### `debug-shell`

If you want to drop into a debug session without first starting the build, you
Expand Down