Merge pull request #3280 from crazy-max/bake-target-pattern

bake: add pattern matching for targets input
This commit is contained in:
Tõnis Tiigi
2025-07-01 09:31:32 -07:00
committed by GitHub
2 changed files with 129 additions and 0 deletions
+31
View File
@@ -205,6 +205,16 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
targets[i] = sanitizeTargetName(t)
}
var tms []string
for _, t := range targets {
names, err := c.matchNames(t)
if err != nil {
return nil, nil, err
}
tms = append(tms, names...)
}
targets = dedupSlice(tms)
o, err := c.newOverrides(overrides)
if err != nil {
return nil, nil, err
@@ -304,6 +314,27 @@ func sliceToMap(env []string) (res map[string]string) {
return
}
func (c Config) matchNames(pattern string) ([]string, error) {
if !strings.ContainsAny(pattern, "*?[]") {
return []string{pattern}, nil
}
var names []string
for _, group := range c.Groups {
if ok, err := path.Match(pattern, group.Name); ok && err == nil {
names = append(names, group.Name)
}
}
for _, target := range c.Targets {
if ok, err := path.Match(pattern, target.Name); ok && err == nil {
names = append(names, target.Name)
}
}
if len(names) == 0 {
return nil, errors.Errorf("could not find any target matching %q", pattern)
}
return names, nil
}
func ParseFiles(files []File, defaults map[string]string) (_ *Config, _ *hclparser.ParseMeta, err error) {
defer func() {
err = formatHCLError(err, files)
+98
View File
@@ -2300,6 +2300,104 @@ func TestGroupTargetsWithDefault(t *testing.T) {
})
}
func TestMatchNames(t *testing.T) {
ctx := context.TODO()
f := File{
Name: "docker-bake.hcl",
Data: []byte(`
group "default" {
targets = ["foo", "foo-bar"]
}
group "baz" {
targets = ["baz-foo", "baz-bar", "baz-fuu"]
}
target "foo" {}
target "foo-bar" {}
target "foo-baz" {}
target "foo-fuu" {}
target "bar-foo" {}
target "bar-baz" {}
target "bar-fuu" {}
target "baz-foo" {}
target "baz-bar" {}
target "baz-fuu" {}
target "mtx" {
name = "mtx-${foo}-${bar}-${baz}"
matrix = {
foo = ["a"]
bar = ["b", "c"]
baz = ["d", "e", "f"]
}
}
`),
}
cases := []struct {
name string
pattern []string
expected []string
wantErr bool
}{
{
name: "single",
pattern: []string{"foo"},
expected: []string{"foo"},
},
{
name: "starts with",
pattern: []string{"foo-*"},
expected: []string{"foo-bar", "foo-baz", "foo-fuu"},
},
{
name: "starts with group",
pattern: []string{"baz*"},
expected: []string{"baz-bar", "baz-foo", "baz-fuu"},
},
{
name: "matrix",
pattern: []string{"mtx"},
expected: []string{"mtx-a-b-d", "mtx-a-b-e", "mtx-a-b-f", "mtx-a-c-d", "mtx-a-c-e", "mtx-a-c-f"},
},
{
name: "matrix starts with",
pattern: []string{"mtx-a-b-*"},
expected: []string{"mtx-a-b-d", "mtx-a-b-e", "mtx-a-b-f"},
},
{
name: "any",
pattern: []string{"*"},
expected: []string{"bar-baz", "bar-foo", "bar-fuu", "baz-bar", "baz-foo", "baz-fuu", "foo", "foo-bar", "foo-baz", "foo-fuu", "mtx-a-b-d", "mtx-a-b-e", "mtx-a-b-f", "mtx-a-c-d", "mtx-a-c-e", "mtx-a-c-f"},
},
{
name: "any with group",
pattern: []string{"*", "default"},
expected: []string{"bar-baz", "bar-foo", "bar-fuu", "baz-bar", "baz-foo", "baz-fuu", "foo", "foo-bar", "foo-baz", "foo-fuu", "mtx-a-b-d", "mtx-a-b-e", "mtx-a-b-f", "mtx-a-c-d", "mtx-a-c-e", "mtx-a-c-f"},
},
{
name: "not found",
pattern: []string{"aaa-*"},
wantErr: true,
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
m, _, err := ReadTargets(ctx, []File{f}, tt.pattern, nil, nil, &EntitlementConf{})
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
require.Equal(t, tt.expected, keys)
}
})
}
}
func stringify[V fmt.Stringer](values []V) []string {
s := make([]string, len(values))
for i, v := range values {