Skip to content

Commit cc3a690

Browse files
heschigopherbot
authored andcommitted
internal/relui: add reproducibility check to distpack builds
Pick an arbitrary distpack, linux-amd64, and rebuild it on Windows to verify that we get precisely the same results. The error reporting here won't be that great, it doesn't recurse into the tar/zips at all. I figure that in the unlikely case it fails, it's going to need some fairly in-depth investigation anyway. Fixes golang/go#58659 Change-Id: I60e66251747dd5d0535e093423c5074d52f8812a Reviewed-on: https://go-review.googlesource.com/c/build/+/490615 Run-TryBot: Heschi Kreinick <[email protected]> Reviewed-by: Carlos Amedee <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Heschi Kreinick <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 5dcd784 commit cc3a690

File tree

3 files changed

+67
-41
lines changed

3 files changed

+67
-41
lines changed

internal/relui/buildrelease_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ VERSION=$(head -n 1 $GO/VERSION)
486486
if [[ $# >0 && $1 == "-distpack" ]]; then
487487
mkdir -p $GO/pkg/distpack
488488
tmp=$(mktemp).tar.gz
489-
tar czf $tmp -C $GO/.. go
489+
tar czf $tmp --mtime 2023-01-01 -C $GO/.. go
490490
mv $tmp $GO/pkg/distpack/$VERSION.src.tar.gz
491491
fi
492492
@@ -525,12 +525,12 @@ if [[ $# >0 && $1 == "-distpack" ]]; then
525525
"windows")
526526
tmp=$(mktemp).zip
527527
# The zip command isn't installed on our buildlets. Python is.
528-
(cd $GO/.. && python3 -m zipfile -c $tmp go/)
528+
(cd $GO/.. && find . | xargs touch -d 2023-01-01 && python3 -m zipfile -c $tmp go/)
529529
mv $tmp $GO/pkg/distpack/$VERSION-$GOOS-$GOARCH.zip
530530
;;
531531
*)
532532
tmp=$(mktemp).tar.gz
533-
tar czf $tmp -C $GO/.. go
533+
tar czf $tmp --mtime 2023-01-01 -C $GO/.. go
534534
mv $tmp $GO/pkg/distpack/$VERSION-$GOOS-$GOARCH.tar.gz
535535
;;
536536
esac
@@ -543,7 +543,7 @@ if [[ $# >0 && $1 == "-distpack" ]]; then
543543
mkdir -p $MODDIR
544544
cp -r $GO $MODDIR
545545
tmp=$(mktemp).zip
546-
(cd $MODTMP && python3 -m zipfile -c $tmp .)
546+
(cd $MODTMP && find . | xargs touch -d 2023-01-01 && python3 -m zipfile -c $tmp .)
547547
mv $tmp $GO/pkg/distpack/$MODVER.zip
548548
fi
549549
`

internal/relui/workflows.go

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -449,10 +449,13 @@ type moduleArtifact struct {
449449
func (tasks *BuildReleaseTasks) addBuildTasks(wd *wf.Definition, major int, version wf.Value[string], timestamp wf.Value[time.Time], source wf.Value[artifact]) (wf.Value[[]artifact], wf.Value[[]moduleArtifact]) {
450450
targets := releasetargets.TargetsForGo1Point(major)
451451
skipTests := wf.Param(wd, wf.ParamDef[[]string]{Name: "Targets to skip testing (or 'all') (optional)", ParamType: wf.SliceShort})
452+
452453
artifacts := []wf.Value[artifact]{source}
454+
var reproducibilityCheckDistpack wf.Value[artifact]
453455
var mods []wf.Value[moduleArtifact]
456+
var blockers []wf.Dependency
457+
454458
// Build, test and sign binary artifacts for all targets.
455-
var testsPassed []wf.Dependency
456459
for _, target := range targets {
457460
targetVal := wf.Const(target)
458461
wd := wd.Sub(target.Name)
@@ -463,7 +466,10 @@ func (tasks *BuildReleaseTasks) addBuildTasks(wd *wf.Definition, major int, vers
463466
var tar, zip wf.Value[artifact]
464467
var mod wf.Value[moduleArtifact]
465468
if enableDistpack(major) {
466-
distpack := wf.Task2(wd, "Build distpack", tasks.buildDistpack, targetVal, source)
469+
distpack := wf.Task3(wd, "Build distpack", tasks.buildDistpack, wf.Const("linux-amd64"), wf.Const(target), source)
470+
if target.Name == "linux-amd64" {
471+
reproducibilityCheckDistpack = distpack
472+
}
467473
if target.GOOS == "windows" {
468474
zip = wf.Task1(wd, "Get binary from distpack", tasks.binaryArchiveFromDistpack, distpack)
469475
tar = wf.Task2(wd, "Convert to .tgz", tasks.convertZipToTGZ, targetVal, zip)
@@ -501,12 +507,16 @@ func (tasks *BuildReleaseTasks) addBuildTasks(wd *wf.Definition, major int, vers
501507
continue
502508
}
503509
short := wf.Action4(wd, "Run short tests", tasks.runTests, targetVal, wf.Const(dashboard.Builders[target.Builder]), skipTests, tar)
504-
testsPassed = append(testsPassed, short)
510+
blockers = append(blockers, short)
505511
if target.LongTestBuilder != "" {
506512
long := wf.Action4(wd, "Run long tests", tasks.runTests, targetVal, wf.Const(dashboard.Builders[target.Builder]), skipTests, tar)
507-
testsPassed = append(testsPassed, long)
513+
blockers = append(blockers, long)
508514
}
509515
}
516+
if enableDistpack(major) {
517+
reproducer := wf.Task3(wd, "Reproduce distpack on Windows", tasks.buildDistpack, wf.Const("windows-amd64-2016"), wf.Const(targets["linux-amd64"]), source)
518+
blockers = append(blockers, wf.Action2(wd, "Check distpacks match", tasks.checkDistpacksMatch, reproducibilityCheckDistpack, reproducer))
519+
}
510520
signedArtifacts := wf.Task1(wd, "Compute GPG signature for artifacts", tasks.computeGPG, wf.Slice(artifacts...))
511521

512522
// Run advisory trybots.
@@ -516,6 +526,7 @@ func (tasks *BuildReleaseTasks) addBuildTasks(wd *wf.Definition, major int, vers
516526
advisoryResults = append(advisoryResults, result)
517527
}
518528
tryBotsApproved := wf.Action1(wd, "Wait for advisory TryBots", tasks.checkAdvisoryTrybots, wf.Slice(advisoryResults...))
529+
blockers = append(blockers, tryBotsApproved)
519530

520531
signedAndTested := wf.Task2(wd, "Wait for signing and tests", func(ctx *wf.TaskContext, artifacts []artifact, version string) ([]artifact, error) {
521532
// Note: Note this needs to happen somewhere, doesn't matter where. Maybe move it to a nicer place later.
@@ -528,7 +539,7 @@ func (tasks *BuildReleaseTasks) addBuildTasks(wd *wf.Definition, major int, vers
528539
}
529540

530541
return artifacts, nil
531-
}, signedArtifacts, version, wf.After(testsPassed...), wf.After(tryBotsApproved), wf.After(wf.Slice(mods...)))
542+
}, signedArtifacts, version, wf.After(blockers...), wf.After(wf.Slice(mods...)))
532543
return signedAndTested, wf.Slice(mods...)
533544
}
534545

@@ -589,35 +600,40 @@ func (b *BuildReleaseTasks) checkSourceMatch(ctx *wf.TaskContext, distpack bool,
589600
if err != nil {
590601
return "", err
591602
}
592-
var bc *dashboard.BuildConfig
593-
if distpack {
594-
bc = dashboard.Builders["linux-amd64"]
603+
branchArchive, err := b.buildSource(ctx, distpack, head, "", versionFile)
604+
if err != nil {
605+
return "", err
595606
}
596-
_, err = b.runBuildStep(ctx, nil, bc, source, "", func(bs *task.BuildletStep, r io.Reader, _ io.Writer) error {
597-
branchArchive := &bytes.Buffer{}
598-
if distpack {
599-
if err := bs.BuildSourceDistpack(ctx, b.GerritHTTPClient, b.GerritURL, head, versionFile, branchArchive); err != nil {
600-
return err
601-
}
602-
} else {
603-
if err := task.WriteSourceArchive(ctx, b.GerritHTTPClient, b.GerritURL, head, versionFile, branchArchive); err != nil {
604-
return err
605-
}
606-
}
607-
branchHashes, err := tarballHashes(branchArchive)
608-
if err != nil {
609-
return fmt.Errorf("hashing branch tarball: %v", err)
610-
}
611-
archiveHashes, err := tarballHashes(r)
612-
if err != nil {
613-
return fmt.Errorf("hashing archive tarball: %v", err)
614-
}
615-
if diff := cmp.Diff(branchHashes, archiveHashes); diff != "" {
616-
return fmt.Errorf("branch state doesn't match source archive (-branch, +archive):\n%v", diff)
617-
}
618-
return nil
607+
diff, err := b.diffArtifacts(ctx, branchArchive, source)
608+
if err != nil {
609+
return "", err
610+
}
611+
if diff != "" {
612+
return "", fmt.Errorf("branch state doesn't match source archive (-branch, +archive):\n%v", diff)
613+
}
614+
return head, nil
615+
}
616+
617+
func (b *BuildReleaseTasks) diffArtifacts(ctx *wf.TaskContext, a1, a2 artifact) (string, error) {
618+
h1, err := b.hashArtifact(ctx, a1)
619+
if err != nil {
620+
return "", fmt.Errorf("hashing first tarball: %v", err)
621+
}
622+
h2, err := b.hashArtifact(ctx, a2)
623+
if err != nil {
624+
return "", fmt.Errorf("hashing second tarball: %v", err)
625+
}
626+
return cmp.Diff(h1, h2), nil
627+
}
628+
629+
func (b *BuildReleaseTasks) hashArtifact(ctx *wf.TaskContext, a artifact) (map[string]string, error) {
630+
var hashes map[string]string
631+
_, err := b.runBuildStep(ctx, nil, nil, a, "", func(_ *task.BuildletStep, r io.Reader, _ io.Writer) error {
632+
var err error
633+
hashes, err = tarballHashes(r)
634+
return err
619635
})
620-
return head, err
636+
return hashes, err
621637
}
622638

623639
func tarballHashes(r io.Reader) (map[string]string, error) {
@@ -644,14 +660,24 @@ func tarballHashes(r io.Reader) (map[string]string, error) {
644660
return hashes, nil
645661
}
646662

647-
func (b *BuildReleaseTasks) buildDistpack(ctx *wf.TaskContext, target *releasetargets.Target, source artifact) (artifact, error) {
648-
// Always run distpack builds on Linux.
649-
bc := dashboard.Builders["linux-amd64"]
650-
return b.runBuildStep(ctx, target, bc, source, ".tar.gz", func(bs *task.BuildletStep, r io.Reader, w io.Writer) error {
663+
func (b *BuildReleaseTasks) buildDistpack(ctx *wf.TaskContext, builder string, target *releasetargets.Target, source artifact) (artifact, error) {
664+
bc := dashboard.Builders[builder]
665+
return b.runBuildStep(ctx, target, bc, source, "tar.gz", func(bs *task.BuildletStep, r io.Reader, w io.Writer) error {
651666
return bs.BuildDistpack(ctx, r, w)
652667
})
653668
}
654669

670+
func (b *BuildReleaseTasks) checkDistpacksMatch(ctx *wf.TaskContext, linux, windows artifact) error {
671+
diff, err := b.diffArtifacts(ctx, linux, windows)
672+
if err != nil {
673+
return err
674+
}
675+
if diff != "" {
676+
return fmt.Errorf("distpacks don't match (-linux, +windows): %v", diff)
677+
}
678+
return nil
679+
}
680+
655681
func (b *BuildReleaseTasks) binaryArchiveFromDistpack(ctx *wf.TaskContext, distpack artifact) (artifact, error) {
656682
// This must not match the module files, which currently start with v0.0.1.
657683
glob := fmt.Sprintf("go*%v-%v.*", distpack.Target.GOOS, distpack.Target.GOARCH)

internal/task/buildrelease.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func (b *BuildletStep) buildDistpack(ctx *workflow.TaskContext, makeEnv []string
282282
}
283283

284284
ctx.Printf("Building (make.bash only) with -distpack.")
285-
return b.exec(ctx, goDir+"/src/make.bash", []string{"-distpack"}, buildlet.ExecOpts{
285+
return b.exec(ctx, goDir+"/"+b.BuildConfig.MakeScript(), append(b.BuildConfig.MakeScriptArgs(), "-distpack"), buildlet.ExecOpts{
286286
ExtraEnv: makeEnv,
287287
})
288288
}

0 commit comments

Comments
 (0)