playground: build playground Go from source

This changes the playground Dockerfile to build playground from source.
Cloud Builds for playground are triggered when a new Go release is
tagged. Go release tags are published to repositories before binary
releases are published. This change fetches the tagged source in order
to build Go, as a tagged binary release may not be available yet.

A binary Go release is still downloaded to be used as the

The build steps use maintq to fetch the latest version of Go. maintq
currently only outputs in textproto format, requiring a step to parse
the git tag. It might be worth adding a flag or special command to
maintq to simplify the output to clarify this step of the release
process. It might also be worthwhile to move this step into the
Makefile, or a checked-in build script.

The trigger steps were tested on Cloud Build without the deployment

Updates golang/go#32606

Change-Id: I811be6aa6b5fb53fce4491e4b4ed235a0f3e62cb
Reviewed-by: Dmitri Shuralyov <>
diff --git a/Dockerfile b/Dockerfile
index 3ea5419..7ddad2a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -17,6 +17,7 @@
 ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
 ENV GOROOT_BOOTSTRAP /usr/local/gobootstrap
 ARG GO_VERSION=go1.12.6
@@ -25,17 +26,19 @@
 # Fake file system
 COPY fake_fs.lst /usr/local/playground/
-# Get the Go binary.
-RUN curl -sSL$GO_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz
-RUN curl -sSL$GO_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256
+# Get a bootstrap version of Go for building from source.
+RUN curl -sSL$GO_BOOTSTRAP_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz
+RUN curl -sSL$GO_BOOTSTRAP_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256
 RUN echo "$(cat /tmp/go.tar.gz.sha256) /tmp/go.tar.gz" | sha256sum -c -
-RUN tar -C /usr/local/ -vxzf /tmp/go.tar.gz
-# Make a copy for GOROOT_BOOTSTRAP, because we rebuild the toolchain and make.bash removes bin/go as its first step.
-RUN cp -R /usr/local/go $GOROOT_BOOTSTRAP
+RUN tar --strip=1 -C $GOROOT_BOOTSTRAP -vxzf /tmp/go.tar.gz
+# Fetch Go source for tag $GO_VERSION.
+RUN git clone --depth=1 --branch=$GO_VERSION /usr/local/go
 # Apply the fake time and fake filesystem patches.
 RUN patch /usr/local/go/src/runtime/rt0_nacl_amd64p32.s /usr/local/playground/enable-fake-time.patch
-RUN cd /usr/local/go && go run misc/nacl/mkzip.go -p syscall /usr/local/playground/fake_fs.lst src/syscall/fstest_nacl.go
-# Re-build the Go toolchain.
+RUN cd /usr/local/go && $GOROOT_BOOTSTRAP/bin/go run misc/nacl/mkzip.go -p syscall /usr/local/playground/fake_fs.lst src/syscall/fstest_nacl.go
+# Build the Go toolchain.
 RUN cd /usr/local/go/src && GOOS=nacl GOARCH=amd64p32 ./make.bash --no-clean
 RUN mkdir /gocache
diff --git a/cloudbuild_trigger.json b/cloudbuild_trigger.json
index 2fa8304..d37d803 100644
--- a/cloudbuild_trigger.json
+++ b/cloudbuild_trigger.json
@@ -20,15 +20,29 @@
+        "name": "golang",
+        "entrypoint": "bash",
+        "args": [
+          "-c",
+          "go get && cp /go/bin/maintq /workspace/maintq"
+        ]
+      },
+      {
+        "name": "debian:stretch",
+        "entrypoint": "bash",
+        "args": [
+          "-c",
+          "apt-get update && apt-get install -y ca-certificates && ./maintq list-releases | head -n 1 | sed -re 's/^.*tag_name:\"(go[0-9](\\.[0-9]+)+)\".*$/\\1/g' > /workspace/latestgo"
+        ]
+      },
+      {
         "dir": "playground",
         "name": "",
+        "entrypoint": "bash",
         "args": [
-          "build",
-          "-t",
-          "$PROJECT_ID/playground",
-          "."
-        ],
-        "timeout": "1800s"
+          "-c",
+          "docker build --build-arg GO_VERSION=`cat /workspace/latestgo` -t$PROJECT_ID/playground ."
+        ]
         "dir": "playground",
@@ -39,10 +53,10 @@
-        ],
-        "timeout": "1200s"
+        ]
+    "timeout": "1800s",
     "images": [