Skip to content

Commit 9da7bb9

Browse files
committed
feat: split cli args experiment
1 parent cb14a4f commit 9da7bb9

File tree

3 files changed

+156
-6
lines changed

3 files changed

+156
-6
lines changed

cmd/task/task.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,15 @@ func run() error {
172172
calls = append(calls, &task.Call{Task: "default"})
173173
}
174174

175-
globals.Set("CLI_ARGS", ast.Var{Value: cliArgs})
175+
if experiments.SplitCLIArgs.Enabled() {
176+
globals.Set("CLI_ARGS", ast.Var{Value: cliArgs})
177+
} else {
178+
quotedCLIArgs, err := cliArgsToQuotedString(cliArgs)
179+
if err != nil {
180+
return err
181+
}
182+
globals.Set("CLI_ARGS", ast.Var{Value: quotedCLIArgs})
183+
}
176184
globals.Set("CLI_FORCE", ast.Var{Value: flags.Force || flags.ForceAll})
177185
globals.Set("CLI_SILENT", ast.Var{Value: flags.Silent})
178186
globals.Set("CLI_VERBOSE", ast.Var{Value: flags.Verbose})
@@ -192,23 +200,27 @@ func run() error {
192200
return e.Run(ctx, calls...)
193201
}
194202

195-
func getArgs() ([]string, string, error) {
203+
func getArgs() ([]string, []string, error) {
196204
var (
197205
args = pflag.Args()
198206
doubleDashPos = pflag.CommandLine.ArgsLenAtDash()
199207
)
200208

201209
if doubleDashPos == -1 {
202-
return args, "", nil
210+
return args, nil, nil
203211
}
204212

213+
return args[:doubleDashPos], args[doubleDashPos:], nil
214+
}
215+
216+
func cliArgsToQuotedString(args []string) (string, error) {
205217
var quotedCliArgs []string
206-
for _, arg := range args[doubleDashPos:] {
218+
for _, arg := range args {
207219
quotedCliArg, err := syntax.Quote(arg, syntax.LangBash)
208220
if err != nil {
209-
return nil, "", err
221+
return "", err
210222
}
211223
quotedCliArgs = append(quotedCliArgs, quotedCliArg)
212224
}
213-
return args[:doubleDashPos], strings.Join(quotedCliArgs, " "), nil
225+
return strings.Join(quotedCliArgs, " "), nil
214226
}

internal/experiments/experiments.go

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var (
3030
AnyVariables Experiment
3131
MapVariables Experiment
3232
EnvPrecedence Experiment
33+
SplitCLIArgs Experiment
3334
)
3435

3536
// An internal list of all the initialized experiments used for iterating.
@@ -46,6 +47,7 @@ func init() {
4647
AnyVariables = New("ANY_VARIABLES")
4748
MapVariables = New("MAP_VARIABLES", 1, 2)
4849
EnvPrecedence = New("ENV_PRECEDENCE", 1)
50+
SplitCLIArgs = New("SPLIT_CLI_ARGS", 1)
4951
}
5052

5153
// Validate checks if any experiments have been enabled while being inactive.
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
slug: /experiments/split-cli-args/
3+
---
4+
5+
import Tabs from '@theme/Tabs';
6+
import TabItem from '@theme/TabItem';
7+
8+
# Split CLI Args (#2139)
9+
10+
:::caution
11+
12+
All experimental features are subject to breaking changes and/or removal _at any
13+
time_. We strongly recommend that you do not use these features in a production
14+
environment. They are intended for testing and feedback only.
15+
16+
:::
17+
18+
:::warning
19+
20+
This experiment breaks the following functionality:
21+
22+
- The `CLI_ARGS` variable will no longer work in arguments to string templating
23+
functions.
24+
- Outputting the `CLI_ARGS` variable directly will result in a string
25+
representation of an array (including the enclosing square brackets).
26+
27+
:::
28+
29+
:::info
30+
31+
To enable this experiment, set the environment variable:
32+
`TASK_X_SPLIT_CLI_ARGS=1`. Check out [our guide to enabling experiments
33+
][enabling-experiments] for more information.
34+
35+
:::
36+
37+
This experiment changes the type of the `CLI_ARGS` variable from a string to an
38+
array of strings. This allows the user to more easily mutate and iterate over
39+
individual arguments. Arguments will no longer be quoted if they contain a
40+
space. However whitespace will still be escaped in arguments if the arguments
41+
are quoted properly. For example:
42+
43+
```yaml
44+
version: '3'
45+
46+
tasks:
47+
default:
48+
silent: true
49+
cmds:
50+
- "echo 'args: {{.CLI_ARGS}}'"
51+
- "echo 'first arg: {{index .CLI_ARGS 0}}'"
52+
- for: { var: CLI_ARGS, as: FILENAME }
53+
cmd: echo "{{.FILENAME}}"
54+
```
55+
56+
<Tabs defaultValue="2"
57+
values={[
58+
{label: 'Before', value: '1'},
59+
{label: 'After', value: '2'}
60+
]}>
61+
62+
<TabItem value="1">
63+
64+
```shell
65+
$ task -- foo.txt bar.txt "hello world.txt"
66+
```
67+
```
68+
args: foo.txt bar.txt hello world.txt
69+
first arg: 102
70+
foo.txt
71+
bar.txt
72+
'hello
73+
world.txt'
74+
```
75+
76+
</TabItem>
77+
<TabItem value="2">
78+
79+
```shell
80+
$ TASK_X_SPLIT_CLI_ARGS=1 task -- foo.txt bar.txt "hello world.txt"
81+
```
82+
```
83+
args: [foo.txt bar.txt hello world.txt]
84+
first arg: foo.txt
85+
foo.txt
86+
bar.txt
87+
hello world.txt
88+
```
89+
90+
</TabItem>
91+
</Tabs>
92+
93+
## Migrating
94+
95+
If you with to enable this experiments, but you don't want any behavior to
96+
change, you should update any uses of the `CLI_ARGS` variable to use the use the
97+
`join` function to convert the array back to a string. For example:
98+
99+
<Tabs defaultValue="2"
100+
values={[
101+
{label: 'Before', value: '1'},
102+
{label: 'After', value: '2'}
103+
]}>
104+
105+
<TabItem value="1">
106+
107+
```yaml
108+
version: '3'
109+
110+
tasks:
111+
example:
112+
cmds:
113+
- echo "CLI_ARGS: {{.CLI_ARGS}}"
114+
```
115+
116+
</TabItem>
117+
<TabItem value="2">
118+
119+
```yaml
120+
version: '3'
121+
122+
tasks:
123+
example:
124+
cmds:
125+
- echo "CLI_ARGS: {{join " " .CLI_ARGS}}"
126+
```
127+
128+
</TabItem>
129+
</Tabs>
130+
131+
Otherwise, if you want the new behavior, you can simply enable the experiment
132+
and update your tasks to use the new array of arguments.
133+
134+
{/* prettier-ignore-start */}
135+
[enabling-experiments]: ./experiments.mdx#enabling-experiments
136+
{/* prettier-ignore-end */}

0 commit comments

Comments
 (0)