promptDepsVars traverses the dependency tree, collects all missing required variables, and prompts for them upfront. This is used for deps which execute in parallel, so all prompts must happen before execution to avoid interleaving. Prompted values are stored in e.promptedVars for injection into tas
(calls []*Call)
| 28 | // in parallel, so all prompts must happen before execution to avoid interleaving. |
| 29 | // Prompted values are stored in e.promptedVars for injection into task calls. |
| 30 | func (e *Executor) promptDepsVars(calls []*Call) error { |
| 31 | if !e.canPrompt() { |
| 32 | return nil |
| 33 | } |
| 34 | |
| 35 | // Collect all missing vars from the dependency tree |
| 36 | visited := make(map[string]bool) |
| 37 | varsMap := orderedmap.NewOrderedMap[string, *ast.VarsWithValidation]() |
| 38 | |
| 39 | var collect func(call *Call) error |
| 40 | collect = func(call *Call) error { |
| 41 | compiledTask, err := e.FastCompiledTask(call) |
| 42 | if err != nil { |
| 43 | return err |
| 44 | } |
| 45 | |
| 46 | for _, v := range getMissingRequiredVars(compiledTask) { |
| 47 | if !varsMap.Has(v.Name) { |
| 48 | varsMap.Set(v.Name, v) |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | // Check visited AFTER collecting vars to handle duplicate task calls with different vars |
| 53 | if visited[call.Task] { |
| 54 | return nil |
| 55 | } |
| 56 | visited[call.Task] = true |
| 57 | |
| 58 | for _, dep := range compiledTask.Deps { |
| 59 | depCall := &Call{ |
| 60 | Task: dep.Task, |
| 61 | Vars: dep.Vars, |
| 62 | Silent: dep.Silent, |
| 63 | } |
| 64 | if err := collect(depCall); err != nil { |
| 65 | return err |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | return nil |
| 70 | } |
| 71 | |
| 72 | for _, call := range calls { |
| 73 | if err := collect(call); err != nil { |
| 74 | return err |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | if varsMap.Len() == 0 { |
| 79 | return nil |
| 80 | } |
| 81 | |
| 82 | prompter := e.newPrompter() |
| 83 | e.promptedVars = ast.NewVars() |
| 84 | |
| 85 | for v := range varsMap.Values() { |
| 86 | value, err := prompter.Prompt(v.Name, getEnumValues(v.Enum)) |
| 87 | if err != nil { |
no test coverage detected