Skip to content

Commit a138978

Browse files
heschigopherbot
authored andcommitted
internal/relui: create module files for releases
Building on relui's new support for distpack builds, publish the toolchain module files it generates. This turns out to be quite a bit more complicated than I had hoped. First, save the entire distpack archive, not just the binary distribution. Extract the binary distribution for use in the normal workflow. Then extract the modules files (really just the .zip, the .mod and .info are tiny) to a separate artifact. Publish those to the CDN alongside the normal release artifacts. For non-distpack builds, copy the dl2mod code in from CL 475920 and generate the module files as a postprocessing step on the binary distribution. The really annoying part is macOS, where we need to distribute the signed binaries in the module, not the ones we built. For that, take the module zip generated by distpack and replace the binaries with the ones from the signed binary distribution. This is a fairly picky process, but hopefully means we don't risk drifting out of sync with the canonical distpacks. Finally, the testing changes: the fake make.bash needs to emulate distpack too, which wasn't too bad. And then the new requirement to process the results of the macOS signing process means that the testing fakes can't just produce cute text files -- they have to contain the real distribution. Change the fake macOS packaging tools to deal in prefixed tarballs. For golang/go#58659. Change-Id: I9cca8af2cb562fb39ef805a044109877b4ab7fb8 Reviewed-on: https://go-review.googlesource.com/c/build/+/482996 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent a75f70f commit a138978

File tree

5 files changed

+603
-174
lines changed

5 files changed

+603
-174
lines changed

internal/relui/buildrelease_test.go

Lines changed: 46 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
"golang.org/x/build/internal"
3434
"golang.org/x/build/internal/gcsfs"
3535
"golang.org/x/build/internal/releasetargets"
36-
"golang.org/x/build/internal/relui/sign"
3736
"golang.org/x/build/internal/task"
3837
"golang.org/x/build/internal/workflow"
3938
)
@@ -112,38 +111,38 @@ func newReleaseTestDeps(t *testing.T, previousTag, wantVersion string) *releaseT
112111
bootstrapServer := httptest.NewServer(http.HandlerFunc(serveBootstrap))
113112
t.Cleanup(bootstrapServer.Close)
114113
fakeBuildlets := task.NewFakeBuildlets(t, bootstrapServer.URL, map[string]string{
115-
"pkgbuild": `#!/bin/bash -eu
114+
"pkgbuild": `#!/bin/bash -eux
116115
case "$@" in
117116
"--identifier=org.golang.go --version ` + wantVersion + ` --scripts=pkg-scripts --root=pkg-root pkg-intermediate/org.golang.go.pkg")
118117
# We're doing an intermediate step in building a PKG.
119-
ls pkg-intermediate >/dev/null
120-
echo "I'm a intermediate PKG!" > "$6"
118+
echo "I'm an intermediate PKG!" > "$6"
119+
tar -cz -C pkg-root . >> "$6"
121120
;;
122121
*)
123122
echo "unexpected command $@"
124123
exit 1
125124
;;
126125
esac
127126
`,
128-
"productbuild": `#!/bin/bash -eu
127+
"productbuild": `#!/bin/bash -eux
129128
case "$@" in
130129
"--distribution=pkg-distribution --resources=pkg-resources --package-path=pkg-intermediate pkg-out/` + wantVersion + `.pkg")
131130
# We're building a PKG.
132131
ls pkg-distribution pkg-resources/bg-light.png pkg-resources/bg-dark.png >/dev/null
133-
cat pkg-intermediate/* | sed "s/intermediate //" > "$4"
132+
cat pkg-intermediate/* | sed "s/an intermediate PKG/a PKG/" > "$4"
134133
;;
135134
*)
136135
echo "unexpected command $@"
137136
exit 1
138137
;;
139138
esac
140139
`,
141-
"pkgutil": `#!/bin/bash -eu
140+
"pkgutil": `#!/bin/bash -eux
142141
case "$@" in
143142
"--expand-full go.pkg pkg-expanded")
144143
# We're expanding a PKG.
145-
grep "I'm a PKG!" < "$2"
146144
mkdir -p "$3/org.golang.go.pkg/Payload/usr/local/go"
145+
tail -n +2 "$2" | tar -xz -C "$3/org.golang.go.pkg/Payload"
147146
;;
148147
*)
149148
echo "unexpected command $@"
@@ -216,7 +215,7 @@ esac
216215
ScratchURL: "file://" + filepath.ToSlash(t.TempDir()),
217216
ServingURL: "file://" + filepath.ToSlash(servingDir),
218217
CreateBuildlet: fakeBuildlets.CreateBuildlet,
219-
SignService: &fakeSignService{t: t, completedJobs: make(map[string][]string)},
218+
SignService: task.NewFakeSignService(t),
220219
DownloadURL: dlServer.URL,
221220
PublishFile: publishFile,
222221
ApproveAction: func(ctx *workflow.TaskContext) error {
@@ -354,7 +353,13 @@ func testRelease(t *testing.T, prevTag string, major int, wantVersion string, ki
354353
OS: "darwin",
355354
Arch: "amd64",
356355
Kind: "installer",
357-
}, "I'm a PKG!\n-signed <macOS>")
356+
}, "I'm a PKG! -signed <macOS>")
357+
modVer := "v0.0.1-" + wantVersion + ".darwin-amd64"
358+
checkContents(t, dlURL, nil, modVer+".mod", nil, "module golang.org/toolchain")
359+
checkContents(t, dlURL, nil, modVer+".info", nil, fmt.Sprintf(`"Version":"%v"`, modVer))
360+
checkZip(t, dlURL, nil, modVer+".zip", nil, map[string]string{
361+
"golang.org/toolchain@" + modVer + "/bin/go": "-signed <macOS>",
362+
})
358363

