diff --git a/bake/bake.go b/bake/bake.go index 384336dfbf8..3b8981a5b92 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -414,12 +414,12 @@ func (c Config) newOverrides(v []string) (map[string]map[string]Override, error) } func (c Config) ResolveGroup(name string) []string { - return c.group(name, map[string]struct{}{}) + return dedupString(c.group(name, map[string][]string{})) } -func (c Config) group(name string, visited map[string]struct{}) []string { +func (c Config) group(name string, visited map[string][]string) []string { if _, ok := visited[name]; ok { - return nil + return visited[name] } var g *Group for _, group := range c.Groups { @@ -431,7 +431,7 @@ func (c Config) group(name string, visited map[string]struct{}) []string { if g == nil { return []string{name} } - visited[name] = struct{}{} + visited[name] = []string{} targets := make([]string, 0, len(g.Targets)) for _, t := range g.Targets { tgroup := c.group(t, visited) @@ -441,6 +441,7 @@ func (c Config) group(name string, visited map[string]struct{}) []string { targets = append(targets, t) } } + visited[name] = targets return targets } diff --git a/bake/bake_test.go b/bake/bake_test.go index 9864e85b024..bf72d8af01c 100644 --- a/bake/bake_test.go +++ b/bake/bake_test.go @@ -1045,3 +1045,79 @@ func TestTargetName(t *testing.T) { }) } } + +func TestNestedGroupsWithSameTarget(t *testing.T) { + ctx := context.TODO() + + f := File{ + Name: "docker-bake.hcl", + Data: []byte(` +group "a" { + targets = ["b", "c"] +} + +group "b" { + targets = ["d"] +} + +group "c" { + targets = ["b"] +} + +target "d" { + context = "." + dockerfile = "./testdockerfile" +} + +group "e" { + targets = ["a", "f"] +} + +target "f" { + context = "./foo" +}`)} + + cases := []struct { + name string + targets []string + ntargets int + }{ + { + name: "a", + targets: []string{"b", "c"}, + ntargets: 1, + }, + { + name: "b", + targets: []string{"d"}, + ntargets: 1, + }, + { + name: "c", + targets: []string{"b"}, + ntargets: 1, + }, + { + name: "d", + targets: []string{"d"}, + ntargets: 1, + }, + { + name: "e", + targets: []string{"a", "f"}, + ntargets: 2, + }, + } + for _, tt := range cases { + tt := tt + t.Run(tt.name, func(t *testing.T) { + m, g, err := ReadTargets(ctx, []File{f}, []string{tt.name}, nil, nil) + require.NoError(t, err) + require.Equal(t, 1, len(g)) + require.Equal(t, tt.targets, g[0].Targets) + require.Equal(t, tt.ntargets, len(m)) + require.Equal(t, ".", *m["d"].Context) + require.Equal(t, "./testdockerfile", *m["d"].Dockerfile) + }) + } +}