cmd/releasebot, cmd/release: add darwin-arm64 target for Go 1.16
For golang/go#42756.
Change-Id: Ia28fb6878617715fb674ccfad0c5801c8925270b
Reviewed-on: https://go-review.googlesource.com/c/build/+/278436
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
Trust: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/cmd/release/release.go b/cmd/release/release.go
index 59bb402..7680406 100644
--- a/cmd/release/release.go
+++ b/cmd/release/release.go
@@ -207,6 +207,13 @@
Builder: "darwin-amd64-10_15",
},
{
+ GoQuery: ">= go1.16beta1", // Go 1.16 Beta 1 is the first Go (pre-)release with the darwin/arm64 port.
+ OS: "darwin",
+ Arch: "arm64",
+ Race: true,
+ Builder: "darwin-arm64-11_0-toothrot",
+ },
+ {
OS: "linux",
Arch: "s390x",
SkipTests: true,
diff --git a/cmd/releasebot/main.go b/cmd/releasebot/main.go
index f94eae3..d76f12c 100644
--- a/cmd/releasebot/main.go
+++ b/cmd/releasebot/main.go
@@ -32,6 +32,10 @@
// A Target is a release target.
type Target struct {
+ // GoQuery is a Go version query specifying the Go versions the
+ // release target applies to. Empty string means all Go versions.
+ GoQuery string
+
Name string // Target name as accepted by cmd/release. For example, "linux-amd64".
TestOnly bool // Run tests only; don't produce a release artifact.
}
@@ -50,6 +54,7 @@
{Name: "windows-386"},
{Name: "windows-amd64"},
{Name: "darwin-amd64"},
+ {Name: "darwin-arm64", GoQuery: ">= go1.16beta1"},
{Name: "linux-s390x"},
{Name: "linux-ppc64le"},
@@ -88,8 +93,9 @@
fmt.Fprintln(os.Stderr, "need to provide a valid mode and a release name")
usage()
}
+ releaseVersion := flag.Arg(0)
for _, target := range strings.Fields(*skipTestFlag) {
- if t, ok := releaseTarget(target); !ok {
+ if t, ok := releaseTarget(target, releaseVersion); !ok {
fmt.Fprintf(os.Stderr, "target %q in -skip-test=%q is not a known target\n", target, *skipTestFlag)
usage()
} else if !t.TestOnly {
@@ -108,13 +114,11 @@
loadGithubAuth()
loadGCSAuth()
- release := flag.Arg(0)
-
w := &Work{
Prepare: *modeFlag == "prepare",
- Version: release,
- BetaRelease: strings.Contains(release, "beta"),
- RCRelease: strings.Contains(release, "rc"),
+ Version: releaseVersion,
+ BetaRelease: strings.Contains(releaseVersion, "beta"),
+ RCRelease: strings.Contains(releaseVersion, "rc"),
Security: *security,
}
@@ -147,6 +151,9 @@
log.Fatalf("cannot understand version %q", w.Version)
}
+ // Select release targets for this Go version.
+ w.ReleaseTargets = matchTargets(w.Version)
+
// Find milestones.
var err error
w.Milestone, err = getMilestone(w.Version)
@@ -244,14 +251,15 @@
RCRelease bool
Security bool // cut a security release from the internal Gerrit
- ReleaseIssue int // Release status issue number
- ReleaseBranch string // "master" for beta releases
- Dir string // work directory ($HOME/go-releasebot-work/<release>)
- StagingDir string // staging directory (a temporary directory inside <work>/release-staging)
- Errors []string
- ReleaseBinary string
- Version string
- VersionCommit string
+ ReleaseIssue int // Release status issue number
+ ReleaseBranch string // "master" for beta releases
+ Dir string // work directory ($HOME/go-releasebot-work/<release>)
+ StagingDir string // staging directory (a temporary directory inside <work>/release-staging)
+ Errors []string
+ ReleaseBinary string
+ ReleaseTargets []Target // Selected release targets for this release.
+ Version string
+ VersionCommit string
releaseMu sync.Mutex
ReleaseInfo map[string]*ReleaseInfo // map and info protected by releaseMu
@@ -560,7 +568,7 @@
// TODO: print sha256
w.releaseMu.Lock()
defer w.releaseMu.Unlock()
- for _, target := range releaseTargets {
+ for _, target := range w.ReleaseTargets {
fmt.Fprintf(md, "- %s", mdEscape(target.Name))
if target.TestOnly {
fmt.Fprintf(md, " (test only)")
@@ -671,7 +679,7 @@
}
var wg sync.WaitGroup
- for _, target := range releaseTargets {
+ for _, target := range w.ReleaseTargets {
w.releaseMu.Lock()
w.ReleaseInfo[target.Name] = new(ReleaseInfo)
w.releaseMu.Unlock()
@@ -706,7 +714,7 @@
// Check for release errors and stop if any.
w.releaseMu.Lock()
- for _, target := range releaseTargets {
+ for _, target := range w.ReleaseTargets {
for _, out := range w.ReleaseInfo[target.Name].Outputs {
if out.Error != "" || len(w.Errors) > 0 {
w.logError("RELEASE BUILD FAILED\n")
@@ -889,12 +897,43 @@
}
}
-// releaseTarget returns a release target with the specified name.
-func releaseTarget(name string) (_ Target, ok bool) {
+// releaseTarget returns a release target with the specified name
+// for the specified Go version.
+func releaseTarget(name, goVer string) (_ Target, ok bool) {
for _, t := range releaseTargets {
+ if !match(t.GoQuery, goVer) {
+ continue
+ }
if t.Name == name {
return t, true
}
}
return Target{}, false
}
+
+// matchTargets selects release targets that have a matching
+// GoQuery value for the specified Go version.
+func matchTargets(goVer string) (matched []Target) {
+ for _, t := range releaseTargets {
+ if !match(t.GoQuery, goVer) {
+ continue
+ }
+ matched = append(matched, t)
+ }
+ return matched
+}
+
+// match reports whether the Go version goVer matches the provided version query.
+// The empty query matches all Go versions.
+// match panics if given a query that it doesn't support.
+func match(query, goVer string) bool {
+ // TODO(golang.org/issue/40558): This should help inform the API for a Go version parser.
+ switch query {
+ case "": // A special case to make the zero Target.GoQuery value useful.
+ return true
+ case ">= go1.16beta1":
+ return !strings.HasPrefix(goVer, "go1.15") && !strings.HasPrefix(goVer, "go1.14")
+ default:
+ panic(fmt.Errorf("match: query %q is not supported", query))
+ }
+}
diff --git a/cmd/releasebot/main_test.go b/cmd/releasebot/main_test.go
new file mode 100644
index 0000000..5c83bdd
--- /dev/null
+++ b/cmd/releasebot/main_test.go
@@ -0,0 +1,87 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func TestTargetSelectionPerGoVersion(t *testing.T) {
+ targetNames := func(targets []Target) (names []string) {
+ for _, t := range targets {
+ names = append(names, t.Name)
+ }
+ return names
+ }
+
+ for _, tc := range []struct {
+ goVer []string // Go versions to test.
+ want []string // Expected release targets.
+ }{
+ {
+ goVer: []string{"go1.16beta1", "go1.16rc1", "go1.16", "go1.16.1"},
+ want: []string{
+ "src",
+ "linux-386",
+ "linux-armv6l",
+ "linux-amd64",
+ "linux-arm64",
+ "freebsd-386",
+ "freebsd-amd64",
+ "windows-386",
+ "windows-amd64",
+ "darwin-amd64",
+ "darwin-arm64", // New to Go 1.16.
+ "linux-s390x",
+ "linux-ppc64le",
+ "linux-amd64-longtest",
+ "windows-amd64-longtest",
+ },
+ },
+ {
+ goVer: []string{"go1.15.7", "go1.14.14"},
+ want: []string{
+ "src",
+ "linux-386",
+ "linux-armv6l",
+ "linux-amd64",
+ "linux-arm64",
+ "freebsd-386",
+ "freebsd-amd64",
+ "windows-386",
+ "windows-amd64",
+ "darwin-amd64",
+ "linux-s390x",
+ "linux-ppc64le",
+ "linux-amd64-longtest",
+ "windows-amd64-longtest",
+ },
+ },
+ } {
+ for _, goVer := range tc.goVer {
+ t.Run(goVer, func(t *testing.T) {
+ got := matchTargets(goVer)
+ if diff := cmp.Diff(tc.want, targetNames(got)); diff != "" {
+ t.Errorf("release target mismatch (-want +got):\n%s", diff)
+ }
+ })
+ }
+ }
+}
+
+func TestAllQueriesSupported(t *testing.T) {
+ for _, r := range releaseTargets {
+ t.Run(r.Name, func(t *testing.T) {
+ defer func() {
+ if err := recover(); err != nil {
+ t.Errorf("target %s uses an unsupported version query:\n%v", r.Name, err)
+ }
+ }()
+ match(r.GoQuery, "go1.15.7") // Shouldn't panic for any r.GoQuery.
+ })
+ }
+}