Skip to content

Commit 2adc53c

Browse files
committed
build: parallelize forced reference evaluation
Use an errgroup helper to evaluate result refs concurrently during forced evaluation, and fail fast on the first evaluation error. This mitigates current case in bake where chained targets with a multi-platform build could miss secrets and other session properties. The outline for the issue case: - Base target is solved but only lazily and not really loaded/tracked in build graph yet. - Child targets are loaded, base target waits. - Evaluate is called for base stage (because it might be missing result condition), child stage is processed as build result. This happens in parallel. - Because `Evaluate()` was called synchronously, it may have not been called yet for the second platform while the child target already needs to run `RUN --mount=type=secret`. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent d315c08 commit 2adc53c

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

build/build.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
630630
return nil, err
631631
}
632632
} else if forceEval {
633-
if err := res.EachRef(func(ref gateway.Reference) error {
633+
if err := eachRefParallel(ctx, res, func(ctx context.Context, ref gateway.Reference) error {
634634
return ref.Evaluate(ctx)
635635
}); err != nil {
636636
return nil, err
@@ -1321,6 +1321,24 @@ func solve(ctx context.Context, c gateway.Client, req gateway.SolveRequest) (*ga
13211321
return res, nil
13221322
}
13231323

1324+
func eachRefParallel(ctx context.Context, res *gateway.Result, fn func(context.Context, gateway.Reference) error) error {
1325+
var refs []gateway.Reference
1326+
if err := res.EachRef(func(ref gateway.Reference) error {
1327+
refs = append(refs, ref)
1328+
return nil
1329+
}); err != nil {
1330+
return err
1331+
}
1332+
1333+
eg, ctx := errgroup.WithContext(ctx)
1334+
for _, ref := range refs {
1335+
eg.Go(func() error {
1336+
return fn(ctx, ref)
1337+
})
1338+
}
1339+
return eg.Wait()
1340+
}
1341+
13241342
func catchFrontendError(retErr, frontendErr *error) {
13251343
*frontendErr = *retErr
13261344
if errors.Is(*retErr, ErrRestart) {

0 commit comments

Comments
 (0)