cmd/debugnewvm: add support for doing a test build too

Change-Id: Ic67032554ab77f69176b774a8c33523062f21c88
Reviewed-on: https://go-review.googlesource.com/51431
Reviewed-by: Jeff Johnson <jrjohnson@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/debugnewvm/debugnewvm.go b/cmd/debugnewvm/debugnewvm.go
index c522aee..4c8ec11 100644
--- a/cmd/debugnewvm/debugnewvm.go
+++ b/cmd/debugnewvm/debugnewvm.go
@@ -12,22 +12,28 @@
 	"fmt"
 	"log"
 	"net/http"
+	"os"
+	"path"
 	"strings"
 	"time"
 
 	"golang.org/x/build/buildenv"
 	"golang.org/x/build/buildlet"
 	"golang.org/x/build/dashboard"
+	"golang.org/x/build/internal/buildgo"
 	"golang.org/x/oauth2"
 	"golang.org/x/oauth2/google"
 	compute "google.golang.org/api/compute/v1"
 )
 
 var (
-	hostType     = flag.String("host", "host-windows-amd64-2012", "host type to create")
+	hostType     = flag.String("host", "", "host type to create")
 	vmImage      = flag.String("override-image", "", "if non-empty, an alternate GCE VM image to use, overriding the one defined for the given host")
 	serial       = flag.Bool("serial", true, "watch serial")
 	pauseAfterUp = flag.Bool("pause-after-up", false, "pause for a few seconds (enough to SIGSTOP) after WorkDir returns")
+
+	runBuild = flag.String("run-build", "", "optional builder name to run all.bash for")
+	buildRev = flag.String("rev", "master", "if --run-build is specified, the git hash or branch name to build")
 )
 
 var (
@@ -39,6 +45,22 @@
 	buildenv.RegisterFlags()
 	flag.Parse()
 
+	var bconf dashboard.BuildConfig
+	if *runBuild != "" {
+		var ok bool
+		bconf, ok = dashboard.Builders[*runBuild]
+		if !ok {
+			log.Fatalf("unknown builder %q", *runBuild)
+		}
+		if *hostType == "" {
+			*hostType = bconf.HostType
+		}
+	}
+
+	if *hostType == "" {
+		log.Fatalf("missing --host (or --run-build)")
+	}
+
 	hconf, ok := dashboard.Hosts[*hostType]
 	if !ok {
 		log.Fatalf("unknown host type %q", *hostType)
@@ -59,7 +81,7 @@
 
 	name := fmt.Sprintf("debug-temp-%d", time.Now().Unix())
 	log.Printf("Creating %s (with VM image %q)", name, hconf.VMImage)
-	c, err := buildlet.StartNewVM(ts, name, *hostType, buildlet.VMOpts{
+	bc, err := buildlet.StartNewVM(ts, name, *hostType, buildlet.VMOpts{
 		Zone:                env.Zone,
 		ProjectID:           env.ProjectName,
 		DeleteIn:            15 * time.Minute,
@@ -85,17 +107,65 @@
 	if err != nil {
 		log.Fatalf("StartNewVM: %v", err)
 	}
-	dir, err := c.WorkDir()
+	dir, err := bc.WorkDir()
 	log.Printf("WorkDir: %v, %v", dir, err)
+
+	var buildFailed bool
+	if *runBuild != "" {
+		// Push GOROOT_BOOTSTRAP, if needed.
+		if u := bconf.GoBootstrapURL(env); u != "" {
+			log.Printf("Pushing 'go1.4' Go bootstrap dir ...")
+			const bootstrapDir = "go1.4" // might be newer; name is the default
+			if err := bc.PutTarFromURL(u, bootstrapDir); err != nil {
+				bc.Close()
+				log.Fatalf("Putting Go bootstrap: %v", err)
+			}
+		}
+
+		// Push Go code
+		log.Printf("Pushing 'go' dir...")
+		goTarGz := "https://go.googlesource.com/go/+archive/" + *buildRev + ".tar.gz"
+		if err := bc.PutTarFromURL(goTarGz, "go"); err != nil {
+			bc.Close()
+			log.Fatalf("Putting go code: %v", err)
+		}
+
+		// Push a synthetic VERSION file to prevent git usage:
+		if err := bc.PutTar(buildgo.VersionTgz(*buildRev), "go"); err != nil {
+			bc.Close()
+			log.Fatalf("Putting VERSION file: %v", err)
+		}
+
+		allScript := bconf.AllScript()
+		log.Printf("Running %s ...", allScript)
+		remoteErr, err := bc.Exec(path.Join("go", allScript), buildlet.ExecOpts{
+			Output:   os.Stdout,
+			ExtraEnv: bconf.Env(),
+			Debug:    true,
+			Args:     bconf.AllScriptArgs(),
+		})
+		if err != nil {
+			log.Fatalf("error trying to run %s: %v", allScript, err)
+		}
+		if remoteErr != nil {
+			log.Printf("remote failure running %s: %v", allScript, remoteErr)
+			buildFailed = true
+		}
+	}
+
 	if *pauseAfterUp {
 		log.Printf("Shutting down in 5 seconds...")
 		time.Sleep(5 * time.Second)
 	}
-	if err := c.Close(); err != nil {
+	if err := bc.Close(); err != nil {
 		log.Fatalf("Close: %v", err)
 	}
 	log.Printf("done.")
-	time.Sleep(5 * time.Second) // wait for serial logging to catch up
+	time.Sleep(2 * time.Second) // wait for serial logging to catch up
+
+	if buildFailed {
+		os.Exit(1)
+	}
 }
 
 // watchSerial streams the named VM's serial port to log.Printf. It's roughly: