Skip to content

Commit 9a228b4

Browse files
Avoid waiting on progress output in multi-project bake
1 parent fb6a260 commit 9a228b4

File tree

1 file changed

+72
-25
lines changed

1 file changed

+72
-25
lines changed

pkg/buildx/commands/bake.go

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ type BakeOptions struct {
4444
DepotOptions
4545
}
4646

47-
func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, printer *progresshelper.SharedPrinter) (err error) {
47+
func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, printer *progresshelper.SharedPrinter) (linter *Linter, requestedTargets []string, err error) {
4848
ctx := appcontext.Context()
4949

5050
ctx, end, err := tracing.TraceCurrentCommand(ctx, "bake")
5151
if err != nil {
52-
return err
52+
return nil, nil, err
5353
}
5454
defer func() {
5555
end(err)
@@ -64,24 +64,24 @@ func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, pri
6464
builder.WithContextPathHash(contextPathHash)}, in.builderOptions...)
6565
b, err := builder.New(dockerCli, builderOpts...)
6666
if err != nil {
67-
return err
67+
return nil, nil, err
6868
}
6969
if err = updateLastActivity(dockerCli, b.NodeGroup); err != nil {
70-
return errors.Wrapf(err, "failed to update builder last activity time")
70+
return nil, nil, errors.Wrapf(err, "failed to update builder last activity time")
7171
}
7272
nodes, err := b.LoadNodes(ctx, false)
7373
if err != nil {
74-
return err
74+
return nil, nil, err
7575
}
7676

7777
validatedOpts, requestedTargets, err := validator.Validate(ctx, nodes, printer)
7878
if err != nil {
79-
return err
79+
return nil, nil, err
8080
}
8181

8282
buildOpts := validatedOpts.ProjectOpts(in.project)
8383
if buildOpts == nil {
84-
return fmt.Errorf("project %s build options not found", in.project)
84+
return nil, nil, fmt.Errorf("project %s build options not found", in.project)
8585
}
8686

8787
// Filter requestedTargets to only include targets for the current project
@@ -147,7 +147,7 @@ func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, pri
147147
buildxNodes := builder.ToBuildxNodes(nodes)
148148
buildxNodes, err = build.FilterAvailableNodes(buildxNodes)
149149
if err != nil {
150-
return wrapBuildError(err, true)
150+
return nil, nil, wrapBuildError(err, true)
151151
}
152152

153153
dockerClient := dockerutil.NewClient(dockerCli)
@@ -157,16 +157,16 @@ func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, pri
157157
// "Boot" the depot nodes.
158158
_, clients, err := build.ResolveDrivers(ctx, buildxNodes, buildxopts, printer)
159159
if err != nil {
160-
return wrapBuildError(err, true)
160+
return nil, nil, wrapBuildError(err, true)
161161
}
162162

163-
linter := NewLinter(printer, NewLintFailureMode(in.lint, in.lintFailOn), clients, buildxNodes)
163+
linter = NewLinter(printer, NewLintFailureMode(in.lint, in.lintFailOn), clients, buildxNodes)
164164
resp, err := build.DepotBuild(ctx, buildxNodes, buildOpts, dockerClient, dockerConfigDir, printer, linter, in.DepotOptions.build)
165165
if err != nil {
166166
if errors.Is(err, LintFailed) {
167167
linter.Print(os.Stderr, in.progress)
168168
}
169-
return wrapBuildError(err, true)
169+
return nil, nil, wrapBuildError(err, true)
170170
}
171171

172172
if in.metadataFile != "" {
@@ -186,14 +186,14 @@ func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, pri
186186
}
187187
err = writeMetadataFile(in.metadataFile, in.project, in.buildID, requestedTargets, dt, true)
188188
if err != nil {
189-
return err
189+
return nil, nil, err
190190
}
191191
}
192192

193193
if in.sbomDir != "" {
194194
err = sbom.Save(ctx, in.sbomDir, resp)
195195
if err != nil {
196-
return err
196+
return nil, nil, err
197197
}
198198
}
199199

@@ -235,17 +235,11 @@ func RunBake(dockerCli command.Cli, in BakeOptions, validator BakeValidator, pri
235235
_, err = build.DepotBuild(ctx, buildxNodes, buildOpts, dockerClient, dockerConfigDir, printer, nil, in.DepotOptions.build)
236236
}
237237

238-
return err
238+
return nil, nil, err
239239
}
240240
}
241241

242-
_ = printer.Wait()
243-
244-
if in.save {
245-
printSaveHelp(in.project, in.buildID, in.progress, requestedTargets, in.additionalTags)
246-
}
247-
linter.Print(os.Stderr, in.progress)
248-
return nil
242+
return linter, requestedTargets, nil
249243
}
250244

251245
func BakeCmd() *cobra.Command {
@@ -325,6 +319,19 @@ func BakeCmd() *cobra.Command {
325319
printer.Add()
326320
}
327321

322+
type saveInfo struct {
323+
project string
324+
buildID string
325+
additionalTags []string
326+
}
327+
type buildResult struct {
328+
linter *Linter
329+
requestedTargets []string
330+
saveInfo *saveInfo
331+
}
332+
var mu sync.Mutex
333+
var buildResults []buildResult
334+
328335
eg, ctx := errgroup.WithContext(context.Background())
329336
for _, projectID := range projectIDs {
330337
options.project = projectID
@@ -376,22 +383,62 @@ func BakeCmd() *cobra.Command {
376383

377384
func(c command.Cli, o BakeOptions, v BakeValidator, p *progresshelper.SharedPrinter) {
378385
eg.Go(func() error {
386+
var linter *Linter
387+
var requestedTargets []string
388+
379389
buildErr := retryRetryableErrors(ctx, func() error {
380-
return RunBake(c, o, v, p)
390+
var err error
391+
linter, requestedTargets, err = RunBake(c, o, v, p)
392+
return err
381393
})
382394
if buildErr != nil {
383-
_ = p.Wait()
395+
buildErr = rewriteFriendlyErrors(buildErr)
384396
}
385397

386398
o.build.Finish(buildErr)
387399
PrintBuildURL(o.buildURL, o.progress)
388400

389-
return rewriteFriendlyErrors(buildErr)
401+
// Collect results for post-processing
402+
if buildErr == nil {
403+
result := buildResult{
404+
linter: linter,
405+
requestedTargets: requestedTargets,
406+
}
407+
if o.save {
408+
result.saveInfo = &saveInfo{
409+
project: o.project,
410+
buildID: o.buildID,
411+
additionalTags: o.additionalTags,
412+
}
413+
}
414+
mu.Lock()
415+
buildResults = append(buildResults, result)
416+
mu.Unlock()
417+
}
418+
419+
return buildErr
390420
})
391421
}(dockerCli, options, validator, printer)
392422
}
393423

394-
return eg.Wait()
424+
// Wait for all builds to complete
425+
err = eg.Wait()
426+
427+
// Now wait for the printer to finish and flush all output
428+
_ = printer.Wait()
429+
430+
// Print save help and linter output after all project builds complete
431+
for _, result := range buildResults {
432+
if result.saveInfo != nil {
433+
printSaveHelp(result.saveInfo.project, result.saveInfo.buildID,
434+
options.progress, result.requestedTargets, result.saveInfo.additionalTags)
435+
}
436+
if result.linter != nil {
437+
result.linter.Print(os.Stderr, options.progress)
438+
}
439+
}
440+
441+
return err
395442
},
396443
}
397444

0 commit comments

Comments
 (0)