cmd/releasebot: add support for security releases
Change-Id: I24f22a6101b550d459a4f4db1971e0c23ffae1d3
Reviewed-on: https://go-review.googlesource.com/c/153866
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/cmd/release/release.go b/cmd/release/release.go
index 4e9e289..53844bd 100644
--- a/cmd/release/release.go
+++ b/cmd/release/release.go
@@ -37,7 +37,8 @@
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")
- rev = flag.String("rev", "", "Go revision to build")
+ rev = flag.String("rev", "", "Go revision to build, alternative to -tarball")
+ tarball = flag.String("tarball", "", "Go tree tarball to build, alternative to -rev")
toolsRev = flag.String("tools", "", "Tools revision to build")
tourRev = flag.String("tour", "master", "Tour revision to include")
netRev = flag.String("net", "master", "Net revision to include")
@@ -70,8 +71,8 @@
log.Fatalf("couldn't find releaselet source: %v", err)
}
- if *rev == "" {
- log.Fatal("must specify -rev flag")
+ if (*rev == "" && *tarball == "") || (*rev != "" && *tarball != "") {
+ log.Fatal("must specify one of -rev and -tarball")
}
if *toolsRev == "" {
log.Fatal("must specify -tools flag")
@@ -285,24 +286,38 @@
goPath = "gopath"
go14 = "go1.4"
)
+ if *tarball != "" {
+ tarFile, err := os.Open(*tarball)
+ if err != nil {
+ b.logf("failed to open tarball %q: %v", *tarball, err)
+ return err
+ }
+ if err := client.PutTar(tarFile, goDir); err != nil {
+ b.logf("failed to put tarball %q into dir %q: %v", *tarball, goDir, err)
+ return err
+ }
+ tarFile.Close()
+ } else {
+ tar := "https://go.googlesource.com/go/+archive/" + *rev + ".tar.gz"
+ if err := client.PutTarFromURL(tar, goDir); err != nil {
+ b.logf("failed to put tarball %q into dir %q: %v", tar, goDir, err)
+ return err
+ }
+ }
for _, r := range []struct {
repo, rev string
}{
- {"go", *rev},
{"tools", *toolsRev},
{"tour", *tourRev},
{"net", *netRev},
} {
- if b.Source && r.repo != "go" {
+ if b.Source {
continue
}
if r.repo == "tour" && !versionIncludesTour(*version) {
continue
}
- dir := goDir
- if r.repo != "go" {
- dir = goPath + "/src/golang.org/x/" + r.repo
- }
+ dir := goPath + "/src/golang.org/x/" + r.repo
tar := "https://go.googlesource.com/" + r.repo + "/+archive/" + r.rev + ".tar.gz"
if err := client.PutTarFromURL(tar, dir); err != nil {
b.logf("failed to put tarball %q into dir %q: %v", tar, dir, err)
diff --git a/cmd/releasebot/git.go b/cmd/releasebot/git.go
index 51b56a5..924d4cf 100644
--- a/cmd/releasebot/git.go
+++ b/cmd/releasebot/git.go
@@ -25,11 +25,16 @@
w.log.Panic(err)
}
+ origin := "https://go.googlesource.com/go"
+ if w.Security {
+ origin = "sso://team/golang/go-private"
+ }
+
// Check out a local mirror to work-mirror, to speed future checkouts for this point release.
mirror := filepath.Join(w.Dir, "gitmirror")
r := w.runner(mirror)
if _, err := os.Stat(mirror); err != nil {
- w.runner(w.Dir).run("git", "clone", "https://go.googlesource.com/go", mirror)
+ w.runner(w.Dir).run("git", "clone", origin, mirror)
r.run("git", "config", "gc.auto", "0") // don't throw away refs we fetch
} else {
r.run("git", "fetch", "origin", "master")
@@ -41,7 +46,7 @@
if err := os.RemoveAll(gitDir); err != nil {
w.log.Panic(err)
}
- w.runner(w.Dir).run("git", "clone", "--reference", mirror, "-b", w.ReleaseBranch, "https://go.googlesource.com/go", gitDir)
+ w.runner(w.Dir).run("git", "clone", "--reference", mirror, "-b", w.ReleaseBranch, origin, gitDir)
r = w.runner(gitDir)
r.run("git", "codereview", "change", "relwork")
r.run("git", "config", "gc.auto", "0") // don't throw away refs we fetch
diff --git a/cmd/releasebot/github.go b/cmd/releasebot/github.go
index 1389185..89c3544 100644
--- a/cmd/releasebot/github.go
+++ b/cmd/releasebot/github.go
@@ -85,7 +85,7 @@
func (w *Work) findOrCreateReleaseIssue() {
w.log.Printf("Release status issue title: %q", w.releaseStatusTitle())
- if dryRun {
+ if dryRun || w.Security {
return
}
if w.ReleaseIssue == 0 {
@@ -103,7 +103,7 @@
// createGitHubIssue creates an issue in the release milestone and returns its number.
func (w *Work) createGitHubIssue(title, msg string) (int, error) {
if dryRun {
- return 0, errors.New("attemted write operation in dry-run mode")
+ return 0, errors.New("attempted write operation in dry-run mode")
}
var dup int
goRepo.ForeachIssue(func(gi *maintner.GitHubIssue) error {
@@ -150,7 +150,11 @@
if gi.Milestone == nil || gi.Milestone.Title != w.Milestone.Title {
return nil
}
- if gi.Closed || gi.Title == w.releaseStatusTitle() {
+ if gi.Title == w.releaseStatusTitle() {
+ return nil
+ }
+ // All issues are unrelated if this is a security release.
+ if gi.Closed && !w.Security {
return nil
}
w.log.Printf("changing milestone of issue %d to %s", gi.Number, w.NextMilestone.Title)
diff --git a/cmd/releasebot/main.go b/cmd/releasebot/main.go
index 6f056d5..6825422 100644
--- a/cmd/releasebot/main.go
+++ b/cmd/releasebot/main.go
@@ -52,12 +52,7 @@
}
func usage() {
- fmt.Fprintln(os.Stderr, "usage: releasebot -mode <release mode> [-dry-run] {go1.8.5|go1.10beta2|go1.11rc1}")
- fmt.Fprintln(os.Stderr, "Release modes:")
- fmt.Fprintln(os.Stderr)
- for m := range releaseModes {
- fmt.Fprintln(os.Stderr, m)
- }
+ fmt.Fprintln(os.Stderr, "usage: releasebot -mode {prepare|release} [-security] [-dry-run] {go1.8.5|go1.10beta2|go1.11rc1}")
os.Exit(2)
}
@@ -66,6 +61,7 @@
func main() {
modeFlag := flag.String("mode", "", "release mode (prepare, release)")
flag.BoolVar(&dryRun, "dry-run", false, "only perform pre-flight checks, only log to terminal")
+ security := flag.Bool("security", false, "cut a security release from the internal Gerrit")
flag.Usage = usage
flag.Parse()
if *modeFlag == "" || !releaseModes[*modeFlag] || flag.NArg() == 0 {
@@ -84,6 +80,10 @@
var wg sync.WaitGroup
for _, release := range flag.Args() {
if strings.Contains(release, "beta") || strings.Contains(release, "rc") {
+ if *security {
+ log.Printf("error: only minor releases are supported in security mode")
+ usage()
+ }
w := &Work{
Prepare: *modeFlag == "prepare",
Version: release,
@@ -110,6 +110,7 @@
NextMilestone: nextM,
Prepare: *modeFlag == "prepare",
Version: release,
+ Security: *security,
}
wg.Add(1)
go func() {
@@ -194,6 +195,7 @@
Prepare bool // create the release commit and submit it for review
BetaRelease bool
RCRelease bool
+ Security bool // cut a security release from the internal Gerrit
ReleaseIssue int // Release status issue number
ReleaseBranch string // "master" for beta releases
@@ -312,6 +314,9 @@
} else {
shortRel := w.Version[:strings.LastIndex(w.Version, ".")]
w.ReleaseBranch = "release-branch." + shortRel
+ if w.Security {
+ w.ReleaseBranch += "-security"
+ }
}
w.checkSpelling()
@@ -326,7 +331,9 @@
if w.BetaRelease || w.RCRelease {
// TODO: go tool api -allow_new=false
} else {
- w.checkReleaseBlockers()
+ if !w.Security {
+ w.checkReleaseBlockers()
+ }
w.checkDocs()
}
w.findOrCreateReleaseIssue()
@@ -389,6 +396,18 @@
}
func (w *Work) nextStepsPrepare(changeID string) {
+ if w.Security {
+ w.log.Printf(`
+
+The release is ready.
+
+Please review and submit https://team-review.git.corp.google.com/q/%s
+after testing it with all.bash and then run the release stage.
+
+`, changeID)
+ return
+ }
+
w.log.Printf(`
The release is ready.
@@ -439,7 +458,8 @@
body := md.String()
fmt.Printf("%s", body)
- if dryRun {
+ // Avoid the risk of leaking sensitive test failures on security releases.
+ if dryRun || w.Security {
return
}
err := postGithubComment(w.ReleaseIssue, body)
@@ -503,8 +523,10 @@
r.run("git", "commit", "-m", desc, "VERSION")
if dryRun {
fmt.Printf("\n### VERSION commit\n\n%s\n", r.runOut("git", "show", "HEAD"))
+ } else if w.Security {
+ r.run("git", "codereview", "mail")
} else {
- r.run("git", "codereview", "mail", "-trybot", "HEAD")
+ r.run("git", "codereview", "mail", "-trybot")
}
return
}
@@ -540,6 +562,22 @@
}
w.ReleaseInfo = make(map[string]*ReleaseInfo)
+ if w.Security {
+ fmt.Printf(`
+
+Please download
+
+ https://team.git.corp.google.com/golang/go-private/+archive/%s.tar.gz
+
+to %s and press enter.
+`, w.VersionCommit, filepath.Join(w.Dir, w.VersionCommit+".tar.gz"))
+
+ _, err := fmt.Scanln()
+ if err != nil {
+ w.log.Panic(err)
+ }
+ }
+
var wg sync.WaitGroup
for _, target := range releaseTargets {
func() {
@@ -627,9 +665,15 @@
} else {
failures := 0
for {
- out, err := w.runner(filepath.Join(w.Dir, "release"), "GOPATH="+filepath.Join(w.Dir, "gopath")).runErr(
- w.ReleaseBinary, "-target", target, "-user", gomoteUser, "-version", w.Version, "-rev", w.VersionCommit,
- "-tools", w.ReleaseBranch, "-net", w.ReleaseBranch)
+ releaseBranch := strings.TrimSuffix(w.ReleaseBranch, "-security")
+ args := []string{w.ReleaseBinary, "-target", target, "-user", gomoteUser,
+ "-version", w.Version, "-tools", releaseBranch, "-net", releaseBranch}
+ if w.Security {
+ args = append(args, "-tarball", filepath.Join(w.Dir, w.VersionCommit+".tar.gz"))
+ } else {
+ args = append(args, "-rev", w.VersionCommit)
+ }
+ out, err := w.runner(filepath.Join(w.Dir, "release"), "GOPATH="+filepath.Join(w.Dir, "gopath")).runErr(args...)
// Exit code from release binary is apparently unreliable.
// Look to see if the files we expected were created instead.
failed := false