feat: support enum.ref in interactive prompts (#2927)

This commit is contained in:
Valentin Maerten
2026-08-03 22:20:10 +02:00
committed by GitHub
parent c5b977ccc1
commit 2e5106bf24
3 changed files with 62 additions and 1 deletions

View File

@@ -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).
- Added support for `enum.ref` in `--interactive` prompts. Required vars using
`enum.ref` now show the selection list like static enums, instead of falling
back to free-form input (#2817 by @vmaerten).
## v3.52.0 - 2026-07-02

View File

@@ -7,6 +7,7 @@ import (
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/input"
"github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/internal/term"
"github.com/go-task/task/v3/taskfile/ast"
)
@@ -45,7 +46,7 @@ func (e *Executor) promptDepsVars(calls []*Call) error {
for _, v := range getMissingRequiredVars(compiledTask) {
if !varsMap.Has(v.Name) {
varsMap.Set(v.Name, v)
varsMap.Set(v.Name, resolveEnumRefForPrompt(v, compiledTask.Vars))
}
}
@@ -216,3 +217,16 @@ func getEnumValues(e *ast.Enum) []string {
}
return e.Value
}
// resolveEnumRefForPrompt returns a copy of v with its enum ref resolved into
// concrete values, so the interactive prompter can show a Select. Refs that
// depend on dynamic vars may not resolve here and fall back to free-form input.
func resolveEnumRefForPrompt(v *ast.VarsWithValidation, vars *ast.Vars) *ast.VarsWithValidation {
if v.Enum == nil || v.Enum.Ref == "" || len(v.Enum.Value) > 0 {
return v
}
vCopy := v.DeepCopy()
cache := &templater.Cache{Vars: vars}
_ = resolveEnumRefs(&ast.Requires{Vars: []*ast.VarsWithValidation{vCopy}}, cache)
return vCopy
}

44
requires_internal_test.go Normal file
View File

@@ -0,0 +1,44 @@
package task
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/go-task/task/v3/taskfile/ast"
)
func TestResolveEnumRefForPrompt(t *testing.T) {
t.Parallel()
vars := ast.NewVars()
vars.Set("ALLOWED_ENVS", ast.Var{Value: []any{"dev", "staging", "prod"}})
t.Run("resolves a static ref into values", func(t *testing.T) {
t.Parallel()
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Ref: ".ALLOWED_ENVS"}}
resolved := resolveEnumRefForPrompt(v, vars)
require.Equal(t, []string{"dev", "staging", "prod"}, getEnumValues(resolved.Enum))
require.Empty(t, v.Enum.Value, "input var must not be mutated")
require.Equal(t, ".ALLOWED_ENVS", v.Enum.Ref)
})
t.Run("leaves an unresolvable ref as-is", func(t *testing.T) {
t.Parallel()
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Ref: ".NONEXISTENT"}}
require.Empty(t, getEnumValues(resolveEnumRefForPrompt(v, vars).Enum))
})
t.Run("passes through a static enum unchanged", func(t *testing.T) {
t.Parallel()
v := &ast.VarsWithValidation{Name: "ENV", Enum: &ast.Enum{Value: []string{"a", "b"}}}
require.Same(t, v, resolveEnumRefForPrompt(v, vars))
})
}