Skip to content

Commit 73438a6

Browse files
committed
build: improve control flow, enable returning build output (image tags)
1 parent 7785765 commit 73438a6

File tree

1 file changed

+82
-53
lines changed

1 file changed

+82
-53
lines changed

cmd/bob/build.go

Lines changed: 82 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,15 @@ func runBuilder(builder bobfile.BuilderSpec, buildCtx *BuildContext, opDesc stri
126126
return nil
127127
}
128128

129-
func buildAndPushOneDockerImage(dockerImage bobfile.DockerImageSpec, buildCtx *BuildContext) error {
129+
type imageBuildOutput struct {
130+
tag string
131+
}
132+
133+
func buildAndPushOneDockerImage(dockerImage bobfile.DockerImageSpec, buildCtx *BuildContext) (*imageBuildOutput, error) {
134+
withErr := func(err error) (*imageBuildOutput, error) {
135+
return nil, fmt.Errorf("buildAndPushOneDockerImage: %w", err)
136+
}
137+
130138
tagWithoutVersion := dockerImage.Image
131139
tag := tagWithoutVersion + ":" + buildCtx.RevisionId.FriendlyRevisionId
132140
tagLatest := tagWithoutVersion + ":latest"
@@ -213,58 +221,60 @@ func buildAndPushOneDockerImage(dockerImage bobfile.DockerImageSpec, buildCtx *B
213221
args = append(args, "--push")
214222
}
215223

216-
return passthroughStdoutAndStderr(exec.Command("docker", args...)).Run()
217-
}
224+
if err := passthroughStdoutAndStderr(exec.Command("docker", args...)).Run(); err != nil {
225+
return withErr(err)
226+
}
227+
} else {
228+
dockerBuildArgs := []string{"docker",
229+
"build",
230+
"--file", dockerfilePath,
231+
"--tag", tag}
232+
// `$ docker build ...` doesn't have annotation support. we have to use labels.
233+
dockerBuildArgs = append(dockerBuildArgs, annotationsAs("--label=")...)
234+
dockerBuildArgs = append(dockerBuildArgs, buildContextDir)
218235

219-
dockerBuildArgs := []string{"docker",
220-
"build",
221-
"--file", dockerfilePath,
222-
"--tag", tag}
223-
// `$ docker build ...` doesn't have annotation support. we have to use labels.
224-
dockerBuildArgs = append(dockerBuildArgs, annotationsAs("--label=")...)
225-
dockerBuildArgs = append(dockerBuildArgs, buildContextDir)
236+
//nolint:gosec // ok
237+
buildCmd := passthroughStdoutAndStderr(exec.Command(dockerBuildArgs[0], dockerBuildArgs[1:]...))
226238

227-
//nolint:gosec // ok
228-
buildCmd := passthroughStdoutAndStderr(exec.Command(dockerBuildArgs[0], dockerBuildArgs[1:]...))
239+
if err := buildCmd.Run(); err != nil {
240+
return withErr(err)
241+
}
229242

230-
if err := buildCmd.Run(); err != nil {
231-
return err
232-
}
243+
if buildCtx.PublishArtefacts {
244+
pushTag := func(tag string) error {
245+
printHeading(fmt.Sprintf("Pushing %s", tag))
233246

234-
if buildCtx.PublishArtefacts {
235-
pushTag := func(tag string) error {
236-
printHeading(fmt.Sprintf("Pushing %s", tag))
247+
pushCmd := passthroughStdoutAndStderr(exec.Command(
248+
"docker",
249+
"push",
250+
tag))
237251

238-
pushCmd := passthroughStdoutAndStderr(exec.Command(
239-
"docker",
240-
"push",
241-
tag))
252+
if err := pushCmd.Run(); err != nil {
253+
return err
254+
}
242255

243-
if err := pushCmd.Run(); err != nil {
244-
return err
256+
return nil
245257
}
246258

247-
return nil
248-
}
249-
250-
if err := pushTag(tag); err != nil {
251-
return err
252-
}
253-
254-
if shouldTagLatest {
255-
if err := exec.Command("docker", "tag", tag, tagLatest).Run(); err != nil {
256-
return fmt.Errorf("tagging failed %s -> %s failed: %v", tag, tagLatest, err)
259+
if err := pushTag(tag); err != nil {
260+
return withErr(err)
257261
}
258262

259-
if err := pushTag(tagLatest); err != nil {
260-
return err
263+
if shouldTagLatest {
264+
if err := exec.Command("docker", "tag", tag, tagLatest).Run(); err != nil {
265+
return withErr(fmt.Errorf("tagging failed %s -> %s failed: %v", tag, tagLatest, err))
266+
}
267+
268+
if err := pushTag(tagLatest); err != nil {
269+
return withErr(err)
270+
}
261271
}
262272
}
263-
264-
return nil
265273
}
266274

267-
return nil
275+
return &imageBuildOutput{
276+
tag: tag,
277+
}, nil
268278
}
269279

270280
func cloneToWorkdir(buildCtx *BuildContext) error {
@@ -322,16 +332,22 @@ func cloneToWorkdir(buildCtx *BuildContext) error {
322332
return nil
323333
}
324334

325-
func build(buildCtx *BuildContext) error {
335+
type buildOutput struct {
336+
images []imageBuildOutput
337+
}
338+
339+
func build(buildCtx *BuildContext) (*buildOutput, error) {
340+
withErr := func(err error) (*buildOutput, error) { return nil, fmt.Errorf("build: %w", err) }
341+
326342
if buildCtx.CloningStepNeeded {
327343
if err := cloneToWorkdir(buildCtx); err != nil {
328-
return err
344+
return withErr(err)
329345
}
330346
}
331347

332348
for _, subrepo := range buildCtx.Bobfile.Subrepos {
333349
if err := ensureSubrepoCloned(buildCtx.WorkspaceDir+"/"+subrepo.Destination, subrepo); err != nil {
334-
return err
350+
return withErr(err)
335351
}
336352
}
337353

@@ -349,7 +365,7 @@ func build(buildCtx *BuildContext) error {
349365

350366
builderType, _, err := parseBuilderUsesType(builder.Uses)
351367
if err != nil {
352-
return err
368+
return withErr(err)
353369
}
354370

355371
// only need to build if a builder is dockerfile. images are ready for consumption.
@@ -358,7 +374,7 @@ func build(buildCtx *BuildContext) error {
358374
}
359375

360376
if err := buildBuilder(buildCtx.Bobfile, &builder); err != nil {
361-
return err
377+
return withErr(err)
362378
}
363379
}
364380

@@ -387,36 +403,43 @@ func build(buildCtx *BuildContext) error {
387403
publishPass := func(cmds bobfile.BuilderCommands) []string { return cmds.Publish }
388404

389405
if err := pass("prepare", preparePass); err != nil {
390-
return err // err context ok
406+
return withErr(err) // err context ok
391407
}
392408

393409
if err := pass("build", buildPass); err != nil {
394-
return err // err context ok
410+
return withErr(err) // err context ok
395411
}
396412

397413
if err := pass("publish", publishPass); err != nil {
398-
return err // err context ok
414+
return withErr(err) // err context ok
399415
}
400416

401417
dockerLoginCache := newDockerRegistryLoginCache()
402418

419+
output := buildOutput{
420+
images: []imageBuildOutput{},
421+
}
422+
403423
for _, dockerImage := range buildCtx.Bobfile.DockerImages {
404424
if buildCtx.BuilderNameFilter != "" {
405425
continue // when building a specifified builder => skip everything else
406426
}
407427

408428
if buildCtx.PublishArtefacts {
409429
if err := loginToDockerRegistry(dockerImage, dockerLoginCache); err != nil {
410-
return err
430+
return withErr(err)
411431
}
412432
}
413433

414-
if err := buildAndPushOneDockerImage(dockerImage, buildCtx); err != nil {
415-
return err
434+
imageOutput, err := buildAndPushOneDockerImage(dockerImage, buildCtx)
435+
if err != nil {
436+
return withErr(err)
416437
}
438+
439+
output.images = append(output.images, *imageOutput)
417440
}
418441

419-
return nil
442+
return &output, nil
420443
}
421444

422445
func constructBuildContext(
@@ -498,7 +521,8 @@ func buildEntry() *cobra.Command {
498521
areWeInCi)
499522
osutil.ExitIfError(err)
500523

501-
osutil.ExitIfError(build(buildCtx))
524+
_, err = build(buildCtx)
525+
osutil.ExitIfError(err)
502526
},
503527
}
504528

@@ -547,7 +571,12 @@ func buildEntry() *cobra.Command {
547571
buildCtx.Debug = true
548572
}
549573

550-
return build(buildCtx)
574+
_, err := build(buildCtx)
575+
if err != nil {
576+
return err
577+
}
578+
579+
return nil
551580
}())
552581
},
553582
})

0 commit comments

Comments
 (0)