зеркало из https://github.com/golang/playground.git
all: use the previous major Go release to bootstrap the build
To avoid having to maintain GO_BOOTSTRAP_VERSION in the playground Dockerfile, always use the latest "published" minor of the previous Go release as the bootstrap version, which per golang/go#54265 should always be a sufficiently recent bootstrap version. Here "published" means that the toolchain must exist, since it will be downloaded for bootstrap. To enable this, add a `-toolchain` flag to the latestgo command, which selects versions from the set of published toolchains, rather than from Gerrit tags. Fixes golang/go#69238 Change-Id: Ib4d4d7f2c0d5c4fbdccfec5d8bb83c040e0c5384 Reviewed-on: https://go-review.googlesource.com/c/playground/+/610675 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Родитель
a92027e249
Коммит
b6b44f662a
13
Dockerfile
13
Dockerfile
|
@ -12,6 +12,14 @@
|
|||
# version of Go. See the configuration in the deploy directory.
|
||||
ARG GO_VERSION=go1.22.6
|
||||
|
||||
# GO_BOOTSTRAP_VERSION is downloaded below and used to bootstrap the build from
|
||||
# source. Therefore, this should be a version that is guaranteed to have
|
||||
# published artifacts, such as the latest minor of the previous major Go
|
||||
# release.
|
||||
#
|
||||
# See also https://go.dev/issue/69238.
|
||||
ARG GO_BOOSTRAP_VERSION=go1.22.6
|
||||
|
||||
############################################################################
|
||||
# Build Go at GO_VERSION, and build faketime standard library.
|
||||
FROM debian:buster AS build-go
|
||||
|
@ -22,9 +30,12 @@ RUN apt-get update && apt-get install -y ${BUILD_DEPS} --no-install-recommends
|
|||
|
||||
ENV GOPATH /go
|
||||
ENV GOROOT_BOOTSTRAP=/usr/local/go-bootstrap
|
||||
ENV GO_BOOTSTRAP_VERSION go1.22.6
|
||||
|
||||
# https://docs.docker.com/reference/dockerfile/#understand-how-arg-and-from-interact
|
||||
ARG GO_VERSION
|
||||
ENV GO_VERSION ${GO_VERSION}
|
||||
ARG GO_BOOTSTRAP_VERSION
|
||||
ENV GO_BOOTSTRAP_VERSION ${GO_BOOTSTRAP_VERSION}
|
||||
|
||||
# Get a bootstrap version of Go for building GO_VERSION. At the time
|
||||
# of this Dockerfile being built, GO_VERSION's artifacts may not yet
|
||||
|
|
|
@ -7,9 +7,12 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -18,16 +21,38 @@ import (
|
|||
"golang.org/x/build/maintner/maintnerd/maintapi/version"
|
||||
)
|
||||
|
||||
var prev = flag.Bool("prev", false, "whether to query the previous Go release, rather than the last (e.g. 1.17 versus 1.18)")
|
||||
var (
|
||||
prev = flag.Bool("prev", false, "if set, query the previous Go release rather than the last (e.g. 1.17 versus 1.18)")
|
||||
toolchain = flag.Bool("toolchain", false, "if set, query released toolchains, rather than gerrit tags; toolchains may lag behind gerrit")
|
||||
)
|
||||
|
||||
func main() {
|
||||
client := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var latest []string
|
||||
if *toolchain {
|
||||
latest = latestToolchainVersions(ctx)
|
||||
} else {
|
||||
client := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
|
||||
latest = latestGerritVersions(ctx, client)
|
||||
}
|
||||
if len(latest) < 2 {
|
||||
log.Fatalf("found %d versions, need at least 2", len(latest))
|
||||
}
|
||||
|
||||
if *prev {
|
||||
fmt.Println(latest[1])
|
||||
} else {
|
||||
fmt.Println(latest[0])
|
||||
}
|
||||
}
|
||||
|
||||
// latestGerritVersions queries the latest versions for each major Go release,
|
||||
// among Gerrit tags.
|
||||
func latestGerritVersions(ctx context.Context, client *gerrit.Client) []string {
|
||||
tagInfo, err := client.GetProjectTags(ctx, "go")
|
||||
if err != nil {
|
||||
log.Fatalf("error retrieving project tags for 'go': %v", err)
|
||||
|
@ -37,6 +62,54 @@ func main() {
|
|||
log.Fatalln("no project tags found for 'go'")
|
||||
}
|
||||
|
||||
var tags []string
|
||||
for _, tag := range tagInfo {
|
||||
tags = append(tags, strings.TrimPrefix(tag.Ref, "refs/tags/"))
|
||||
}
|
||||
return latestPatches(tags)
|
||||
}
|
||||
|
||||
// latestToolchainVersions queries the latest versions for each major Go
|
||||
// release, among published toolchains. It may have fewer versions than
|
||||
// [latestGerritVersions], because not all toolchains may be published.
|
||||
func latestToolchainVersions(ctx context.Context) []string {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://go.dev/dl/?mode=json", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("NewRequest: %v", err)
|
||||
}
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf("fetching toolchains: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
log.Fatalf("fetching toolchains: got status %d, want 200", res.StatusCode)
|
||||
}
|
||||
data, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("reading body: %v", err)
|
||||
}
|
||||
|
||||
type release struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
var releases []release
|
||||
if err := json.Unmarshal(data, &releases); err != nil {
|
||||
log.Fatalf("unmarshaling releases JSON: %v", err)
|
||||
}
|
||||
var all []string
|
||||
for _, rel := range releases {
|
||||
all = append(all, rel.Version)
|
||||
}
|
||||
return latestPatches(all)
|
||||
}
|
||||
|
||||
// latestPatches returns the latest minor release of each major Go version,
|
||||
// among the set of tag or tag-like strings. The result is in descending
|
||||
// order, such that later versions are sorted first.
|
||||
//
|
||||
// Tags that aren't of the form goX, goX.Y, or goX.Y.Z are ignored.
|
||||
func latestPatches(tags []string) []string {
|
||||
// Find the latest patch version for each major Go version.
|
||||
type majMin struct {
|
||||
maj, min int // maj, min in semver terminology, which corresponds to a major go release
|
||||
|
@ -47,16 +120,14 @@ func main() {
|
|||
}
|
||||
latestPatches := make(map[majMin]patchTag) // (maj, min) -> latest patch info
|
||||
|
||||
for _, tag := range tagInfo {
|
||||
tagName := strings.TrimPrefix(tag.Ref, "refs/tags/")
|
||||
maj, min, patch, ok := version.ParseTag(tagName)
|
||||
for _, tag := range tags {
|
||||
maj, min, patch, ok := version.ParseTag(tag)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
mm := majMin{maj, min}
|
||||
if latest, ok := latestPatches[mm]; !ok || latest.patch < patch {
|
||||
latestPatches[mm] = patchTag{patch, tagName}
|
||||
latestPatches[mm] = patchTag{patch, tag}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,18 +135,17 @@ func main() {
|
|||
for mm := range latestPatches {
|
||||
mms = append(mms, mm)
|
||||
}
|
||||
// Sort by descending semantic ordering, so that later versions are first.
|
||||
sort.Slice(mms, func(i, j int) bool {
|
||||
if mms[i].maj != mms[j].maj {
|
||||
return mms[i].maj < mms[j].maj
|
||||
return mms[i].maj > mms[j].maj
|
||||
}
|
||||
return mms[i].min < mms[j].min
|
||||
return mms[i].min > mms[j].min
|
||||
})
|
||||
|
||||
var mm majMin
|
||||
if *prev && len(mms) > 1 {
|
||||
mm = mms[len(mms)-2] // latest patch of the previous Go release
|
||||
} else {
|
||||
mm = mms[len(mms)-1]
|
||||
var latest []string
|
||||
for _, mm := range mms {
|
||||
latest = append(latest, latestPatches[mm].tag)
|
||||
}
|
||||
fmt.Print(latestPatches[mm].tag)
|
||||
return latest
|
||||
}
|
||||
|
|
|
@ -8,12 +8,20 @@
|
|||
"go run golang.org/x/playground/cmd/latestgo > /workspace/goversion && echo GO_VERSION=`cat /workspace/goversion`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "golang",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"go run golang.org/x/playground/cmd/latestgo -prev -toolchain > /workspace/gobootstrapversion && echo GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gcr.io/cloud-builders/docker",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"docker build --build-arg GO_VERSION=`cat /workspace/goversion` -t gcr.io/$PROJECT_ID/playground ."
|
||||
"docker build --build-arg GO_VERSION=`cat /workspace/goversion` --build-arg GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion` -t gcr.io/$PROJECT_ID/playground ."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -8,12 +8,20 @@
|
|||
"go run golang.org/x/playground/cmd/latestgo -prev > /workspace/goversion && echo GO_VERSION=`cat /workspace/goversion`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "golang",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"go run golang.org/x/playground/cmd/latestgo -prev -toolchain > /workspace/gobootstrapversion && echo GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gcr.io/cloud-builders/docker",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"docker build --build-arg GO_VERSION=`cat /workspace/goversion` -t gcr.io/$PROJECT_ID/playground-goprev ."
|
||||
"docker build --build-arg GO_VERSION=`cat /workspace/goversion` --build_arg GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion` -t gcr.io/$PROJECT_ID/playground-goprev ."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
{
|
||||
"steps": [
|
||||
{
|
||||
"name": "golang",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"go run golang.org/x/playground/cmd/latestgo -prev -toolchain > /workspace/gobootstrapversion && echo GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gcr.io/cloud-builders/docker",
|
||||
"entrypoint": "sh",
|
||||
"args": [
|
||||
"-c",
|
||||
"docker build --build-arg GO_VERSION=master -t gcr.io/$PROJECT_ID/playground-gotip ."
|
||||
"docker build --build-arg GO_VERSION=master --build-arg GO_BOOTSTRAP_VERSION=`cat /workspace/gobootstrapversion` -t gcr.io/$PROJECT_ID/playground-gotip ."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче