Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9028cb5

Browse files
committedFeb 24, 2021
all: support Go 1.16 in the Go Playground
This makes a number of changes in order to support modules being on by default in Go 1.16. - Change default Go version in Dockerfile to go1.16 - Change default Go version in sandbox/Dockerfile to go1.16 - Build playground web server with GO_VERSION instead of GO_BOOTSTRAP_VERSION (for golang/go#40319) - Drop code related to non-module codepaths. This should keep us future-proof for later versions of Go. This works for me testing locally with gVisor's runsc. Fixes golang/go#44389 Fixes golang/go#40319 Change-Id: Ib99510e662658b75c401567314c3e8ed612002a0 Reviewed-on: https://go-review.googlesource.com/c/playground/+/295649 Trust: Alexander Rakoczy <[email protected]> Run-TryBot: Alexander Rakoczy <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 9040051 commit 9028cb5

File tree

6 files changed

+64
-150
lines changed

6 files changed

+64
-150
lines changed
 

‎Dockerfile

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,74 @@
22
# Use of this source code is governed by a BSD-style
33
# license that can be found in the LICENSE file.
44

5-
ARG GO_VERSION=go1.14.1
5+
# The playground builds Go from a bootstrap version for two reasons:
6+
# - The playground deployment is triggered before the artifacts are
7+
# published for the latest version of Go.
8+
# - The sandbox builds the Go standard library with a custom build
9+
# flag called faketime.
610

7-
FROM debian:buster AS go-faketime
11+
# GO_VERSION is provided by Cloud Build, and is set to the latest
12+
# version of Go. See the configuration in the deploy directory.
13+
ARG GO_VERSION=go1.16
14+
15+
############################################################################
16+
# Build Go at GO_VERSION, and build faketime standard library.
17+
FROM debian:buster AS build-go
818
LABEL maintainer="golang-dev@googlegroups.com"
919

1020
ENV BUILD_DEPS 'curl git gcc patch libc6-dev ca-certificates'
1121
RUN apt-get update && apt-get install -y ${BUILD_DEPS} --no-install-recommends
1222

1323
ENV GOPATH /go
14-
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
15-
ENV GO_BOOTSTRAP_VERSION go1.14.1
24+
ENV GOROOT_BOOTSTRAP=/usr/local/go-bootstrap
25+
ENV GO_BOOTSTRAP_VERSION go1.16
1626
ARG GO_VERSION
1727
ENV GO_VERSION ${GO_VERSION}
1828

19-
# Get a version of Go for building the playground
29+
# Get a bootstrap version of Go for building GO_VERSION. At the time
30+
# of this Dockerfile being built, GO_VERSION's artifacts may not yet
31+
# be published.
2032
RUN curl -sSL https://dl.google.com/go/$GO_BOOTSTRAP_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz
2133
RUN curl -sSL https://dl.google.com/go/$GO_BOOTSTRAP_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256
2234
RUN echo "$(cat /tmp/go.tar.gz.sha256) /tmp/go.tar.gz" | sha256sum -c -
23-
RUN mkdir -p /usr/local/go
24-
RUN tar --strip=1 -C /usr/local/go -vxzf /tmp/go.tar.gz
35+
RUN mkdir -p $GOROOT_BOOTSTRAP
36+
RUN tar --strip=1 -C $GOROOT_BOOTSTRAP -vxzf /tmp/go.tar.gz
2537

2638
RUN mkdir /gocache
2739
ENV GOCACHE /gocache
2840
ENV GO111MODULE on
2941
ENV GOPROXY=https://proxy.golang.org
3042

31-
# Compile Go at target sandbox version and install standard library with --tags=faketime.
43+
# Compile Go at target version in /usr/local/go.
3244
WORKDIR /usr/local
33-
RUN git clone https://go.googlesource.com/go go-faketime && cd go-faketime && git reset --hard $GO_VERSION
34-
WORKDIR /usr/local/go-faketime/src
45+
RUN git clone https://go.googlesource.com/go go && cd go && git reset --hard $GO_VERSION
46+
WORKDIR /usr/local/go/src
3547
RUN ./make.bash
48+
49+
# Make a copy in /usr/local/go-faketime where the standard library
50+
# is installed with -tags=faketime.
51+
RUN cp -R /usr/local/go /usr/local/go-faketime
3652
ENV GOROOT /usr/local/go-faketime
53+
WORKDIR /usr/local/go-faketime/src
3754
RUN ../bin/go install --tags=faketime std
3855

39-
FROM golang:1.14 as build-playground
56+
############################################################################
57+
# Build playground web server.
58+
FROM debian:buster as build-playground
4059

60+
RUN apt-get update && apt-get install -y ca-certificates --no-install-recommends
61+
# Build playground from Go built at GO_VERSION.
62+
COPY --from=build-go /usr/local/go /usr/local/go
63+
ENV GOROOT /usr/local/go
64+
ENV GOPATH /go
65+
ENV PATH="/go/bin:/usr/local/go/bin:${PATH}"
66+
# Cache dependencies for efficient Dockerfile building.
4167
COPY go.mod /go/src/playground/go.mod
4268
COPY go.sum /go/src/playground/go.sum
4369
WORKDIR /go/src/playground
4470
RUN go mod download
4571

46-
# Add and compile playground daemon
72+
# Add and compile playground daemon.
4773
COPY . /go/src/playground/
4874
RUN go install
4975

@@ -53,43 +79,19 @@ FROM debian:buster
5379

5480
RUN apt-get update && apt-get install -y git ca-certificates --no-install-recommends
5581

56-
COPY --from=go-faketime /usr/local/go-faketime /usr/local/go-faketime
82+
COPY --from=build-go /usr/local/go-faketime /usr/local/go-faketime
5783

5884
ARG GO_VERSION
5985
ENV GO_VERSION ${GO_VERSION}
6086
ENV GOPATH /go
61-
ENV PATH /usr/local/go-faketime/bin:$GOPATH/bin:$PATH
62-
63-
# Add and compile tour packages
64-
RUN go get \
65-
golang.org/x/tour/pic \
66-
golang.org/x/tour/reader \
67-
golang.org/x/tour/tree \
68-
golang.org/x/tour/wc \
69-
golang.org/x/talks/content/2016/applicative/google && \
70-
rm -rf $GOPATH/src/golang.org/x/tour/.git && \
71-
rm -rf $GOPATH/src/golang.org/x/talks/.git
72-
73-
# Add tour packages under their old import paths (so old snippets still work)
74-
RUN mkdir -p $GOPATH/src/code.google.com/p/go-tour && \
75-
cp -R $GOPATH/src/golang.org/x/tour/* $GOPATH/src/code.google.com/p/go-tour/ && \
76-
sed -i 's_// import_// public import_' $(find $GOPATH/src/code.google.com/p/go-tour/ -name *.go) && \
77-
go install \
78-
code.google.com/p/go-tour/pic \
79-
code.google.com/p/go-tour/reader \
80-
code.google.com/p/go-tour/tree \
81-
code.google.com/p/go-tour/wc
87+
ENV PATH="/go/bin:/usr/local/go-faketime/bin:${PATH}"
8288

8389
RUN mkdir /app
84-
8590
COPY --from=build-playground /go/bin/playground /app
8691
COPY edit.html /app
8792
COPY static /app/static
8893
COPY examples /app/examples
8994
WORKDIR /app
9095

91-
# Whether we allow third-party imports via proxy.golang.org:
92-
ENV ALLOW_PLAY_MODULE_DOWNLOADS true
93-
9496
EXPOSE 8080
9597
ENTRYPOINT ["/app/playground"]

‎sandbox.go

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,6 @@ type buildResult struct {
396396
goPath string
397397
// exePath is the path to the built binary.
398398
exePath string
399-
// useModules is true if the binary was built with module support.
400-
useModules bool
401399
// testParam is set if tests should be run when running the binary.
402400
testParam string
403401
// errorMessage is an error message string to be returned to the user.
@@ -408,7 +406,7 @@ type buildResult struct {
408406

409407
// cleanup cleans up the temporary goPath created when building with module support.
410408
func (b *buildResult) cleanup() error {
411-
if b.useModules && b.goPath != "" {
409+
if b.goPath != "" {
412410
return os.RemoveAll(b.goPath)
413411
}
414412
return nil
@@ -435,8 +433,7 @@ func sandboxBuild(ctx context.Context, tmpDir string, in []byte, vet bool) (*bui
435433
}
436434
}
437435

438-
br.useModules = allowModuleDownloads(files)
439-
if !files.Contains("go.mod") && br.useModules {
436+
if !files.Contains("go.mod") {
440437
files.AddFile("go.mod", []byte("module play\n"))
441438
}
442439

@@ -471,20 +468,16 @@ func sandboxBuild(ctx context.Context, tmpDir string, in []byte, vet bool) (*bui
471468
cmd.Dir = tmpDir
472469
cmd.Env = []string{"GOOS=linux", "GOARCH=amd64", "GOROOT=/usr/local/go-faketime"}
473470
cmd.Env = append(cmd.Env, "GOCACHE="+goCache)
474-
if br.useModules {
475-
// Create a GOPATH just for modules to be downloaded
476-
// into GOPATH/pkg/mod.
477-
cmd.Args = append(cmd.Args, "-modcacherw")
478-
br.goPath, err = ioutil.TempDir("", "gopath")
479-
if err != nil {
480-
log.Printf("error creating temp directory: %v", err)
481-
return nil, fmt.Errorf("error creating temp directory: %v", err)
482-
}
483-
cmd.Env = append(cmd.Env, "GO111MODULE=on", "GOPROXY="+playgroundGoproxy())
484-
} else {
485-
br.goPath = os.Getenv("GOPATH") // contains old code.google.com/p/go-tour, etc
486-
cmd.Env = append(cmd.Env, "GO111MODULE=off") // in case it becomes on by default later
471+
// Create a GOPATH just for modules to be downloaded
472+
// into GOPATH/pkg/mod.
473+
cmd.Args = append(cmd.Args, "-modcacherw")
474+
cmd.Args = append(cmd.Args, "-mod=mod")
475+
br.goPath, err = ioutil.TempDir("", "gopath")
476+
if err != nil {
477+
log.Printf("error creating temp directory: %v", err)
478+
return nil, fmt.Errorf("error creating temp directory: %v", err)
487479
}
480+
cmd.Env = append(cmd.Env, "GO111MODULE=on", "GOPROXY="+playgroundGoproxy())
488481
cmd.Args = append(cmd.Args, buildPkgArg)
489482
cmd.Env = append(cmd.Env, "GOPATH="+br.goPath)
490483
out := &bytes.Buffer{}
@@ -521,7 +514,7 @@ func sandboxBuild(ctx context.Context, tmpDir string, in []byte, vet bool) (*bui
521514
}
522515
if vet {
523516
// TODO: do this concurrently with the execution to reduce latency.
524-
br.vetOut, err = vetCheckInDir(tmpDir, br.goPath, br.useModules)
517+
br.vetOut, err = vetCheckInDir(tmpDir, br.goPath)
525518
if err != nil {
526519
return nil, fmt.Errorf("running vet: %v", err)
527520
}
@@ -567,21 +560,6 @@ func sandboxRun(ctx context.Context, exePath string, testParam string) (sandboxt
567560
return execRes, nil
568561
}
569562

570-
// allowModuleDownloads reports whether the code snippet in src should be allowed
571-
// to download modules.
572-
func allowModuleDownloads(files *fileSet) bool {
573-
if files.Num() == 1 && bytes.Contains(files.Data(progName), []byte(`"code.google.com/p/go-tour/`)) {
574-
// This domain doesn't exist anymore but we want old snippets using
575-
// these packages to still run, so the Dockerfile adds these packages
576-
// at this name in $GOPATH. Any snippets using this old name wouldn't
577-
// have expected (or been able to use) third-party packages anyway,
578-
// so disabling modules and proxy fetches is acceptable.
579-
return false
580-
}
581-
v, _ := strconv.ParseBool(os.Getenv("ALLOW_PLAY_MODULE_DOWNLOADS"))
582-
return v
583-
}
584-
585563
// playgroundGoproxy returns the GOPROXY environment config the playground should use.
586564
// It is fetched from the environment variable PLAY_GOPROXY. A missing or empty
587565
// value for PLAY_GOPROXY returns the default value of https://proxy.golang.org.

‎sandbox/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# environment so the play-sandbox server can connect to the host's
55
# docker daemon, which has the gvisor "runsc" runtime available.
66

7-
FROM golang:1.14 AS build
7+
FROM golang:1.16 AS build
88

99
COPY go.mod /go/src/playground/go.mod
1010
COPY go.sum /go/src/playground/go.sum

‎server_test.go

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -299,37 +299,6 @@ func TestCommandHandler(t *testing.T) {
299299
}
300300
}
301301

302-
func TestAllowModuleDownloads(t *testing.T) {
303-
const envKey = "ALLOW_PLAY_MODULE_DOWNLOADS"
304-
defer func(old string) { os.Setenv(envKey, old) }(os.Getenv(envKey))
305-
306-
tests := []struct {
307-
src string
308-
env string
309-
want bool
310-
}{
311-
{src: "package main", want: true},
312-
{src: "package main", env: "false", want: false},
313-
{src: `import "code.google.com/p/go-tour/"`, want: false},
314-
}
315-
for i, tt := range tests {
316-
if tt.env != "" {
317-
os.Setenv(envKey, tt.env)
318-
} else {
319-
os.Setenv(envKey, "true")
320-
}
321-
files, err := splitFiles([]byte(tt.src))
322-
if err != nil {
323-
t.Errorf("%d. splitFiles = %v", i, err)
324-
continue
325-
}
326-
got := allowModuleDownloads(files)
327-
if got != tt.want {
328-
t.Errorf("%d. allow = %v; want %v; files:\n%s", i, got, tt.want, filesAsString(files))
329-
}
330-
}
331-
}
332-
333302
func TestPlaygroundGoproxy(t *testing.T) {
334303
const envKey = "PLAY_GOPROXY"
335304
defer os.Setenv(envKey, os.Getenv(envKey))

‎tests.go

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ func (s *server) runTests() {
4141
stdlog.Fatal(err)
4242
}
4343

44-
// Enable module downloads for testing:
45-
defer func(old string) { os.Setenv("ALLOW_PLAY_MODULE_DOWNLOADS", old) }(os.Getenv("ALLOW_PLAY_MODULE_DOWNLOADS"))
46-
os.Setenv("ALLOW_PLAY_MODULE_DOWNLOADS", "true")
47-
4844
failed := false
4945
for i, t := range tests {
5046
stdlog.Printf("testing case %d (%q)...\n", i, t.name)
@@ -178,30 +174,6 @@ func main() {
178174
}
179175
}
180176
`, want: "timers fired as expected"},
181-
182-
{
183-
name: "old_tour_pkgs_in_gopath",
184-
prog: `
185-
package main
186-
187-
import (
188-
"code.google.com/p/go-tour/pic"
189-
"code.google.com/p/go-tour/reader"
190-
"code.google.com/p/go-tour/tree"
191-
"code.google.com/p/go-tour/wc"
192-
)
193-
194-
var (
195-
_ = pic.Show
196-
_ = reader.Validate
197-
_ = tree.New
198-
_ = wc.Test
199-
)
200-
201-
func main() {
202-
println("ok")
203-
}
204-
`, want: "ok"},
205177
{
206178
name: "must_be_package_main",
207179
prog: `

‎vet.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
// Deprecated: this is the handler for the legacy /vet endpoint; use
2222
// the /compile (compileAndRun) handler instead with the WithVet
2323
// boolean set. This code path doesn't support modules and only exists
24-
// as a temporary compatiblity bridge to older javascript clients.
24+
// as a temporary compatibility bridge to older javascript clients.
2525
func vetCheck(ctx context.Context, req *request) (*response, error) {
2626
tmpDir, err := ioutil.TempDir("", "vet")
2727
if err != nil {
@@ -33,8 +33,7 @@ func vetCheck(ctx context.Context, req *request) (*response, error) {
3333
if err := ioutil.WriteFile(in, []byte(req.Body), 0400); err != nil {
3434
return nil, fmt.Errorf("error creating temp file %q: %v", in, err)
3535
}
36-
const useModules = false // legacy handler; no modules (see func comment)
37-
vetOutput, err := vetCheckInDir(tmpDir, os.Getenv("GOPATH"), useModules)
36+
vetOutput, err := vetCheckInDir(tmpDir, os.Getenv("GOPATH"))
3837
if err != nil {
3938
// This is about errors running vet, not vet returning output.
4039
return nil, err
@@ -43,27 +42,21 @@ func vetCheck(ctx context.Context, req *request) (*response, error) {
4342
}
4443

4544
// vetCheckInDir runs go vet in the provided directory, using the
46-
// provided GOPATH value, and whether modules are enabled. The
47-
// returned error is only about whether go vet was able to run, not
48-
// whether vet reported problem. The returned value is ("", nil) if
49-
// vet successfully found nothing, and (non-empty, nil) if vet ran and
50-
// found issues.
51-
func vetCheckInDir(dir, goPath string, modules bool) (output string, execErr error) {
45+
// provided GOPATH value. The returned error is only about whether
46+
// go vet was able to run, not whether vet reported problem. The
47+
// returned value is ("", nil) if vet successfully found nothing,
48+
// and (non-empty, nil) if vet ran and found issues.
49+
func vetCheckInDir(dir, goPath string) (output string, execErr error) {
5250
cmd := exec.Command("go", "vet")
53-
if !modules {
54-
cmd.Args = append(cmd.Args, progName)
55-
}
5651
cmd.Dir = dir
5752
// Linux go binary is not built with CGO_ENABLED=0.
5853
// Prevent vet to compile packages in cgo mode.
5954
// See #26307.
6055
cmd.Env = append(os.Environ(), "CGO_ENABLED=0", "GOPATH="+goPath)
61-
if modules {
62-
cmd.Env = append(cmd.Env,
63-
"GO111MODULE=on",
64-
"GOPROXY="+playgroundGoproxy(),
65-
)
66-
}
56+
cmd.Env = append(cmd.Env,
57+
"GO111MODULE=on",
58+
"GOPROXY="+playgroundGoproxy(),
59+
)
6760
out, err := cmd.CombinedOutput()
6861
if err == nil {
6962
return "", nil

0 commit comments

Comments
 (0)
Please sign in to comment.