gotipplay: identify the gotip playground build in the UI

Attempt to clearly label the Go tip playground as a development build,
and surface the version string.

For some reason I had to install git in the build-playground phase of
the Docker build, to avoid errors from the Go command. I'm not sure why
this is, but it seems harmless.

For golang/go#48517

Change-Id: I35b150686c9f177d76024cc38ff62cb8785525e0
Reviewed-on: https://go-review.googlesource.com/c/playground/+/363980
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
diff --git a/Dockerfile b/Dockerfile
index 6a94f60..af37ec4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -50,7 +50,7 @@
 # Build playground web server.
 FROM debian:buster as build-playground
 
-RUN apt-get update && apt-get install -y ca-certificates --no-install-recommends
+RUN apt-get update && apt-get install -y ca-certificates git --no-install-recommends
 # Build playground from Go built at GO_VERSION.
 COPY --from=build-go /usr/local/go /usr/local/go
 ENV GOROOT /usr/local/go
diff --git a/README.md b/README.md
index 5001f98..b145b8c 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,9 @@
 cat /path/to/code.go | go run client.go | curl -s --upload-file - localhost:8080/compile
 ```
 
+To run the "gotip" version of the playground, set `GOTIP=true`
+in your environment (via `-e GOTIP=true` if using `docker run`).
+
 ## Deployment
 
 ### Deployment Triggers
@@ -39,7 +42,14 @@
 The Cloud Build configuration will always build and deploy with the latest supported release of Go.
 
 ```bash
-gcloud builds submit --config deploy/deploy.json .
+gcloud --project=golang-org builds submit --config deploy/deploy.json .
+```
+
+To deploy the "Go tip" version of the playground, which uses the latest
+development build, use `deploy_gotip.json` instead:
+
+```bash
+gcloud --project=golang-org builds submit --config deploy/deploy_gotip.json .
 ```
 
 ### Deploy via gcloud app deploy
diff --git a/app.gotip.yaml b/app.gotip.yaml
index 5894c9e..2e129bc 100644
--- a/app.gotip.yaml
+++ b/app.gotip.yaml
@@ -18,4 +18,5 @@
 
 env_variables:
   MEMCACHED_ADDR: 'memcached-play-golang:11211'
+  GOTIP: true
 
diff --git a/edit.go b/edit.go
index c8cb974..3d63848 100644
--- a/edit.go
+++ b/edit.go
@@ -23,6 +23,7 @@
 	Share     bool
 	Analytics bool
 	GoVersion string
+	Gotip     bool
 }
 
 func (s *server) handleEdit(w http.ResponseWriter, r *http.Request) {
@@ -44,7 +45,11 @@
 		return
 	}
 
-	snip := &snippet{Body: []byte(hello)}
+	content := hello
+	if s.gotip {
+		content = helloGotip
+	}
+	snip := &snippet{Body: []byte(content)}
 	if strings.HasPrefix(r.URL.Path, "/p/") {
 		if !allowShare(r) {
 			w.WriteHeader(http.StatusUnavailableForLegalReasons)
@@ -82,6 +87,7 @@
 		Share:     allowShare(r),
 		Analytics: r.Host == hostname,
 		GoVersion: runtime.Version(),
+		Gotip:     s.gotip,
 	}
 	if err := editTemplate.Execute(w, data); err != nil {
 		s.log.Errorf("editTemplate.Execute(w, %+v): %v", data, err)
@@ -99,3 +105,23 @@
 	fmt.Println("Hello, playground")
 }
 `
+
+var helloGotip = fmt.Sprintf(`package main
+
+import (
+	"fmt"
+)
+
+// This playground uses a development build of Go:
+// %s
+
+func Print[T any](s ...T) {
+	for _, v := range s {
+		fmt.Print(v)
+	}
+}
+
+func main() {
+	Print("Hello, ", "playground\n")
+}
+`, runtime.Version())
diff --git a/edit.html b/edit.html
index 14b5e4b..bf5e4df 100644
--- a/edit.html
+++ b/edit.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <html>
 	<head>
-		<title>The Go Playground</title>
+		<title>The {{if .Gotip}}Gotip{{else}}Go{{end}} Playground</title>
 		<link rel="stylesheet" href="/static/style.css">
 		{{if .Analytics}}
 		<script async src="https://www.googletagmanager.com/gtag/js?id=UA-11222381-7"></script>
@@ -103,7 +103,7 @@
 	<body itemscope itemtype="http://schema.org/CreativeWork">
 		<input type="button" value="Run" id="embedRun">
 		<div id="banner">
-			<div id="head" itemprop="name">The Go Playground</div>
+			<div id="head" itemprop="name">The {{if .Gotip}}<a href="https://golang.org/dl/gotip">Gotip</a>{{else}}Go{{end}} Playground</div>
 			<input type="button" value="Run" id="run">
 			<input type="button" value="Format" id="fmt">
 			<div id="importsBox">
@@ -185,7 +185,11 @@
 </p>
 
 <p>
+{{if .Gotip}}
+This playground uses a development version of Go.<br>
+{{else}}
 The playground uses the latest stable release of Go.<br>
+{{end}}
 The current version is <a href="/p/Ztyu2FJaajl">{{.GoVersion}}</a>.
 </p>
 
diff --git a/main.go b/main.go
index ed59695..1d6c9ac 100644
--- a/main.go
+++ b/main.go
@@ -44,6 +44,9 @@
 			log.Printf("App (project ID: %q) is NOT caching results", pid)
 		}
 		s.log = log
+		if gotip := os.Getenv("GOTIP"); gotip == "true" {
+			s.gotip = true
+		}
 		return nil
 	}, enableMetrics)
 	if err != nil {
diff --git a/server.go b/server.go
index 8352c51..ff03baa 100644
--- a/server.go
+++ b/server.go
@@ -19,6 +19,7 @@
 	db    store
 	log   logger
 	cache responseCache
+	gotip bool // if set, server is using gotip
 
 	// When the executable was last modified. Used for caching headers of compiled assets.
 	modtime time.Time
diff --git a/static/style.css b/static/style.css
index 4e5fc45..e9d2c25 100644
--- a/static/style.css
+++ b/static/style.css
@@ -182,4 +182,4 @@
 	z-index: 1;
 	top: 10px;
 	right: 10px;
-}
\ No newline at end of file
+}