From 7c22db3c3417fe7610cb9a90c4c4c1e71f293082 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:53:02 +0200 Subject: [PATCH] bake: add pattern matching for targets input Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- bake/bake.go | 31 +++++++++++++++ bake/bake_test.go | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/bake/bake.go b/bake/bake.go index 32ec402ba..b0549b135 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -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) diff --git a/bake/bake_test.go b/bake/bake_test.go index ec3b7ec1a..bf7d3050b 100644 --- a/bake/bake_test.go +++ b/bake/bake_test.go @@ -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 {