2023-06-30 02:13:41 +01:00
|
|
|
package task
|
|
|
|
|
|
|
|
|
|
import (
|
2024-10-18 18:16:57 +02:00
|
|
|
"slices"
|
|
|
|
|
|
2023-06-30 02:13:41 +01:00
|
|
|
"github.com/go-task/task/v3/errors"
|
2025-12-13 11:05:18 +01:00
|
|
|
"github.com/go-task/task/v3/internal/prompt"
|
|
|
|
|
"github.com/go-task/task/v3/internal/term"
|
2023-12-29 20:32:03 +00:00
|
|
|
"github.com/go-task/task/v3/taskfile/ast"
|
2023-06-30 02:13:41 +01:00
|
|
|
)
|
|
|
|
|
|
2025-12-13 12:01:36 +01:00
|
|
|
// promptForInteractiveVars prompts the user for any missing required variables
|
2025-12-13 11:05:18 +01:00
|
|
|
// and injects them into the call's Vars. It returns true if any variables were
|
|
|
|
|
// prompted for (meaning the task needs to be recompiled).
|
|
|
|
|
func (e *Executor) promptForInteractiveVars(t *ast.Task, call *Call) (bool, error) {
|
|
|
|
|
if t.Requires == nil || len(t.Requires.Vars) == 0 {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 12:01:36 +01:00
|
|
|
// Don't prompt if interactive mode is disabled
|
|
|
|
|
if !e.Interactive {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 11:05:18 +01:00
|
|
|
// Don't prompt if NoTTY is set or we're not in a terminal
|
|
|
|
|
if e.NoTTY || (!e.AssumeTerm && !term.IsTerminal()) {
|
|
|
|
|
return false, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prompter := prompt.New()
|
|
|
|
|
var prompted bool
|
|
|
|
|
|
|
|
|
|
for _, requiredVar := range t.Requires.Vars {
|
|
|
|
|
// Skip if already set
|
|
|
|
|
if _, ok := t.Vars.Get(requiredVar.Name); ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var value string
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
if len(requiredVar.Enum) > 0 {
|
|
|
|
|
value, err = prompter.Select(requiredVar.Name, requiredVar.Enum)
|
|
|
|
|
} else {
|
|
|
|
|
value, err = prompter.Text(requiredVar.Name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
if errors.Is(err, prompt.ErrCancelled) {
|
|
|
|
|
return false, &errors.TaskCancelledByUserError{TaskName: call.Task}
|
|
|
|
|
}
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Inject into call.Vars
|
|
|
|
|
if call.Vars == nil {
|
|
|
|
|
call.Vars = ast.NewVars()
|
|
|
|
|
}
|
|
|
|
|
call.Vars.Set(requiredVar.Name, ast.Var{Value: value})
|
|
|
|
|
prompted = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return prompted, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-30 18:27:16 -03:00
|
|
|
func (e *Executor) areTaskRequiredVarsSet(t *ast.Task) error {
|
2023-06-30 02:13:41 +01:00
|
|
|
if t.Requires == nil || len(t.Requires.Vars) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-20 20:08:14 +01:00
|
|
|
var missingVars []errors.MissingVar
|
2023-06-30 02:13:41 +01:00
|
|
|
for _, requiredVar := range t.Requires.Vars {
|
2025-02-08 17:29:36 +01:00
|
|
|
_, ok := t.Vars.Get(requiredVar.Name)
|
2024-12-30 17:54:36 +00:00
|
|
|
if !ok {
|
2025-02-20 20:08:14 +01:00
|
|
|
missingVars = append(missingVars, errors.MissingVar{
|
|
|
|
|
Name: requiredVar.Name,
|
|
|
|
|
AllowedValues: requiredVar.Enum,
|
|
|
|
|
})
|
2023-06-30 02:13:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(missingVars) > 0 {
|
2025-02-20 20:08:14 +01:00
|
|
|
return &errors.TaskMissingRequiredVarsError{
|
2023-06-30 02:13:41 +01:00
|
|
|
TaskName: t.Name(),
|
|
|
|
|
MissingVars: missingVars,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-08 17:29:36 +01:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *Executor) areTaskRequiredVarsAllowedValuesSet(t *ast.Task) error {
|
|
|
|
|
if t.Requires == nil || len(t.Requires.Vars) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var notAllowedValuesVars []errors.NotAllowedVar
|
|
|
|
|
for _, requiredVar := range t.Requires.Vars {
|
|
|
|
|
varValue, _ := t.Vars.Get(requiredVar.Name)
|
|
|
|
|
|
|
|
|
|
value, isString := varValue.Value.(string)
|
|
|
|
|
if isString && requiredVar.Enum != nil && !slices.Contains(requiredVar.Enum, value) {
|
|
|
|
|
notAllowedValuesVars = append(notAllowedValuesVars, errors.NotAllowedVar{
|
|
|
|
|
Value: value,
|
|
|
|
|
Enum: requiredVar.Enum,
|
|
|
|
|
Name: requiredVar.Name,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-18 18:16:57 +02:00
|
|
|
if len(notAllowedValuesVars) > 0 {
|
2025-02-20 20:08:14 +01:00
|
|
|
return &errors.TaskNotAllowedVarsError{
|
2024-10-18 18:16:57 +02:00
|
|
|
TaskName: t.Name(),
|
|
|
|
|
NotAllowedVars: notAllowedValuesVars,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-30 02:13:41 +01:00
|
|
|
return nil
|
|
|
|
|
}
|