mirror of
https://github.com/go-task/task.git
synced 2026-02-24 20:20:30 +01:00
feat(cmd): add ask option to commands
Add an `ask` attribute to commands that shows a y/n confirmation
before executing. If the user declines, the command is skipped but
the task continues with the next command.
Example:
```yaml
cmds:
- cmd: echo "Deploying..."
ask: "Deploy to production?"
- task: run-migrations
ask: "Run database migrations?"
```
Behavior:
- Default: asks for y/n confirmation
- --yes: auto-confirms all asks
- --dry: shows commands without asking
This differs from task-level `prompt:` which cancels the entire task
if declined. Command-level `ask:` only skips the individual command.
This commit is contained in:
16
task.go
16
task.go
@@ -365,6 +365,22 @@ func (e *Executor) runCommand(ctx context.Context, t *ast.Task, call *Call, i in
|
||||
}
|
||||
}
|
||||
|
||||
// Handle ask attached to command (y/n confirmation)
|
||||
if cmd.Ask != "" && !e.Dry {
|
||||
if e.AssumeYes {
|
||||
e.Logger.VerboseOutf(logger.Yellow, "task: [%s] %s [assuming yes]\n", t.Name(), cmd.Ask)
|
||||
} else {
|
||||
if err := e.Logger.Prompt(logger.Yellow, cmd.Ask, "n", "y", "yes"); errors.Is(err, logger.ErrNoTerminal) {
|
||||
return &errors.TaskCancelledNoTerminalError{TaskName: call.Task}
|
||||
} else if errors.Is(err, logger.ErrPromptCancelled) {
|
||||
e.Logger.VerboseOutf(logger.Yellow, "task: [%s] ask declined - skipped\n", t.Name())
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case cmd.Task != "":
|
||||
reacquire := e.releaseConcurrencyLimit()
|
||||
|
||||
@@ -20,6 +20,7 @@ type Cmd struct {
|
||||
IgnoreError bool
|
||||
Defer bool
|
||||
Platforms []*Platform
|
||||
Ask string
|
||||
}
|
||||
|
||||
func (c *Cmd) DeepCopy() *Cmd {
|
||||
@@ -38,6 +39,7 @@ func (c *Cmd) DeepCopy() *Cmd {
|
||||
IgnoreError: c.IgnoreError,
|
||||
Defer: c.Defer,
|
||||
Platforms: deepcopy.Slice(c.Platforms),
|
||||
Ask: c.Ask,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +67,7 @@ func (c *Cmd) UnmarshalYAML(node *yaml.Node) error {
|
||||
IgnoreError bool `yaml:"ignore_error"`
|
||||
Defer *Defer
|
||||
Platforms []*Platform
|
||||
Ask string
|
||||
}
|
||||
if err := node.Decode(&cmdStruct); err != nil {
|
||||
return errors.NewTaskfileDecodeError(err, node)
|
||||
@@ -98,6 +101,7 @@ func (c *Cmd) UnmarshalYAML(node *yaml.Node) error {
|
||||
c.If = cmdStruct.If
|
||||
c.Silent = cmdStruct.Silent
|
||||
c.IgnoreError = cmdStruct.IgnoreError
|
||||
c.Ask = cmdStruct.Ask
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -111,6 +115,7 @@ func (c *Cmd) UnmarshalYAML(node *yaml.Node) error {
|
||||
c.Shopt = cmdStruct.Shopt
|
||||
c.IgnoreError = cmdStruct.IgnoreError
|
||||
c.Platforms = cmdStruct.Platforms
|
||||
c.Ask = cmdStruct.Ask
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -741,6 +741,8 @@ tasks:
|
||||
platforms: [linux, darwin]
|
||||
set: [errexit]
|
||||
shopt: [globstar]
|
||||
if: '[ "$CI" = "true" ]'
|
||||
ask: "Run this command?"
|
||||
```
|
||||
|
||||
### Task References
|
||||
@@ -857,6 +859,36 @@ tasks:
|
||||
if: '[ "{{.ITEM}}" != "b" ]'
|
||||
```
|
||||
|
||||
### Command Confirmations
|
||||
|
||||
Use `ask` to request user confirmation before executing a command. If the
|
||||
user declines (answers "n" or "no"), the command is skipped but the task
|
||||
continues.
|
||||
|
||||
```yaml
|
||||
tasks:
|
||||
deploy:
|
||||
cmds:
|
||||
- cmd: echo "Deploying to production..."
|
||||
ask: "Deploy to production?"
|
||||
- cmd: echo "Updating database..."
|
||||
ask: "Run database migrations?"
|
||||
- echo "Done!" # No ask, always runs
|
||||
```
|
||||
|
||||
| Flag | Behavior |
|
||||
|------|----------|
|
||||
| (none) | Asks user for y/n confirmation |
|
||||
| `--yes` | Auto-confirms all asks |
|
||||
| `--dry` | Shows commands without asking |
|
||||
|
||||
:::note
|
||||
|
||||
This is different from the task-level `prompt:` which cancels the entire task
|
||||
if declined. Command-level `ask:` only skips the individual command.
|
||||
|
||||
:::
|
||||
|
||||
## Shell Options
|
||||
|
||||
### Set Options
|
||||
|
||||
@@ -340,6 +340,10 @@
|
||||
"if": {
|
||||
"description": "A shell command to evaluate. If the exit code is non-zero, the command is skipped.",
|
||||
"type": "string"
|
||||
},
|
||||
"ask": {
|
||||
"description": "A y/n confirmation shown before executing this task call. If declined, the task call is skipped.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -381,6 +385,10 @@
|
||||
"if": {
|
||||
"description": "A shell command to evaluate. If the exit code is non-zero, the command is skipped.",
|
||||
"type": "string"
|
||||
},
|
||||
"ask": {
|
||||
"description": "A y/n confirmation shown before executing this command. If declined, the command is skipped.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
Reference in New Issue
Block a user