8
8
"path/filepath"
9
9
"strings"
10
10
11
+ "github.com/hashicorp/hcl/v2/ext/typeexpr"
12
+
11
13
"github.com/hashicorp/hcl/v2"
12
14
"github.com/hashicorp/hcl/v2/gohcl"
13
15
"github.com/hashicorp/hcl/v2/hclparse"
@@ -257,6 +259,8 @@ func newApp(app *App, cc *HCL2Config, importDir func(string) (*App, error)) (*Ap
257
259
258
260
var conf * HCL2Config
259
261
262
+ var globals []JobSpec
263
+
260
264
jobByName := map [string ]JobSpec {}
261
265
for _ , j := range jobs {
262
266
jobByName [j .Name ] = j
@@ -288,7 +292,10 @@ func newApp(app *App, cc *HCL2Config, importDir func(string) (*App, error)) (*Ap
288
292
//
289
293
// If the user-side has a global parameter/option that has the same name as the library-side,
290
294
// their types MUST match.
291
- merged := mergeJobs (importedJob , j )
295
+ merged , err := mergeParamsAndOpts (importedJob , j )
296
+ if err != nil {
297
+ return nil , fmt .Errorf ("merging globals: %w" , err )
298
+ }
292
299
293
300
merged .Name = ""
294
301
@@ -302,6 +309,9 @@ func newApp(app *App, cc *HCL2Config, importDir func(string) (*App, error)) (*Ap
302
309
} else {
303
310
// Import the top-level job in the library as the non-top-level job on the user side
304
311
newJobName = j .Name
312
+
313
+ // And merge global parameters and options
314
+ globals = append (globals , importedJob )
305
315
}
306
316
307
317
importedJob .Name = newJobName
@@ -316,12 +326,27 @@ func newApp(app *App, cc *HCL2Config, importDir func(string) (*App, error)) (*Ap
316
326
}
317
327
}
318
328
329
+ root := jobByName ["" ]
330
+
331
+ for _ , g := range globals {
332
+ merged , err := mergeParamsAndOpts (g , root )
333
+ if err != nil {
334
+ return nil , fmt .Errorf ("merging globals: %w" , err )
335
+ }
336
+
337
+ root = * merged
338
+ }
339
+
340
+ jobByName ["" ] = root
341
+
319
342
if conf == nil {
320
343
conf = cc
321
344
}
322
345
323
346
app .Config = conf
324
347
348
+ app .Config .JobSpec = root
349
+
325
350
app .JobByName = jobByName
326
351
327
352
var newJobs []JobSpec
@@ -335,7 +360,7 @@ func newApp(app *App, cc *HCL2Config, importDir func(string) (*App, error)) (*Ap
335
360
return app , nil
336
361
}
337
362
338
- func mergeJobs (src JobSpec , dst JobSpec ) * JobSpec {
363
+ func mergeParamsAndOpts (src JobSpec , dst JobSpec ) ( * JobSpec , error ) {
339
364
paramMap := map [string ]Parameter {}
340
365
optMap := map [string ]OptionSpec {}
341
366
@@ -348,14 +373,38 @@ func mergeJobs(src JobSpec, dst JobSpec) *JobSpec {
348
373
}
349
374
350
375
for _ , p := range src .Parameters {
351
- if _ , exists := paramMap [p .Name ]; ! exists {
376
+ if existing , exists := paramMap [p .Name ]; ! exists {
352
377
paramMap [p .Name ] = p
378
+ } else {
379
+ exTy , err := typeexpr .TypeConstraint (existing .Type )
380
+ if err != nil {
381
+ return nil , fmt .Errorf ("parsing parameter type: %w" , err )
382
+ }
383
+ toTy , err := typeexpr .TypeConstraint (p .Type )
384
+ if err != nil {
385
+ return nil , fmt .Errorf ("parsing parameter type: %w" , err )
386
+ }
387
+ if exTy != toTy {
388
+ return nil , fmt .Errorf ("imported job %q has incompatible parameter %q: needs type of %v, encountered %v" , src .Name , p .Name , exTy .GoString (), toTy .GoString ())
389
+ }
353
390
}
354
391
}
355
392
356
393
for _ , o := range src .Options {
357
- if _ , exists := optMap [o .Name ]; ! exists {
394
+ if existing , exists := optMap [o .Name ]; ! exists {
358
395
optMap [o .Name ] = o
396
+ } else {
397
+ exTy , err := typeexpr .TypeConstraint (existing .Type )
398
+ if err != nil {
399
+ return nil , fmt .Errorf ("parsing option type: %w" , err )
400
+ }
401
+ toTy , err := typeexpr .TypeConstraint (o .Type )
402
+ if err != nil {
403
+ return nil , fmt .Errorf ("parsing option type: %w" , err )
404
+ }
405
+ if exTy != toTy {
406
+ return nil , fmt .Errorf ("imported job %q has incompatible option %q: needs type of %v, encountered %v" , src .Name , o .Name , exTy .GoString (), toTy .GoString ())
407
+ }
359
408
}
360
409
}
361
410
@@ -375,5 +424,5 @@ func mergeJobs(src JobSpec, dst JobSpec) *JobSpec {
375
424
dst .Parameters = params
376
425
dst .Options = opts
377
426
378
- return & dst
427
+ return & dst , nil
379
428
}
0 commit comments