Skip to content

Commit 44aaec8

Browse files
committed
chore: improvements on go-task#1163 + changelog entry
1 parent f815ce2 commit 44aaec8

File tree

9 files changed

+80
-41
lines changed

9 files changed

+80
-41
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
website (#1198 by @pd93).
99
- Deprecated `version: 2` schema. This will be removed in the next major release
1010
(#1197, #1198, #1199 by @pd93).
11+
- Added a new `prompt:` prop to set a warning prompt to be shown before running
12+
a potential dangurous task (#100, #1163 by @MaxCheetham,
13+
[Documentation](https://taskfile.dev/usage/#warning-prompts))
1114

1215
## v3.25.0 - 2023-05-22
1316

docs/docs/api_reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ If `--` is given, all remaning arguments will be assigned to a special
4444
| | `--output-group-error-only` | `bool` | `false` | Swallow command output on zero exit code. |
4545
| `-p` | `--parallel` | `bool` | `false` | Executes tasks provided on command line in parallel. |
4646
| `-s` | `--silent` | `bool` | `false` | Disables echoing. |
47-
| `-y` | `--yes` | `bool` | `false` | Assume "yes" as answer to all prompts. |
47+
| `-y` | `--yes` | `bool` | `false` | Assume "yes" as answer to all prompts. |
4848
| | `--status` | `bool` | `false` | Exits with non-zero exit code if any of the given tasks is not up-to-date. |
4949
| | `--summary` | `bool` | `false` | Show summary about a task. |
5050
| `-t` | `--taskfile` | `string` | `Taskfile.yml` or `Taskfile.yaml` | |

docs/docs/usage.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,9 @@ tasks:
12161216

12171217
Warning Prompts to prompt a user for confirmation before a task is executed.
12181218

1219-
Below is an example using `prompt` with a dangerous command, that is called between two safe commands
1219+
Below is an example using `prompt` with a dangerous command, that is called
1220+
between two safe commands:
1221+
12201222
```yaml
12211223
version: '3'
12221224
@@ -1229,46 +1231,47 @@ tasks:
12291231
12301232
not-dangerous:
12311233
cmds:
1232-
- echo 'not dangerous command.'
1234+
- echo 'not dangerous command'
12331235
12341236
another-not-dangerous:
12351237
cmds:
1236-
- echo 'another not dangerous command.'
1238+
- echo 'another not dangerous command'
12371239
12381240
dangerous:
1239-
prompt: This is a dangerous command.. Do you want to continue?
1241+
prompt: This is a dangerous command... Do you want to continue?
12401242
cmds:
1241-
- echo 'dangerous command.'
1242-
1243+
- echo 'dangerous command'
12431244
```
1245+
12441246
```bash
12451247
❯ task dangerous
1246-
task: "This is a dangerous command.. Do you want to continue?" [y/N]
1248+
task: "This is a dangerous command... Do you want to continue?" [y/N]
12471249
```
12481250

1249-
### Prompt behaviour
1250-
1251-
Warning prompts are called before executing a task. If a prompt is denied Task will exit with [Exit code](api_reference.md#exit-codes) 205. If approved, Task will continue as normal.
1251+
Warning prompts are called before executing a task. If a prompt is denied Task
1252+
will exit with [exit code](api_reference.md#exit-codes) 205. If approved, Task
1253+
will continue as normal.
12521254

12531255
```bash
1254-
❯ taskd --dir ./testdata/prompt example
1255-
task: [not-dangerous] echo 'not dangerous command.'
1256-
not dangerous command.
1257-
task: "This is a dangerous command.. Do you want to continue?" [y/N]
1256+
❯ task example
1257+
not dangerous command
1258+
task: "This is a dangerous command. Do you want to continue?" [y/N]
12581259
y
1259-
task: [dangerous] echo 'dangerous command.'
1260-
dangerous command.
1261-
task: [another-not-dangerous] echo 'another not dangerous command.'
1262-
another not dangerous command.
1260+
dangerous command
1261+
another not dangerous command
12631262
```
12641263

1265-
### Skipping Warning Prompts
1266-
1267-
To skip warning prompts automatically, you can use the [-y | --yes] option when calling the task. By including this option, all warnings, will be automatically confirmed, and no prompts will be shows.
1268-
1264+
To skip warning prompts automatically, you can use the `--yes` (alias `-y`)
1265+
option when calling the task. By including this option, all warnings, will be
1266+
automatically confirmed, and no prompts will be shown.
12691267

1268+
:::caution
12701269

1270+
Tasks with prompts always fail by default on non-terminal environments, like a
1271+
CI, where an `stdin` won't be available for the user to answer. In cases like,
1272+
use `--yes` (`-y`) to force all tasks with a prompt to run.
12711273

1274+
:::
12721275

12731276
## Silent mode
12741277

errors/errors_task.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,34 @@ func (err *TaskCalledTooManyTimesError) Code() int {
9999
return CodeTaskCalledTooManyTimes
100100
}
101101

102-
// TaskCancelledError is returned when the user does not accept an optional prompt to continue.
103-
type TaskCancelledError struct {
102+
// TaskCancelledByUserError is returned when the user does not accept an optional prompt to continue.
103+
type TaskCancelledByUserError struct {
104104
TaskName string
105105
}
106106

107-
func (err *TaskCancelledError) Error() string {
107+
func (err *TaskCancelledByUserError) Error() string {
108108
return fmt.Sprintf(
109-
`task: %q Cancelled by user`,
109+
`task: Task "%q" cancelled by user`,
110110
err.TaskName,
111111
)
112112
}
113113

114-
func (err *TaskCancelledError) Code() int {
114+
func (err *TaskCancelledByUserError) Code() int {
115+
return CodeTaskCancelled
116+
}
117+
118+
// TaskCancelledNoTerminalError is returned when trying to run a task with a prompt in a non-terminal environment.
119+
type TaskCancelledNoTerminalError struct {
120+
TaskName string
121+
}
122+
123+
func (err *TaskCancelledNoTerminalError) Error() string {
124+
return fmt.Sprintf(
125+
`task: Task "%q" cancelled because it has a prompt and the environment is not a terminal. Use --yes (-y) to run anyway.`,
126+
err.TaskName,
127+
)
128+
}
129+
130+
func (err *TaskCancelledNoTerminalError) Code() int {
115131
return CodeTaskCancelled
116132
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/stretchr/testify v1.8.4
1616
golang.org/x/exp v0.0.0-20230212135524-a684f29349b6
1717
golang.org/x/sync v0.2.0
18+
golang.org/x/term v0.3.0
1819
gopkg.in/yaml.v3 v3.0.1
1920
mvdan.cc/sh/v3 v3.6.0
2021
)
@@ -26,6 +27,5 @@ require (
2627
github.com/pmezard/go-difflib v1.0.0 // indirect
2728
github.com/stretchr/objx v0.5.0 // indirect
2829
golang.org/x/sys v0.6.0 // indirect
29-
golang.org/x/term v0.3.0 // indirect
3030
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
3131
)

internal/term/term.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package term
2+
3+
import (
4+
"os"
5+
6+
"golang.org/x/term"
7+
)
8+
9+
func IsTerminal() bool {
10+
return term.IsTerminal(int(os.Stdin.Fd())) && term.IsTerminal(int(os.Stdout.Fd()))
11+
}

task.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/go-task/task/v3/internal/sort"
2424
"github.com/go-task/task/v3/internal/summary"
2525
"github.com/go-task/task/v3/internal/templater"
26+
"github.com/go-task/task/v3/internal/term"
2627
"github.com/go-task/task/v3/taskfile"
2728

2829
"github.com/sajari/fuzzy"
@@ -59,6 +60,7 @@ type Executor struct {
5960
Color bool
6061
Concurrency int
6162
Interval time.Duration
63+
AssumesTerm bool
6264

6365
Stdin io.Reader
6466
Stdout io.Writer
@@ -102,7 +104,6 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
102104
}
103105
return &errors.TaskInternalError{TaskName: call.Task}
104106
}
105-
106107
}
107108

108109
if e.Summary {
@@ -148,10 +149,13 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
148149
release := e.acquireConcurrencyLimit()
149150
defer release()
150151

151-
// check if the given task has a warning prompt
152152
if t.Prompt != "" && !e.AssumeYes {
153+
if !e.AssumesTerm && !term.IsTerminal() {
154+
return &errors.TaskCancelledNoTerminalError{TaskName: call.Task}
155+
}
153156

154157
e.Logger.Outf(logger.Yellow, "task: %q [y/N]\n", t.Prompt)
158+
155159
reader := bufio.NewReader(e.Stdin)
156160
userInput, err := reader.ReadString('\n')
157161
if err != nil {
@@ -160,7 +164,7 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
160164

161165
userInput = strings.ToLower(strings.TrimSpace(userInput))
162166
if !shouldPromptContinue(userInput) {
163-
return &errors.TaskCancelledError{TaskName: call.Task}
167+
return &errors.TaskCancelledByUserError{TaskName: call.Task}
164168
}
165169
}
166170

task_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -680,19 +680,20 @@ func TestPromptInSummary(t *testing.T) {
680680
inBuff.Write([]byte(test.input))
681681

682682
e := task.Executor{
683-
Dir: dir,
684-
Stdin: &inBuff,
685-
Stdout: &outBuff,
683+
Dir: dir,
684+
Stdin: &inBuff,
685+
Stdout: &outBuff,
686+
AssumesTerm: true,
686687
}
687688
require.NoError(t, e.Setup())
688689

689690
err := e.Run(context.Background(), taskfile.Call{Task: "foo"})
690691

691692
if test.wantError {
692693
require.Error(t, err)
693-
return
694+
} else {
695+
require.NoError(t, err)
694696
}
695-
require.NoError(t, err)
696697
})
697698
}
698699
}
@@ -705,9 +706,10 @@ func TestPromptWithIndirectTask(t *testing.T) {
705706
inBuff.Write([]byte("y\n"))
706707

707708
e := task.Executor{
708-
Dir: dir,
709-
Stdin: &inBuff,
710-
Stdout: &outBuff,
709+
Dir: dir,
710+
Stdin: &inBuff,
711+
Stdout: &outBuff,
712+
AssumesTerm: true,
711713
}
712714
require.NoError(t, e.Setup())
713715

testdata/prompt/Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
version: 3
2+
23
tasks:
34
foo:
45
prompt: Do you want to continue?
@@ -10,7 +11,6 @@ tasks:
1011
- task: show-prompt
1112

1213
show-prompt:
13-
summary: some text for the summary
1414
prompt: Do you want to continue?
1515
cmds:
1616
- echo 'show-prompt'

0 commit comments

Comments
 (0)