@@ -698,30 +698,30 @@ type Target struct {
698
698
// Inherits is the only field that cannot be overridden with --set
699
699
Inherits []string `json:"inherits,omitempty" hcl:"inherits,optional" cty:"inherits"`
700
700
701
- Annotations []string `json:"annotations,omitempty" hcl:"annotations,optional" cty:"annotations"`
702
- Attest []string `json:"attest,omitempty" hcl:"attest,optional" cty:"attest"`
703
- Context * string `json:"context,omitempty" hcl:"context,optional" cty:"context"`
704
- Contexts map [string ]string `json:"contexts,omitempty" hcl:"contexts,optional" cty:"contexts"`
705
- Dockerfile * string `json:"dockerfile,omitempty" hcl:"dockerfile,optional" cty:"dockerfile"`
706
- DockerfileInline * string `json:"dockerfile-inline,omitempty" hcl:"dockerfile-inline,optional" cty:"dockerfile-inline"`
707
- Args map [string ]* string `json:"args,omitempty" hcl:"args,optional" cty:"args"`
708
- Labels map [string ]* string `json:"labels,omitempty" hcl:"labels,optional" cty:"labels"`
709
- Tags []string `json:"tags,omitempty" hcl:"tags,optional" cty:"tags"`
710
- CacheFrom [] * buildflags.CacheOptionsEntry `json:"cache-from,omitempty" hcl:"cache-from,optional" cty:"cache-from"`
711
- CacheTo [] * buildflags.CacheOptionsEntry `json:"cache-to,omitempty" hcl:"cache-to,optional" cty:"cache-to"`
712
- Target * string `json:"target,omitempty" hcl:"target,optional" cty:"target"`
713
- Secrets [] * buildflags.Secret `json:"secret,omitempty" hcl:"secret,optional" cty:"secret"`
714
- SSH [] * buildflags.SSH `json:"ssh,omitempty" hcl:"ssh,optional" cty:"ssh"`
715
- Platforms []string `json:"platforms,omitempty" hcl:"platforms,optional" cty:"platforms"`
716
- Outputs [] * buildflags.ExportEntry `json:"output,omitempty" hcl:"output,optional" cty:"output"`
717
- Pull * bool `json:"pull,omitempty" hcl:"pull,optional" cty:"pull"`
718
- NoCache * bool `json:"no-cache,omitempty" hcl:"no-cache,optional" cty:"no-cache"`
719
- NetworkMode * string `json:"network,omitempty" hcl:"network,optional" cty:"network"`
720
- NoCacheFilter []string `json:"no-cache-filter,omitempty" hcl:"no-cache-filter,optional" cty:"no-cache-filter"`
721
- ShmSize * string `json:"shm-size,omitempty" hcl:"shm-size,optional"`
722
- Ulimits []string `json:"ulimits,omitempty" hcl:"ulimits,optional"`
723
- Call * string `json:"call,omitempty" hcl:"call,optional" cty:"call"`
724
- Entitlements []string `json:"entitlements,omitempty" hcl:"entitlements,optional" cty:"entitlements"`
701
+ Annotations []string `json:"annotations,omitempty" hcl:"annotations,optional" cty:"annotations"`
702
+ Attest []string `json:"attest,omitempty" hcl:"attest,optional" cty:"attest"`
703
+ Context * string `json:"context,omitempty" hcl:"context,optional" cty:"context"`
704
+ Contexts map [string ]string `json:"contexts,omitempty" hcl:"contexts,optional" cty:"contexts"`
705
+ Dockerfile * string `json:"dockerfile,omitempty" hcl:"dockerfile,optional" cty:"dockerfile"`
706
+ DockerfileInline * string `json:"dockerfile-inline,omitempty" hcl:"dockerfile-inline,optional" cty:"dockerfile-inline"`
707
+ Args map [string ]* string `json:"args,omitempty" hcl:"args,optional" cty:"args"`
708
+ Labels map [string ]* string `json:"labels,omitempty" hcl:"labels,optional" cty:"labels"`
709
+ Tags []string `json:"tags,omitempty" hcl:"tags,optional" cty:"tags"`
710
+ CacheFrom buildflags.CacheOptions `json:"cache-from,omitempty" hcl:"cache-from,optional" cty:"cache-from"`
711
+ CacheTo buildflags.CacheOptions `json:"cache-to,omitempty" hcl:"cache-to,optional" cty:"cache-to"`
712
+ Target * string `json:"target,omitempty" hcl:"target,optional" cty:"target"`
713
+ Secrets buildflags.Secrets `json:"secret,omitempty" hcl:"secret,optional" cty:"secret"`
714
+ SSH buildflags.SSHKeys `json:"ssh,omitempty" hcl:"ssh,optional" cty:"ssh"`
715
+ Platforms []string `json:"platforms,omitempty" hcl:"platforms,optional" cty:"platforms"`
716
+ Outputs buildflags.Exports `json:"output,omitempty" hcl:"output,optional" cty:"output"`
717
+ Pull * bool `json:"pull,omitempty" hcl:"pull,optional" cty:"pull"`
718
+ NoCache * bool `json:"no-cache,omitempty" hcl:"no-cache,optional" cty:"no-cache"`
719
+ NetworkMode * string `json:"network,omitempty" hcl:"network,optional" cty:"network"`
720
+ NoCacheFilter []string `json:"no-cache-filter,omitempty" hcl:"no-cache-filter,optional" cty:"no-cache-filter"`
721
+ ShmSize * string `json:"shm-size,omitempty" hcl:"shm-size,optional"`
722
+ Ulimits []string `json:"ulimits,omitempty" hcl:"ulimits,optional"`
723
+ Call * string `json:"call,omitempty" hcl:"call,optional" cty:"call"`
724
+ Entitlements []string `json:"entitlements,omitempty" hcl:"entitlements,optional" cty:"entitlements"`
725
725
// IMPORTANT: if you add more fields here, do not forget to update newOverrides/AddOverrides and docs/bake-reference.md.
726
726
727
727
// linked is a private field to mark a target used as a linked one
@@ -739,12 +739,12 @@ func (t *Target) normalize() {
739
739
t .Annotations = removeDupesStr (t .Annotations )
740
740
t .Attest = removeAttestDupes (t .Attest )
741
741
t .Tags = removeDupesStr (t .Tags )
742
- t .Secrets = removeDupes ( t .Secrets )
743
- t .SSH = removeDupes ( t .SSH )
742
+ t .Secrets = t .Secrets . Normalize ( )
743
+ t .SSH = t .SSH . Normalize ( )
744
744
t .Platforms = removeDupesStr (t .Platforms )
745
- t .CacheFrom = removeDupes ( t .CacheFrom )
746
- t .CacheTo = removeDupes ( t .CacheTo )
747
- t .Outputs = removeDupes ( t .Outputs )
745
+ t .CacheFrom = t .CacheFrom . Normalize ( )
746
+ t .CacheTo = t .CacheTo . Normalize ( )
747
+ t .Outputs = t .Outputs . Normalize ( )
748
748
t .NoCacheFilter = removeDupesStr (t .NoCacheFilter )
749
749
t .Ulimits = removeDupesStr (t .Ulimits )
750
750
@@ -815,16 +815,16 @@ func (t *Target) Merge(t2 *Target) {
815
815
t .Attest = removeAttestDupes (t .Attest )
816
816
}
817
817
if t2 .Secrets != nil { // merge
818
- t .Secrets = append ( t .Secrets , t2 .Secrets ... )
818
+ t .Secrets = t .Secrets . Merge ( t2 .Secrets )
819
819
}
820
820
if t2 .SSH != nil { // merge
821
- t .SSH = append ( t .SSH , t2 .SSH ... )
821
+ t .SSH = t .SSH . Merge ( t2 .SSH )
822
822
}
823
823
if t2 .Platforms != nil { // no merge
824
824
t .Platforms = t2 .Platforms
825
825
}
826
826
if t2 .CacheFrom != nil { // merge
827
- t .CacheFrom = append ( t .CacheFrom , t2 .CacheFrom ... )
827
+ t .CacheFrom = t .CacheFrom . Merge ( t2 .CacheFrom )
828
828
}
829
829
if t2 .CacheTo != nil { // no merge
830
830
t .CacheTo = t2 .CacheTo
@@ -1333,30 +1333,19 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
1333
1333
}
1334
1334
bo .Platforms = platforms
1335
1335
1336
- secrets := make ([]* controllerapi.Secret , len (t .Secrets ))
1337
- for i , s := range t .Secrets {
1338
- secrets [i ] = s .ToPB ()
1339
- }
1340
- bo .SecretSpecs = secrets
1341
-
1342
- secretAttachment , err := controllerapi .CreateSecrets (secrets )
1336
+ bo .SecretSpecs = t .Secrets .ToPB ()
1337
+ secretAttachment , err := controllerapi .CreateSecrets (bo .SecretSpecs )
1343
1338
if err != nil {
1344
1339
return nil , err
1345
1340
}
1346
1341
bo .Session = append (bo .Session , secretAttachment )
1347
1342
1348
- var sshSpecs []* controllerapi.SSH
1349
- if len (t .SSH ) > 0 {
1350
- sshSpecs := make ([]* controllerapi.SSH , len (t .SSH ))
1351
- for i , s := range t .SSH {
1352
- sshSpecs [i ] = s .ToPB ()
1353
- }
1354
- } else if buildflags .IsGitSSH (bi .ContextPath ) || (inp != nil && buildflags .IsGitSSH (inp .URL )) {
1355
- sshSpecs = []* controllerapi.SSH {{ID : "default" }}
1343
+ bo .SSHSpecs = t .SSH .ToPB ()
1344
+ if len (bo .SSHSpecs ) == 0 && buildflags .IsGitSSH (bi .ContextPath ) || (inp != nil && buildflags .IsGitSSH (inp .URL )) {
1345
+ bo .SSHSpecs = []* controllerapi.SSH {{ID : "default" }}
1356
1346
}
1357
- bo .SSHSpecs = sshSpecs
1358
1347
1359
- sshAttachment , err := controllerapi .CreateSSH (sshSpecs )
1348
+ sshAttachment , err := controllerapi .CreateSSH (bo . SSHSpecs )
1360
1349
if err != nil {
1361
1350
return nil , err
1362
1351
}
@@ -1372,24 +1361,14 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
1372
1361
}
1373
1362
}
1374
1363
1375
- cacheImports := make ([]* controllerapi.CacheOptionsEntry , len (t .CacheFrom ))
1376
- for i , ci := range t .CacheFrom {
1377
- cacheImports [i ] = ci .ToPB ()
1378
- }
1379
- bo .CacheFrom = controllerapi .CreateCaches (cacheImports )
1380
-
1381
- cacheExports := make ([]* controllerapi.CacheOptionsEntry , len (t .CacheTo ))
1382
- for i , ce := range t .CacheTo {
1383
- cacheExports [i ] = ce .ToPB ()
1364
+ if t .CacheFrom != nil {
1365
+ bo .CacheFrom = controllerapi .CreateCaches (t .CacheFrom .ToPB ())
1384
1366
}
1385
- bo .CacheTo = controllerapi .CreateCaches (cacheExports )
1386
-
1387
- outputs := make ([]* controllerapi.ExportEntry , len (t .Outputs ))
1388
- for i , output := range t .Outputs {
1389
- outputs [i ] = output .ToPB ()
1367
+ if t .CacheTo != nil {
1368
+ bo .CacheTo = controllerapi .CreateCaches (t .CacheTo .ToPB ())
1390
1369
}
1391
1370
1392
- bo .Exports , bo .ExportsLocalPathsTemporary , err = controllerapi .CreateExports (outputs )
1371
+ bo .Exports , bo .ExportsLocalPathsTemporary , err = controllerapi .CreateExports (t . Outputs . ToPB () )
1393
1372
if err != nil {
1394
1373
return nil , err
1395
1374
}
@@ -1434,34 +1413,6 @@ func defaultTarget() *Target {
1434
1413
return & Target {}
1435
1414
}
1436
1415
1437
- type comparable [E any ] interface {
1438
- Equal (other E ) bool
1439
- }
1440
-
1441
- func removeDupes [E comparable [E ]](s []E ) []E {
1442
- // Move backwards through the slice.
1443
- // For each element, any elements after the current element are unique.
1444
- // If we find our current element conflicts with an existing element,
1445
- // then we swap the offender with the end of the slice and chop it off.
1446
-
1447
- // Start at the second to last element.
1448
- // The last element is always unique.
1449
- for i := len (s ) - 2 ; i >= 0 ; i -- {
1450
- elem := s [i ]
1451
- // Check for duplicates after our current element.
1452
- for j := i + 1 ; j < len (s ); j ++ {
1453
- if elem .Equal (s [j ]) {
1454
- // Found a duplicate, exchange the
1455
- // duplicate with the last element.
1456
- s [j ], s [len (s )- 1 ] = s [len (s )- 1 ], s [j ]
1457
- s = s [:len (s )- 1 ]
1458
- break
1459
- }
1460
- }
1461
- }
1462
- return s
1463
- }
1464
-
1465
1416
func removeDupesStr (s []string ) []string {
1466
1417
i := 0
1467
1418
seen := make (map [string ]struct {}, len (s ))
@@ -1616,6 +1567,10 @@ type arrValue[B any] interface {
1616
1567
func parseArrValue [T any , PT arrValue [T ]](s []string ) ([]* T , error ) {
1617
1568
outputs := make ([]* T , 0 , len (s ))
1618
1569
for _ , text := range s {
1570
+ if text == "" {
1571
+ continue
1572
+ }
1573
+
1619
1574
output := new (T )
1620
1575
if err := PT (output ).UnmarshalText ([]byte (text )); err != nil {
1621
1576
return nil , err
@@ -1625,9 +1580,13 @@ func parseArrValue[T any, PT arrValue[T]](s []string) ([]*T, error) {
1625
1580
return outputs , nil
1626
1581
}
1627
1582
1628
- func parseCacheArrValues (s []string ) ([] * buildflags.CacheOptionsEntry , error ) {
1629
- outs := make ([] * buildflags.CacheOptionsEntry , 0 , len ( s ))
1583
+ func parseCacheArrValues (s []string ) (buildflags.CacheOptions , error ) {
1584
+ var outs buildflags.CacheOptions
1630
1585
for _ , in := range s {
1586
+ if in == "" {
1587
+ continue
1588
+ }
1589
+
1631
1590
if ! strings .Contains (in , "=" ) {
1632
1591
// This is ref only format. Each field in the CSV is its own entry.
1633
1592
fields , err := csvvalue .Fields (in , nil )
0 commit comments