@@ -85,49 +85,82 @@ func (v *Var) UnmarshalYAML(unmarshal func(interface{}) error) error {
8585}
8686
8787// getVariables returns fully resolved variables following the priority order:
88- // 1. Task variables
89- // 2. Call variables
90- // 3. Taskvars file variables
91- // 4. Environment variables
88+ // 1. Call variables (should already have been resolved)
89+ // 2. Environment (should not need to be resolved)
90+ // 3. Task variables, resolved with access to:
91+ // - call, taskvars and environment variables
92+ // 4. Taskvars variables, resolved with access to:
93+ // - environment variables
9294func (e * Executor ) getVariables (call Call ) (Vars , error ) {
9395 t , ok := e .Tasks [call .Task ]
9496 if ! ok {
95- return nil , & taskNotFoundError {taskName : call .Task }
96- }
97- vr := varResolver {e : e , vars : getEnvironmentVariables ()}
98- vr .merge (e .taskvars )
99- vr .merge (e .taskvars )
100- vr .merge (call .Vars )
101- vr .merge (call .Vars )
102- vr .merge (t .Vars )
103- vr .merge (t .Vars )
104- return vr .vars , vr .err
105- }
106-
107- type varResolver struct {
108- e * Executor
109- vars Vars
110- err error
111- }
97+ return nil , & taskNotFoundError {call .Task }
98+ }
11299
113- func (vr * varResolver ) merge (vars Vars ) {
114- if vr .err != nil {
115- return
100+ merge := func (dest Vars , srcs ... Vars ) {
101+ for _ , src := range srcs {
102+ for k , v := range src {
103+ dest [k ] = v
104+ }
105+ }
116106 }
117- r := varReplacer {vars : vr .vars }
118- for k , v := range vars {
119- v = Var {
120- Static : r .replace (v .Static ),
121- Sh : r .replace (v .Sh ),
107+ varsKeys := func (srcs ... Vars ) []string {
108+ m := make (map [string ]struct {})
109+ for _ , src := range srcs {
110+ for k := range src {
111+ m [k ] = struct {}{}
112+ }
122113 }
123- static , err := vr .e .handleShVar (v )
124- if err != nil {
125- vr .err = err
126- return
114+ lst := make ([]string , 0 , len (m ))
115+ for k := range m {
116+ lst = append (lst , k )
127117 }
128- vr . vars [ k ] = Var { Static : static }
118+ return lst
129119 }
130- vr .err = r .err
120+ replaceVars := func (dest Vars , keys []string ) error {
121+ r := varReplacer {vars : dest }
122+ for _ , k := range keys {
123+ v := dest [k ]
124+ dest [k ] = Var {
125+ Static : r .replace (v .Static ),
126+ Sh : r .replace (v .Sh ),
127+ }
128+ }
129+ return r .err
130+ }
131+ resolveShell := func (dest Vars , keys []string ) error {
132+ for _ , k := range keys {
133+ v := dest [k ]
134+ static , err := e .handleShVar (v )
135+ if err != nil {
136+ return err
137+ }
138+ dest [k ] = Var {Static : static }
139+ }
140+ return nil
141+ }
142+ update := func (dest Vars , srcs ... Vars ) error {
143+ merge (dest , srcs ... )
144+ // updatedKeys ensures template evaluation is run only once.
145+ updatedKeys := varsKeys (srcs ... )
146+ if err := replaceVars (dest , updatedKeys ); err != nil {
147+ return err
148+ }
149+ return resolveShell (dest , updatedKeys )
150+ }
151+
152+ // Resolve taskvars variables to "result" with environment override variables.
153+ override := getEnvironmentVariables ()
154+ result := make (Vars , len (e .taskvars )+ len (t .Vars )+ len (override ))
155+ if err := update (result , e .taskvars , override ); err != nil {
156+ return nil , err
157+ }
158+ // Resolve task variables to "result" with environment and call override variables.
159+ merge (override , call .Vars )
160+ if err := update (result , t .Vars , override ); err != nil {
161+ return nil , err
162+ }
163+ return result , nil
131164}
132165
133166func (e * Executor ) handleShVar (v Var ) (string , error ) {
0 commit comments