359364
head, err := deps.gerrit.ReadBranchHead(deps.ctx, "dl", "master")
360365
if err != nil {
@@ -472,12 +477,13 @@ func TestAdvisoryTrybotFail(t *testing.T) {
472477
const makeScript = `#!/bin/bash -eu
473478
474479
GO=../
480+
VERSION=$(head -n 1 $GO/VERSION)
475481
476482
if [[ $# >0 && $1 == "-distpack" ]]; then
477483
mkdir -p $GO/pkg/distpack
478484
tmp=$(mktemp).tar.gz
479485
tar czf $tmp -C $GO/.. go
480-
mv $tmp $GO/pkg/distpack/go1.99.src.tar.gz
486+
mv $tmp $GO/pkg/distpack/$VERSION.src.tar.gz
481487
fi
482488
483489
mkdir -p $GO/bin
@@ -516,14 +522,25 @@ if [[ $# >0 && $1 == "-distpack" ]]; then
516522
tmp=$(mktemp).zip
517523
# The zip command isn't installed on our buildlets. Python is.
518524
(cd $GO/.. && python3 -m zipfile -c $tmp go/)
519-
mv $tmp $GO/pkg/distpack/go1.99.$GOOS-$GOARCH.zip
525+
mv $tmp $GO/pkg/distpack/$VERSION-$GOOS-$GOARCH.zip
520526
;;
521527
*)
522528
tmp=$(mktemp).tar.gz
523529
tar czf $tmp -C $GO/.. go
524-
mv $tmp $GO/pkg/distpack/go1.99.$GOOS-$GOARCH.tar.gz
530+
mv $tmp $GO/pkg/distpack/$VERSION-$GOOS-$GOARCH.tar.gz
525531
;;
526532
esac
533+
534+
MODVER=v0.0.1-$VERSION.$GOOS-$GOARCH
535+
echo "module golang.org/toolchain" > $GO/pkg/distpack/$MODVER.mod
536+
echo -e "{\"Version\":\"$MODVER\", \"Timestamp\":\"fake timestamp\"}" > $GO/pkg/distpack/$MODVER.info
537+
MODTMP=$(mktemp -d)
538+
MODDIR=$MODTMP/golang.org/toolchain@$MODVER
539+
mkdir -p $MODDIR
540+
cp -r $GO $MODDIR
541+
tmp=$(mktemp).zip
542+
(cd $MODTMP && python3 -m zipfile -c $tmp .)
543+
mv $tmp $GO/pkg/distpack/$MODVER.zip
527544
fi
528545
`
529546

@@ -557,14 +574,18 @@ func serveBootstrap(w http.ResponseWriter, r *http.Request) {
557574

558575
func checkFile(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, check func(*testing.T, []byte)) {
559576
t.Run(filename, func(t *testing.T) {
560-
f, ok := files[filename]
561-
if !ok {
562-
t.Fatalf("file %q not published", filename)
563-
}
564-
if diff := cmp.Diff(meta, f, cmpopts.IgnoreFields(task.WebsiteFile{}, "Filename", "Version", "ChecksumSHA256", "Size")); diff != "" {
565-
t.Errorf("file metadata mismatch (-want +got):\n%v", diff)
577+
resolvedName := filename
578+
if files != nil {
579+
f, ok := files[filename]
580+
if !ok {
581+
t.Fatalf("file %q not published", filename)
582+
}
583+
if diff := cmp.Diff(meta, f, cmpopts.IgnoreFields(task.WebsiteFile{}, "Filename", "Version", "ChecksumSHA256", "Size")); diff != "" {
584+
t.Errorf("file metadata mismatch (-want +got):\n%v", diff)
585+
}
586+
resolvedName = f.Filename
566587
}
567-
body := fetch(t, dlURL+"/"+f.Filename)
588+
body := fetch(t, dlURL+"/"+resolvedName)
568589
check(t, body)
569590
})
570591
}
@@ -586,7 +607,7 @@ func fetch(t *testing.T, url string) []byte {
586607

587608
func checkContents(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, contents string) {
588609
checkFile(t, dlURL, files, filename, meta, func(t *testing.T, b []byte) {
589-
if got, want := string(b), contents; got != want {
610+
if got, want := string(b), contents; !strings.Contains(got, want) {
590611
t.Errorf("%v contains %q, want %q", filename, got, want)
591612
}
592613
})
@@ -616,8 +637,8 @@ func checkTGZ(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, fi
616637
t.Fatal(err)
617638
}
618639
delete(contents, h.Name)
619-
if string(b) != want {
620-
t.Errorf("contents of %v were %q, want %q", h.Name, string(b), want)
640+
if got := string(b); !strings.Contains(got, want) {
641+
t.Errorf("%v contains %q, want %q", filename, got, want)
621642
}
622643
}
623644
if len(contents) != 0 {
@@ -646,8 +667,8 @@ func checkZip(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, fi
646667
t.Fatal(err)
647668
}
648669
delete(contents, f.Name)
649-
if string(b) != want {
650-
t.Errorf("contents of %v were %q, want %q", f.Name, string(b), want)
670+
if got := string(b); !strings.Contains(got, want) {
671+
t.Errorf("%v contains %q, want %q", filename, got, want)
651672
}
652673
}
653674
if len(contents) != 0 {
@@ -758,75 +779,6 @@ func (l *errorListener) TaskStateChanged(id uuid.UUID, taskID string, st *workfl
758779
return nil
759780
}
760781

761-
type fakeSignService struct {
762-
t *testing.T
763-
mu sync.Mutex
764-
completedJobs map[string][]string // Job ID → output objectURIs.
765-
}
766-
767-
func (s *fakeSignService) SignArtifact(_ context.Context, bt sign.BuildType, in []string) (jobID string, _ error) {
768-
s.t.Logf("fakeSignService: doing %s signing of %q", bt, in)
769-
var out []string
770-
switch bt {
771-
case sign.BuildMacOS, sign.BuildWindows:
772-
if len(in) != 1 {
773-
return "", fmt.Errorf("got %d inputs, want 1", len(in))
774-
}
775-
out = []string{fakeSignFile(in[0], fmt.Sprintf("-signed <%s>", bt))}
776-
case sign.BuildGPG:
777-
if len(in) == 0 {
778-
return "", fmt.Errorf("got 0 inputs, want 1 or more")
779-
}
780-
for _, f := range in {
781-
out = append(out, fakeGPGFile(f))
782-
}
783-
default:
784-
return "", fmt.Errorf("SignArtifact: not implemented for %v", bt)
785-
}
786-
jobID = uuid.NewString()
787-
s.mu.Lock()
788-
s.completedJobs[jobID] = out
789-
s.mu.Unlock()
790-
return jobID, nil
791-
}
792-
func (s *fakeSignService) ArtifactSigningStatus(_ context.Context, jobID string) (_ sign.Status, desc string, out []string, _ error) {
793-
s.mu.Lock()
794-
out, ok := s.completedJobs[jobID]
795-
s.mu.Unlock()
796-
if !ok {
797-
return sign.StatusNotFound, fmt.Sprintf("job %q not found", jobID), nil, nil
798-
}
799-
return sign.StatusCompleted, "", out, nil
800-
}
801-
func (s *fakeSignService) CancelSigning(_ context.Context, jobID string) error {
802-
s.t.Errorf("CancelSigning was called unexpectedly")
803-
return fmt.Errorf("intentional fake error")
804-
}
805-
func fakeSignFile(f, msg string) string {
806-
b, err := os.ReadFile(strings.TrimPrefix(f, "file://"))
807-
if err != nil {
808-
panic(fmt.Errorf("fakeSignFile: os.ReadFile: %v", err))
809-
}
810-
b = append(b, []byte(msg)...)
811-
err = os.WriteFile(strings.TrimPrefix(f, "file://")+".signed", b, 0600)
812-
if err != nil {
813-
panic(fmt.Errorf("fakeSignFile: os.WriteFile: %v", err))
814-
}
815-
return f + ".signed"
816-
}
817-
func fakeGPGFile(f string) string {
818-
b, err := os.ReadFile(strings.TrimPrefix(f, "file://"))
819-
if err != nil {
820-
panic(fmt.Errorf("fakeGPGFile: os.ReadFile: %v", err))
821-
}
822-
gpg := fmt.Sprintf("I'm a GPG signature for %x!", sha256.Sum256(b))
823-
err = os.WriteFile(strings.TrimPrefix(f, "file://")+".asc", []byte(gpg), 0600)
824-
if err != nil {
825-
panic(fmt.Errorf("fakeGPGFile: os.WriteFile: %v", err))
826-
}
827-
return f + ".asc"
828-
}
829-
830782
func fakeCDNLoad(ctx context.Context, t *testing.T, from, to string) {
831783
fromFS, toFS := gcsfs.DirFS(from), gcsfs.DirFS(to)
832784
seen := map[string]bool{}

0 commit comments

Comments
 (0)