playground: only build binaries for health check

This change avoids cascading sandbox backend failures to the frontend
instances.

The timeout TODO is safe to remove as we now pass in the request context
for cancellation, and sandboxBuild has its own build timeout.

Updates golang/go#25224
Updates golang/go#38530

Change-Id: If892f86bad08c55429b6ebab768b83c5d7621cf1
Reviewed-on: https://go-review.googlesource.com/c/playground/+/229677
Run-TryBot: Alexander Rakoczy <alex@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
diff --git a/sandbox.go b/sandbox.go
index 76fd7fa..8931100 100644
--- a/sandbox.go
+++ b/sandbox.go
@@ -593,17 +593,20 @@
 	return "https://proxy.golang.org"
 }
 
-func (s *server) healthCheck() error {
-	ctx := context.Background() // TODO: cap it to some reasonable timeout
-	resp, err := compileAndRun(ctx, &request{Body: healthProg})
+// healthCheck attempts to build a binary from the source in healthProg.
+// It returns any error returned from sandboxBuild, or nil if none is returned.
+func (s *server) healthCheck(ctx context.Context) error {
+	tmpDir, err := ioutil.TempDir("", "sandbox")
+	if err != nil {
+		return fmt.Errorf("error creating temp directory: %v", err)
+	}
+	defer os.RemoveAll(tmpDir)
+	br, err := sandboxBuild(ctx, tmpDir, []byte(healthProg), false)
 	if err != nil {
 		return err
 	}
-	if resp.Errors != "" {
-		return fmt.Errorf("compile error: %v", resp.Errors)
-	}
-	if len(resp.Events) != 1 || resp.Events[0].Message != "ok" {
-		return fmt.Errorf("unexpected output: %v", resp.Events)
+	if br.errorMessage != "" {
+		return errors.New(br.errorMessage)
 	}
 	return nil
 }
diff --git a/server.go b/server.go
index 9161633..8352c51 100644
--- a/server.go
+++ b/server.go
@@ -75,7 +75,7 @@
 }
 
 func (s *server) handleHealthCheck(w http.ResponseWriter, r *http.Request) {
-	if err := s.healthCheck(); err != nil {
+	if err := s.healthCheck(r.Context()); err != nil {
 		http.Error(w, "Health check failed: "+err.Error(), http.StatusInternalServerError)
 		return
 	}
diff --git a/tests.go b/tests.go
index 3db7e63..840a5e7 100644
--- a/tests.go
+++ b/tests.go
@@ -37,7 +37,7 @@
 }
 
 func (s *server) runTests() {
-	if err := s.healthCheck(); err != nil {
+	if err := s.healthCheck(context.Background()); err != nil {
 		stdlog.Fatal(err)
 	}