mirror of
https://github.com/go-task/task.git
synced 2026-08-29 10:08:27 +02:00
fix: support .MATCH in wildcard include vars
This commit is contained in:
@@ -11,6 +11,9 @@
|
||||
(#2184 by @jubr).
|
||||
- Fixed `joinUrl` collapsing the `//` in a URL scheme (e.g. producing
|
||||
`http:/localhost` instead of `http://localhost`) (#2915 by @vsaraikin).
|
||||
- Fixed `.MATCH` not being available in the `vars` of an include declared with a
|
||||
wildcard namespace (e.g. `'stack:*'`), so `{{index .MATCH 0}}` can now be used
|
||||
to feed captured segments into the included Taskfile (#2732 by @vmaerten).
|
||||
|
||||
## v3.52.0 - 2026-07-02
|
||||
|
||||
|
||||
@@ -115,6 +115,15 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (*
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// MATCH is populated by GetTask from the wildcard match. Expose it early so
|
||||
// that include vars coming from a wildcard include namespace can reference
|
||||
// the captured segments, e.g. `{{index .MATCH 0}}`. It is re-set identically
|
||||
// when call.Vars is ranged below, which is harmless.
|
||||
if call != nil && call.Vars != nil {
|
||||
if match, ok := call.Vars.Get("MATCH"); ok {
|
||||
result.Set("MATCH", match)
|
||||
}
|
||||
}
|
||||
if t != nil {
|
||||
for k, v := range t.IncludeVars.All() {
|
||||
if err := rangeFunc(k, v); err != nil {
|
||||
|
||||
49
task_test.go
49
task_test.go
@@ -3040,6 +3040,55 @@ func TestWildcard(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncludesWildcardVars(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
call string
|
||||
expectedOutput string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "match feeds include var",
|
||||
call: "stack:prod:deploy",
|
||||
expectedOutput: "Deploying to prod\n",
|
||||
},
|
||||
{
|
||||
name: "different match",
|
||||
call: "stack:staging:deploy",
|
||||
expectedOutput: "Deploying to staging\n",
|
||||
},
|
||||
{
|
||||
name: "no match",
|
||||
call: "stack:deploy",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.call, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var buff bytes.Buffer
|
||||
e := task.NewExecutor(
|
||||
task.WithDir("testdata/includes_wildcard_vars"),
|
||||
task.WithStdout(&buff),
|
||||
task.WithStderr(&buff),
|
||||
task.WithSilent(true),
|
||||
task.WithForce(true),
|
||||
)
|
||||
require.NoError(t, e.Setup())
|
||||
if test.wantErr {
|
||||
require.Error(t, e.Run(t.Context(), &task.Call{Task: test.call}))
|
||||
return
|
||||
}
|
||||
require.NoError(t, e.Run(t.Context(), &task.Call{Task: test.call}))
|
||||
assert.Equal(t, test.expectedOutput, buff.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// enableExperimentForTest enables the experiment behind pointer e for the duration of test t and sub-tests,
|
||||
// with the experiment being restored to its previous state when tests complete.
|
||||
//
|
||||
|
||||
7
testdata/includes_wildcard_vars/Taskfile.yml
vendored
Normal file
7
testdata/includes_wildcard_vars/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
version: "3"
|
||||
|
||||
includes:
|
||||
'stack:*':
|
||||
taskfile: ./stack/Taskfile.yml
|
||||
vars:
|
||||
ENV: '{{index .MATCH 0}}'
|
||||
6
testdata/includes_wildcard_vars/stack/Taskfile.yml
vendored
Normal file
6
testdata/includes_wildcard_vars/stack/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
version: "3"
|
||||
|
||||
tasks:
|
||||
deploy:
|
||||
cmds:
|
||||
- echo "Deploying to {{.ENV}}"
|
||||
@@ -461,6 +461,31 @@ includes:
|
||||
DOCKER_IMAGE: frontend_image
|
||||
```
|
||||
|
||||
You can also use a [wildcard](#wildcard-arguments) in the include's namespace and
|
||||
reference the captured segments through the `.MATCH` variable when setting the
|
||||
include vars. This lets a single include be reused across many namespaces without
|
||||
the included Taskfile needing to know how the value is extracted:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
'stack:*':
|
||||
taskfile: ./taskfiles/Stack.yml
|
||||
vars:
|
||||
ENV: '{{index .MATCH 0}}'
|
||||
```
|
||||
|
||||
Running `task stack:prod:deploy` sets `ENV` to `prod` for the included Taskfile.
|
||||
|
||||
::: info
|
||||
|
||||
`.MATCH` is only available in the include's `vars`. The `taskfile` and `dir`
|
||||
fields are resolved when Taskfiles are loaded and merged, before any task is
|
||||
called, so no wildcard has been matched yet at that point.
|
||||
|
||||
:::
|
||||
|
||||
### Namespace aliases
|
||||
|
||||
When including a Taskfile, you can give the namespace a list of `aliases`. This
|
||||
|
||||
Reference in New Issue
Block a user