mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 09:17:49 +08:00
Merge pull request #3031 from crazy-max/bake-set-append
bake: support += operator to append with overrides
This commit is contained in:
commit
9a204c44c3
76
bake/bake.go
76
bake/bake.go
@ -45,6 +45,7 @@ type File struct {
|
|||||||
type Override struct {
|
type Override struct {
|
||||||
Value string
|
Value string
|
||||||
ArrValue []string
|
ArrValue []string
|
||||||
|
Append bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultFilenames() []string {
|
func defaultFilenames() []string {
|
||||||
@ -528,9 +529,12 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
|
|||||||
m := map[string]map[string]Override{}
|
m := map[string]map[string]Override{}
|
||||||
for _, v := range v {
|
for _, v := range v {
|
||||||
parts := strings.SplitN(v, "=", 2)
|
parts := strings.SplitN(v, "=", 2)
|
||||||
keys := strings.SplitN(parts[0], ".", 3)
|
|
||||||
|
skey := strings.TrimSuffix(parts[0], "+")
|
||||||
|
appendTo := strings.HasSuffix(parts[0], "+")
|
||||||
|
keys := strings.SplitN(skey, ".", 3)
|
||||||
if len(keys) < 2 {
|
if len(keys) < 2 {
|
||||||
return nil, errors.Errorf("invalid override key %s, expected target.name", parts[0])
|
return nil, errors.Errorf("invalid override key %s, expected target.name", skey)
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern := keys[0]
|
pattern := keys[0]
|
||||||
@ -543,8 +547,7 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
kk := strings.SplitN(parts[0], ".", 2)
|
okey := strings.Join(keys[1:], ".")
|
||||||
|
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
t, ok := m[name]
|
t, ok := m[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -552,14 +555,15 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
|
|||||||
m[name] = t
|
m[name] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
o := t[kk[1]]
|
override := t[okey]
|
||||||
|
|
||||||
// IMPORTANT: if you add more fields here, do not forget to update
|
// IMPORTANT: if you add more fields here, do not forget to update
|
||||||
// docs/reference/buildx_bake.md (--set) and https://docs.docker.com/build/bake/overrides/
|
// docs/reference/buildx_bake.md (--set) and https://docs.docker.com/build/bake/overrides/
|
||||||
switch keys[1] {
|
switch keys[1] {
|
||||||
case "output", "cache-to", "cache-from", "tags", "platform", "secrets", "ssh", "attest", "entitlements", "network", "annotations":
|
case "output", "cache-to", "cache-from", "tags", "platform", "secrets", "ssh", "attest", "entitlements", "network", "annotations":
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
o.ArrValue = append(o.ArrValue, parts[1])
|
override.Append = appendTo
|
||||||
|
override.ArrValue = append(override.ArrValue, parts[1])
|
||||||
}
|
}
|
||||||
case "args":
|
case "args":
|
||||||
if len(keys) != 3 {
|
if len(keys) != 3 {
|
||||||
@ -570,7 +574,7 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
|
|||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
o.Value = v
|
override.Value = v
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case "contexts":
|
case "contexts":
|
||||||
@ -580,11 +584,11 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error)
|
|||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
o.Value = parts[1]
|
override.Value = parts[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t[kk[1]] = o
|
t[okey] = override
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
@ -896,13 +900,21 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
|
|||||||
}
|
}
|
||||||
t.Labels[keys[1]] = &value
|
t.Labels[keys[1]] = &value
|
||||||
case "tags":
|
case "tags":
|
||||||
t.Tags = o.ArrValue
|
if o.Append {
|
||||||
|
t.Tags = append(t.Tags, o.ArrValue...)
|
||||||
|
} else {
|
||||||
|
t.Tags = o.ArrValue
|
||||||
|
}
|
||||||
case "cache-from":
|
case "cache-from":
|
||||||
cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue)
|
cacheFrom, err := buildflags.ParseCacheEntry(o.ArrValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
t.CacheFrom = cacheFrom
|
if o.Append {
|
||||||
|
t.CacheFrom = t.CacheFrom.Merge(cacheFrom)
|
||||||
|
} else {
|
||||||
|
t.CacheFrom = cacheFrom
|
||||||
|
}
|
||||||
for _, c := range t.CacheFrom {
|
for _, c := range t.CacheFrom {
|
||||||
if c.Type == "local" {
|
if c.Type == "local" {
|
||||||
if v, ok := c.Attrs["src"]; ok {
|
if v, ok := c.Attrs["src"]; ok {
|
||||||
@ -915,7 +927,11 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
t.CacheTo = cacheTo
|
if o.Append {
|
||||||
|
t.CacheTo = t.CacheTo.Merge(cacheTo)
|
||||||
|
} else {
|
||||||
|
t.CacheTo = cacheTo
|
||||||
|
}
|
||||||
for _, c := range t.CacheTo {
|
for _, c := range t.CacheTo {
|
||||||
if c.Type == "local" {
|
if c.Type == "local" {
|
||||||
if v, ok := c.Attrs["dest"]; ok {
|
if v, ok := c.Attrs["dest"]; ok {
|
||||||
@ -932,7 +948,11 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid value for outputs")
|
return errors.Wrap(err, "invalid value for outputs")
|
||||||
}
|
}
|
||||||
t.Secrets = secrets
|
if o.Append {
|
||||||
|
t.Secrets = t.Secrets.Merge(secrets)
|
||||||
|
} else {
|
||||||
|
t.Secrets = secrets
|
||||||
|
}
|
||||||
for _, s := range t.Secrets {
|
for _, s := range t.Secrets {
|
||||||
if s.FilePath != "" {
|
if s.FilePath != "" {
|
||||||
ent.FSRead = append(ent.FSRead, s.FilePath)
|
ent.FSRead = append(ent.FSRead, s.FilePath)
|
||||||
@ -943,18 +963,30 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid value for outputs")
|
return errors.Wrap(err, "invalid value for outputs")
|
||||||
}
|
}
|
||||||
t.SSH = ssh
|
if o.Append {
|
||||||
|
t.SSH = t.SSH.Merge(ssh)
|
||||||
|
} else {
|
||||||
|
t.SSH = ssh
|
||||||
|
}
|
||||||
for _, s := range t.SSH {
|
for _, s := range t.SSH {
|
||||||
ent.FSRead = append(ent.FSRead, s.Paths...)
|
ent.FSRead = append(ent.FSRead, s.Paths...)
|
||||||
}
|
}
|
||||||
case "platform":
|
case "platform":
|
||||||
t.Platforms = o.ArrValue
|
if o.Append {
|
||||||
|
t.Platforms = append(t.Platforms, o.ArrValue...)
|
||||||
|
} else {
|
||||||
|
t.Platforms = o.ArrValue
|
||||||
|
}
|
||||||
case "output":
|
case "output":
|
||||||
outputs, err := parseArrValue[buildflags.ExportEntry](o.ArrValue)
|
outputs, err := parseArrValue[buildflags.ExportEntry](o.ArrValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid value for outputs")
|
return errors.Wrap(err, "invalid value for outputs")
|
||||||
}
|
}
|
||||||
t.Outputs = outputs
|
if o.Append {
|
||||||
|
t.Outputs = t.Outputs.Merge(outputs)
|
||||||
|
} else {
|
||||||
|
t.Outputs = outputs
|
||||||
|
}
|
||||||
for _, o := range t.Outputs {
|
for _, o := range t.Outputs {
|
||||||
if o.Destination != "" {
|
if o.Destination != "" {
|
||||||
ent.FSWrite = append(ent.FSWrite, o.Destination)
|
ent.FSWrite = append(ent.FSWrite, o.Destination)
|
||||||
@ -984,11 +1016,19 @@ func (t *Target) AddOverrides(overrides map[string]Override, ent *EntitlementCon
|
|||||||
}
|
}
|
||||||
t.NoCache = &noCache
|
t.NoCache = &noCache
|
||||||
case "no-cache-filter":
|
case "no-cache-filter":
|
||||||
t.NoCacheFilter = o.ArrValue
|
if o.Append {
|
||||||
|
t.NoCacheFilter = append(t.NoCacheFilter, o.ArrValue...)
|
||||||
|
} else {
|
||||||
|
t.NoCacheFilter = o.ArrValue
|
||||||
|
}
|
||||||
case "shm-size":
|
case "shm-size":
|
||||||
t.ShmSize = &value
|
t.ShmSize = &value
|
||||||
case "ulimits":
|
case "ulimits":
|
||||||
t.Ulimits = o.ArrValue
|
if o.Append {
|
||||||
|
t.Ulimits = append(t.Ulimits, o.ArrValue...)
|
||||||
|
} else {
|
||||||
|
t.Ulimits = o.ArrValue
|
||||||
|
}
|
||||||
case "network":
|
case "network":
|
||||||
t.NetworkMode = &value
|
t.NetworkMode = &value
|
||||||
case "pull":
|
case "pull":
|
||||||
|
@ -37,6 +37,15 @@ target "webapp" {
|
|||||||
annotations = [
|
annotations = [
|
||||||
"index,manifest:org.opencontainers.image.authors=dvdksn"
|
"index,manifest:org.opencontainers.image.authors=dvdksn"
|
||||||
]
|
]
|
||||||
|
attest = [
|
||||||
|
"type=provenance,mode=max"
|
||||||
|
]
|
||||||
|
platforms = [
|
||||||
|
"linux/amd64"
|
||||||
|
]
|
||||||
|
secret = [
|
||||||
|
"id=FOO,env=FOO"
|
||||||
|
]
|
||||||
inherits = ["webDEP"]
|
inherits = ["webDEP"]
|
||||||
}`),
|
}`),
|
||||||
}
|
}
|
||||||
@ -127,6 +136,22 @@ target "webapp" {
|
|||||||
require.Equal(t, []string{"webapp"}, g["default"].Targets)
|
require.Equal(t, []string{"webapp"}, g["default"].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("AttestOverride", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.attest=type=sbom"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, m["webapp"].Attest, 2)
|
||||||
|
require.Equal(t, "provenance", m["webapp"].Attest[0].Type)
|
||||||
|
require.Equal(t, "sbom", m["webapp"].Attest[1].Type)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("AttestAppend", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.attest+=type=sbom"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, m["webapp"].Attest, 2)
|
||||||
|
require.Equal(t, "provenance", m["webapp"].Attest[0].Type)
|
||||||
|
require.Equal(t, "sbom", m["webapp"].Attest[1].Type)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("ContextOverride", func(t *testing.T) {
|
t.Run("ContextOverride", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil, &EntitlementConf{})
|
_, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.context"}, nil, &EntitlementConf{})
|
||||||
@ -148,6 +173,49 @@ target "webapp" {
|
|||||||
require.Equal(t, []string{"webapp"}, g["default"].Targets)
|
require.Equal(t, []string{"webapp"}, g["default"].Targets)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("PlatformOverride", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform=linux/arm64"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"linux/arm64"}, m["webapp"].Platforms)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("PlatformAppend", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"linux/amd64", "linux/arm64"}, m["webapp"].Platforms)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("PlatformAppendMulti", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64", "webapp.platform+=linux/riscv64"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"linux/amd64", "linux/arm64", "linux/riscv64"}, m["webapp"].Platforms)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("PlatformAppendMultiLastOverride", func(t *testing.T) {
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.platform+=linux/arm64", "webapp.platform=linux/riscv64"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"linux/arm64", "linux/riscv64"}, m["webapp"].Platforms)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SecretsOverride", func(t *testing.T) {
|
||||||
|
t.Setenv("FOO", "foo")
|
||||||
|
t.Setenv("BAR", "bar")
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secrets=id=BAR,env=BAR"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, m["webapp"].Secrets, 1)
|
||||||
|
require.Equal(t, "BAR", m["webapp"].Secrets[0].ID)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SecretsAppend", func(t *testing.T) {
|
||||||
|
t.Setenv("FOO", "foo")
|
||||||
|
t.Setenv("BAR", "bar")
|
||||||
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.secrets+=id=BAR,env=BAR"}, nil, &EntitlementConf{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, m["webapp"].Secrets, 2)
|
||||||
|
require.Equal(t, "FOO", m["webapp"].Secrets[0].ID)
|
||||||
|
require.Equal(t, "BAR", m["webapp"].Secrets[1].ID)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("ShmSizeOverride", func(t *testing.T) {
|
t.Run("ShmSizeOverride", func(t *testing.T) {
|
||||||
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, &EntitlementConf{})
|
m, _, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{"webapp.shm-size=256m"}, nil, &EntitlementConf{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -347,19 +347,22 @@ is defined in https://golang.org/pkg/path/#Match.
|
|||||||
```console
|
```console
|
||||||
$ docker buildx bake --set target.args.mybuildarg=value
|
$ docker buildx bake --set target.args.mybuildarg=value
|
||||||
$ docker buildx bake --set target.platform=linux/arm64
|
$ docker buildx bake --set target.platform=linux/arm64
|
||||||
$ docker buildx bake --set foo*.args.mybuildarg=value # overrides build arg for all targets starting with 'foo'
|
$ docker buildx bake --set foo*.args.mybuildarg=value # overrides build arg for all targets starting with 'foo'
|
||||||
$ docker buildx bake --set *.platform=linux/arm64 # overrides platform for all targets
|
$ docker buildx bake --set *.platform=linux/arm64 # overrides platform for all targets
|
||||||
$ docker buildx bake --set foo*.no-cache # bypass caching only for targets starting with 'foo'
|
$ docker buildx bake --set foo*.no-cache # bypass caching only for targets starting with 'foo'
|
||||||
|
$ docker buildx bake --set target.platform+=linux/arm64 # appends 'linux/arm64' to the platform list
|
||||||
```
|
```
|
||||||
|
|
||||||
You can override the following fields:
|
You can override the following fields:
|
||||||
|
|
||||||
* `annotations`
|
* `annotations`
|
||||||
|
* `attest`
|
||||||
* `args`
|
* `args`
|
||||||
* `cache-from`
|
* `cache-from`
|
||||||
* `cache-to`
|
* `cache-to`
|
||||||
* `context`
|
* `context`
|
||||||
* `dockerfile`
|
* `dockerfile`
|
||||||
|
* `entitlements`
|
||||||
* `labels`
|
* `labels`
|
||||||
* `load`
|
* `load`
|
||||||
* `no-cache`
|
* `no-cache`
|
||||||
@ -372,3 +375,20 @@ You can override the following fields:
|
|||||||
* `ssh`
|
* `ssh`
|
||||||
* `tags`
|
* `tags`
|
||||||
* `target`
|
* `target`
|
||||||
|
|
||||||
|
You can append using `+=` operator for the following fields:
|
||||||
|
|
||||||
|
* `annotations`¹
|
||||||
|
* `attest`¹
|
||||||
|
* `cache-from`
|
||||||
|
* `cache-to`
|
||||||
|
* `entitlements`¹
|
||||||
|
* `no-cache-filter`
|
||||||
|
* `output`
|
||||||
|
* `platform`
|
||||||
|
* `secrets`
|
||||||
|
* `ssh`
|
||||||
|
* `tags`
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> ¹ These fields already append by default.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user