Skip to content

Commit 2e5106b

Browse files
authored
feat: support enum.ref in interactive prompts (#2927)
1 parent c5b977c commit 2e5106b

3 files changed

Lines changed: 62 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
(#2184 by @jubr).
1212
- Fixed `joinUrl` collapsing the `//` in a URL scheme (e.g. producing
1313
`http:/localhost` instead of `http://localhost`) (#2915 by @vsaraikin).
14+
- Added support for `enum.ref` in `--interactive` prompts. Required vars using
15+
`enum.ref` now show the selection list like static enums, instead of falling
16+
back to free-form input (#2817 by @vmaerten).
1417

1518
## v3.52.0 - 2026-07-02
1619

requires.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/go-task/task/v3/errors"
99
"github.com/go-task/task/v3/internal/input"
10+
"github.com/go-task/task/v3/internal/templater"
1011
"github.com/go-task/task/v3/internal/term"
1112
"github.com/go-task/task/v3/taskfile/ast"
1213
)
@@ -45,7 +46,7 @@ func (e *Executor) promptDepsVars(calls []*Call) error {
4546

4647
for _, v := range getMissingRequiredVars(compiledTask) {
4748
if !varsMap.Has(v.Name) {
48-
varsMap.Set(v.Name, v)
49+
varsMap.Set(v.Name, resolveEnumRefForPrompt(v, compiledTask.Vars))
4950
}
5051
}
5152

@@ -216,3 +217,16 @@ func getEnumValues(e *ast.Enum) []string {
216217
}
217218
return e.Value
218219
}
220+
221+
// resolveEnumRefForPrompt returns a copy of v with its enum ref resolved into
222+
// concrete values, so the interactive prompter can show a Select. Refs that
223+
// depend on dynamic vars may not resolve here and fall back to free-form input.
224+
func resolveEnumRefForPrompt(v *ast.VarsWithValidation, vars *ast.Vars) *ast.VarsWithValidation {
225+
if v.Enum == nil || v.Enum.Ref == "" || len(v.Enum.Value) > 0 {
226+
return v
227+
}
228+
vCopy := v.DeepCopy()
229+
cache := &templater.Cache{Vars: vars}
230+
_ = resolveEnumRefs(&ast.Requires{Vars: []*ast.VarsWithValidation{vCopy}}, cache)
231+
return vCopy
232+
}

requires_internal_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package task
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
"github.com/go-task/task/v3/taskfile/ast"
9+
)
10+
11+
func TestResolveEnumRefForPrompt(t *testing.T) {
12+
t.Parallel()
13+
14+
vars := ast.NewVars()
15+
vars.Set("ALLOWED_ENVS", ast.Var{Value: []any{"dev", "staging", "prod"}})
16+
17+
t.Run("resolves a static ref into values", func(t *testing.T) {
18+
t.Parallel()
19+
20+
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Ref: ".ALLOWED_ENVS"}}
21+
22+
resolved := resolveEnumRefForPrompt(v, vars)
23+
24+
require.Equal(t, []string{"dev", "staging", "prod"}, getEnumValues(resolved.Enum))
25+
require.Empty(t, v.Enum.Value, "input var must not be mutated")
26+
require.Equal(t, ".ALLOWED_ENVS", v.Enum.Ref)
27+
})
28+
29+
t.Run("leaves an unresolvable ref as-is", func(t *testing.T) {
30+
t.Parallel()
31+
32+
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Ref: ".NONEXISTENT"}}
33+
34+
require.Empty(t, getEnumValues(resolveEnumRefForPrompt(v, vars).Enum))
35+
})
36+
37+
t.Run("passes through a static enum unchanged", func(t *testing.T) {
38+
t.Parallel()
39+
40+
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Value: []string{"a", "b"}}}
41+
42+
require.Same(t, v, resolveEnumRefForPrompt(v, vars))
43+
})
44+
}

0 commit comments

Comments
 (0)