cmd/releasebot: add support for beta releases
Change-Id: I20b4c68dd2512dc76f5751c200d487784b68670b
Reviewed-on: https://go-review.googlesource.com/119537
Reviewed-by: Andrew Bonventre <andybons@golang.org>
diff --git a/cmd/releasebot/README.md b/cmd/releasebot/README.md
index 4e49997..e49f60c 100644
--- a/cmd/releasebot/README.md
+++ b/cmd/releasebot/README.md
@@ -4,10 +4,10 @@
The release happens in two stages:
-* the `prepare` stage checks preconditions, makes the release commit and mails it for review;
-* the `release` stage runs after the release commit is merged, and it tags, builds and cleans up the release.
+* the `prepare` stage checks preconditions, and if needed makes the release commit and mails it for review;
+* the `release` stage runs after the release commit (if any) is merged, and it tags, builds and cleans up the release.
-At the moment only minor releases are supported.
+At the moment only minor and beta releases are supported.
## Permissions
diff --git a/cmd/releasebot/git.go b/cmd/releasebot/git.go
index e2474fd..f81e3fd 100644
--- a/cmd/releasebot/git.go
+++ b/cmd/releasebot/git.go
@@ -19,10 +19,6 @@
// $HOME/go-releasebot-work/<release>/gitmirror,
// to use as an object cache to speed future checkouts.
func (w *Work) gitCheckout() {
- shortRel := strings.ToLower(w.Milestone.Title)
- shortRel = shortRel[:strings.LastIndex(shortRel, ".")]
- w.ReleaseBranch = "release-branch." + shortRel
-
w.Dir = filepath.Join(os.Getenv("HOME"), "go-releasebot-work/"+strings.ToLower(w.Version))
w.log.Printf("working in %s\n", w.Dir)
if err := os.MkdirAll(w.Dir, 0777); err != nil {
@@ -65,6 +61,7 @@
out = r.runOut("git", "show", w.VersionCommit)
fmt.Printf("About to tag the following commit as %s:\n\n%s\n\nOk? (y/n) ", w.Version, out)
if dryRun {
+ fmt.Println("dry-run")
return
}
var response string
diff --git a/cmd/releasebot/github.go b/cmd/releasebot/github.go
index 7f13392..b9dc7db 100644
--- a/cmd/releasebot/github.go
+++ b/cmd/releasebot/github.go
@@ -73,8 +73,8 @@
// for the given milestone.
// If you change this function, releasebot will not be able to find an
// existing tracking issue using the old name and will create a new one.
-func releaseStatusTitle(m *maintner.GitHubMilestone) string {
- return "all: " + strings.Replace(m.Title, "Go", "Go ", -1) + " release status"
+func (w *Work) releaseStatusTitle() string {
+ return "all: " + strings.Replace(w.Version, "go", "Go ", -1) + " release status"
}
type tokenSource oauth2.Token
@@ -84,13 +84,13 @@
}
func (w *Work) findOrCreateReleaseIssue() {
- w.log.Printf("Release status issue title: %q", releaseStatusTitle(w.Milestone))
+ w.log.Printf("Release status issue title: %q", w.releaseStatusTitle())
if dryRun {
return
}
if w.ReleaseIssue == 0 {
- title := releaseStatusTitle(w.Milestone)
- body := fmt.Sprintf("Issue tracking the %s release by releasebot.", w.Milestone.Title)
+ title := w.releaseStatusTitle()
+ body := fmt.Sprintf("Issue tracking the %s release by releasebot.", w.Version)
num, err := w.createGitHubIssue(title, body)
if err != nil {
w.log.Panic(err)
@@ -116,11 +116,14 @@
if dup != 0 {
return dup, nil
}
- is, _, err := githubClient.Issues.ListByRepo(context.TODO(), "golang", "go", &github.IssueListByRepoOptions{
+ opts := &github.IssueListByRepoOptions{
State: "all",
ListOptions: github.ListOptions{PerPage: 100},
- Milestone: strconv.Itoa(int(w.Milestone.Number)),
- })
+ }
+ if !w.BetaRelease {
+ opts.Milestone = strconv.Itoa(int(w.Milestone.Number))
+ }
+ is, _, err := githubClient.Issues.ListByRepo(context.TODO(), "golang", "go", opts)
if err != nil {
return 0, err
}
@@ -130,11 +133,14 @@
return i.GetNumber(), nil
}
}
- i, _, err := githubClient.Issues.Create(context.TODO(), "golang", "go", &github.IssueRequest{
- Title: github.String(title),
- Body: github.String(msg),
- Milestone: github.Int(int(w.Milestone.Number)),
- })
+ copts := &github.IssueRequest{
+ Title: github.String(title),
+ Body: github.String(msg),
+ }
+ if !w.BetaRelease {
+ copts.Milestone = github.Int(int(w.Milestone.Number))
+ }
+ i, _, err := githubClient.Issues.Create(context.TODO(), "golang", "go", copts)
return i.GetNumber(), err
}
@@ -144,7 +150,7 @@
if gi.Milestone == nil || gi.Milestone.Title != w.Milestone.Title {
return nil
}
- if gi.Closed || gi.Title == releaseStatusTitle(w.Milestone) {
+ if gi.Closed || gi.Title == w.releaseStatusTitle() {
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 df08340..659f6b0 100644
--- a/cmd/releasebot/main.go
+++ b/cmd/releasebot/main.go
@@ -51,7 +51,7 @@
}
func usage() {
- fmt.Fprintln(os.Stderr, "usage: releasebot -mode <release mode> [-dry-run] go1.8.5")
+ fmt.Fprintln(os.Stderr, "usage: releasebot -mode <release mode> [-dry-run] {go1.8.5|go1.10beta2}")
fmt.Fprintln(os.Stderr, "Release modes:")
fmt.Fprintln(os.Stderr)
for m := range releaseModes {
@@ -81,6 +81,20 @@
var wg sync.WaitGroup
for _, release := range flag.Args() {
+ if strings.Contains(release, "beta") {
+ w := &Work{
+ Prepare: *modeFlag == "prepare",
+ Version: release,
+ BetaRelease: true,
+ }
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ w.doRelease()
+ }()
+ continue
+ }
+
errFoundMilestone := errors.New("found milestone")
err := goRepo.ForeachMilestone(func(m *maintner.GitHubMilestone) error {
if strings.ToLower(m.Title) == release {
@@ -91,9 +105,9 @@
w := &Work{
Milestone: m,
NextMilestone: nextM,
+ Prepare: *modeFlag == "prepare",
+ Version: release,
}
- w.Prepare = *modeFlag == "prepare"
- w.Version = release
wg.Add(1)
go func() {
defer wg.Done()
@@ -174,12 +188,11 @@
logBuf *bytes.Buffer
log *log.Logger
- Prepare bool // create the release commit and submit it for review
+ Prepare bool // create the release commit and submit it for review
+ BetaRelease bool
- Milestone *maintner.GitHubMilestone
- NextMilestone *maintner.GitHubMilestone // Next minor milestone
- ReleaseIssue int // Release status issue number
- ReleaseBranch string
+ ReleaseIssue int // Release status issue number
+ ReleaseBranch string // "master" for beta releases
Dir string // work directory ($HOME/go-releasebot-work/<release>)
Errors []string
ReleaseBinary string
@@ -188,6 +201,10 @@
releaseMu sync.Mutex
ReleaseInfo map[string]*ReleaseInfo // map and info protected by releaseMu
+
+ // Properties set for minor releases only.
+ Milestone *maintner.GitHubMilestone
+ NextMilestone *maintner.GitHubMilestone // Next minor milestone
}
// ReleaseInfo describes a release build for a specific target.
@@ -283,30 +300,48 @@
w.log.Printf("starting")
+ if w.BetaRelease {
+ w.ReleaseBranch = "master"
+ } else {
+ shortRel := strings.ToLower(w.Milestone.Title)
+ shortRel = shortRel[:strings.LastIndex(shortRel, ".")]
+ w.ReleaseBranch = "release-branch." + shortRel
+ }
+
w.checkSpelling()
- w.checkReleaseBlockers()
w.gitCheckout()
- w.checkDocs()
+ if !w.BetaRelease {
+ w.checkReleaseBlockers()
+ w.checkDocs()
+ } else {
+ // TODO: go tool api -allow_new false
+ }
w.findOrCreateReleaseIssue()
if len(w.Errors) > 0 && !dryRun {
w.logError("**Found errors during release. Stopping!**")
return
}
- if w.Prepare {
+ if w.Prepare && w.BetaRelease {
+ w.nextStepsBeta()
+ } else if w.Prepare {
changeID := w.writeVersion()
w.nextStepsPrepare(changeID)
} else {
- w.checkVersion()
// TODO: check build.golang.org
+ if !w.BetaRelease {
+ w.checkVersion()
+ }
if len(w.Errors) > 0 {
w.logError("**Found errors during release. Stopping!**")
return
}
w.gitTagVersion()
w.buildReleases()
- w.pushIssues()
- w.closeMilestone()
+ if !w.BetaRelease {
+ w.pushIssues()
+ w.closeMilestone()
+ }
w.nextStepsRelease()
}
}
@@ -349,6 +384,14 @@
`, changeID)
}
+func (w *Work) nextStepsBeta() {
+ w.log.Printf(`
+
+The release is ready. Run with mode=release to execute it.
+
+`)
+}
+
func (w *Work) nextStepsRelease() {
w.log.Printf(`