cmd/release: embed releaselet.go source code statically
Previously, the release binary dynamically looked for the releaselet.go
source code. It first checked in the current working directory, and
then used the go/build package to find the location of source code of
golang.org/x/build/cmd/release package on disk.
The release binary is not generally executed by hand, rather it is used
internally by releasebot command. That makes it hard to know in advance
where the current working directory for release will be (that directory
is $HOME/go-releasebot-work/<release> that releasebot creates itself).
Further, with the proliferation of module mode, it's no longer viable
to be able to find the location of a package by its import path via
go/build.Import. As a result, there's now a higher risk of cmd/release
not finding, or finding a wrong version of releaselet.go.
Change the release binary to instead statically embed the releaselet.go
source code as a constant string, in a static.go file that is generated
via a go:generate directive.
Add a test to ensure the embedded copy of releaselet.go doesn't get out
of sync.
The embedding approach was loosely based on approach taken in package
golang.org/x/tools/godoc/static, but it was simplified for the smaller
needs of cmd/release (i.e., embedding a single text file). We rely on
fmt's %q verb to do the escaping, which has the risk of changing between
Go versions, but it's unlikely to happen often to warrant worrying yet.
Fixes golang/go#33443
Change-Id: Ie7a9481c33a7d9668d696d3827e5681b07b37094
Reviewed-on: https://go-review.googlesource.com/c/build/+/189817
Reviewed-by: Filippo Valsorda <filippo@golang.org>
diff --git a/cmd/release/release.go b/cmd/release/release.go
index af05eb7..4cf0bf5 100644
--- a/cmd/release/release.go
+++ b/cmd/release/release.go
@@ -14,7 +14,6 @@
"context"
"flag"
"fmt"
- gobuild "go/build"
"io"
"io/ioutil"
"log"
@@ -33,6 +32,8 @@
"golang.org/x/build/dashboard"
)
+//go:generate go run makestatic.go
+
var (
target = flag.String("target", "", "If specified, build specific target platform (e.g. 'linux-amd64'). Default is to build all.")
watch = flag.Bool("watch", false, "Watch the build. Only compatible with -target")
@@ -67,10 +68,6 @@
return
}
- if err := findReleaselet(); err != nil {
- log.Fatalf("couldn't find releaselet source: %v", err)
- }
-
if (*rev == "" && *tarball == "") || (*rev != "" && *tarball != "") {
log.Fatal("must specify one of -rev or -tarball")
}
@@ -109,28 +106,6 @@
wg.Wait()
}
-var releaselet = "releaselet.go"
-
-func findReleaselet() error {
- // First try the working directory.
- if _, err := os.Stat(releaselet); err == nil {
- return nil
- }
-
- // Then, try to locate the release command in the workspace.
- const importPath = "golang.org/x/build/cmd/release"
- pkg, err := gobuild.Import(importPath, "", gobuild.FindOnly)
- if err != nil {
- return fmt.Errorf("finding %q: %v", importPath, err)
- }
- r := filepath.Join(pkg.Dir, releaselet)
- if _, err := os.Stat(r); err != nil {
- return err
- }
- releaselet = r
- return nil
-}
-
type Build struct {
OS, Arch string
Source bool
@@ -509,12 +484,7 @@
}
b.logf("Pushing and running releaselet.")
- f, err := os.Open(releaselet)
- if err != nil {
- return err
- }
- err = client.Put(f, "releaselet.go", 0666)
- f.Close()
+ err = client.Put(strings.NewReader(releaselet), "releaselet.go", 0666)
if err != nil {
return err
}