| // Copyright 2015 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package dashboard contains shared configuration and logic used by various |
| // pieces of the Go continuous build system. |
| package dashboard |
| |
| import ( |
| "errors" |
| "io/ioutil" |
| "os" |
| "strings" |
| ) |
| |
| // Builders are the different build configurations. |
| // The keys are like "darwin-amd64" or "linux-386-387". |
| // This map should not be modified by other packages. |
| var Builders = map[string]BuildConfig{} |
| |
| // A BuildConfig describes how to run either a Docker-based or VM-based builder. |
| type BuildConfig struct { |
| // Name is the unique name of the builder, in the form of |
| // "darwin-386" or "linux-amd64-race". |
| Name string |
| |
| // VM-specific settings: |
| VMImage string // e.g. "openbsd-amd64-56" |
| machineType string // optional GCE instance type |
| |
| // Docker-specific settings: (used if VMImage == "") |
| Image string // Docker image to use to build |
| cmd string // optional -cmd flag (relative to go/src/) |
| env []string // extra environment ("key=value") pairs |
| dashURL string // url of the build dashboard |
| tool string // the tool this configuration is for |
| } |
| |
| func (c *BuildConfig) GOOS() string { return c.Name[:strings.Index(c.Name, "-")] } |
| |
| func (c *BuildConfig) GOARCH() string { |
| arch := c.Name[strings.Index(c.Name, "-")+1:] |
| i := strings.Index(arch, "-") |
| if i == -1 { |
| return arch |
| } |
| return arch[:i] |
| } |
| |
| // AllScript returns the relative path to the operating system's script to |
| // do the build and run its standard set of tests. |
| // Example values are "src/all.bash", "src/all.bat", "src/all.rc". |
| func (c *BuildConfig) AllScript() string { |
| if strings.HasPrefix(c.Name, "windows-") { |
| return "src/all.bat" |
| } |
| if strings.HasPrefix(c.Name, "plan9-") { |
| return "src/all.rc" |
| } |
| // TODO(bradfitz): race.bash, etc, once the race builder runs |
| // via the buildlet. |
| return "src/all.bash" |
| } |
| |
| func (c *BuildConfig) UsesDocker() bool { return c.VMImage == "" } |
| func (c *BuildConfig) UsesVM() bool { return c.VMImage != "" } |
| |
| // MachineType returns the GCE machine type to use for this builder. |
| func (c *BuildConfig) MachineType() string { |
| if v := c.machineType; v != "" { |
| return v |
| } |
| return "n1-highcpu-2" |
| } |
| |
| // DockerRunArgs returns the arguments that go after "docker run" to execute |
| // this docker image. The rev (git hash) is required. The builderKey is optional. |
| // TODO(bradfitz): remove the builderKey being passed down, once the coordinator |
| // does the reporting to the dashboard for docker builds too. |
| func (conf BuildConfig) DockerRunArgs(rev, builderKey string) ([]string, error) { |
| if !conf.UsesDocker() { |
| return nil, errors.New("not a docker-based build") |
| } |
| var args []string |
| if builderKey != "" { |
| tmpKey := "/tmp/" + conf.Name + ".buildkey" |
| if _, err := os.Stat(tmpKey); err != nil { |
| if err := ioutil.WriteFile(tmpKey, []byte(builderKey), 0600); err != nil { |
| return nil, err |
| } |
| } |
| // Images may look for .gobuildkey in / or /root, so provide both. |
| // TODO(adg): fix images that look in the wrong place. |
| args = append(args, "-v", tmpKey+":/.gobuildkey") |
| args = append(args, "-v", tmpKey+":/root/.gobuildkey") |
| } |
| for _, pair := range conf.env { |
| args = append(args, "-e", pair) |
| } |
| if strings.HasPrefix(conf.Name, "linux-amd64") { |
| args = append(args, "-e", "GOROOT_BOOTSTRAP=/go1.4-amd64/go") |
| } else if strings.HasPrefix(conf.Name, "linux-386") { |
| args = append(args, "-e", "GOROOT_BOOTSTRAP=/go1.4-386/go") |
| } |
| args = append(args, |
| conf.Image, |
| "/usr/local/bin/builder", |
| "-rev="+rev, |
| "-dashboard="+conf.dashURL, |
| "-tool="+conf.tool, |
| "-buildroot=/", |
| "-v", |
| ) |
| if conf.cmd != "" { |
| args = append(args, "-cmd", conf.cmd) |
| } |
| args = append(args, conf.Name) |
| return args, nil |
| } |
| |
| func init() { |
| addBuilder(BuildConfig{Name: "linux-386"}) |
| addBuilder(BuildConfig{Name: "linux-386-387", env: []string{"GO386=387"}}) |
| addBuilder(BuildConfig{Name: "linux-amd64"}) |
| addBuilder(BuildConfig{Name: "linux-amd64-nocgo", env: []string{"CGO_ENABLED=0", "USER=root"}}) |
| addBuilder(BuildConfig{Name: "linux-amd64-noopt", env: []string{"GO_GCFLAGS=-N -l"}}) |
| addBuilder(BuildConfig{Name: "linux-amd64-race"}) |
| addBuilder(BuildConfig{Name: "nacl-386"}) |
| addBuilder(BuildConfig{Name: "nacl-amd64p32"}) |
| addBuilder(BuildConfig{ |
| Name: "linux-amd64-gccgo", |
| Image: "gobuilders/linux-x86-gccgo", |
| cmd: "make RUNTESTFLAGS=\"--target_board=unix/-m64\" check-go -j16", |
| dashURL: "https://build.golang.org/gccgo", |
| tool: "gccgo", |
| }) |
| addBuilder(BuildConfig{ |
| Name: "linux-386-gccgo", |
| Image: "gobuilders/linux-x86-gccgo", |
| cmd: "make RUNTESTFLAGS=\"--target_board=unix/-m32\" check-go -j16", |
| dashURL: "https://build.golang.org/gccgo", |
| tool: "gccgo", |
| }) |
| addBuilder(BuildConfig{Name: "linux-386-sid", Image: "gobuilders/linux-x86-sid"}) |
| addBuilder(BuildConfig{Name: "linux-amd64-sid", Image: "gobuilders/linux-x86-sid"}) |
| addBuilder(BuildConfig{Name: "linux-386-clang", Image: "gobuilders/linux-x86-clang"}) |
| addBuilder(BuildConfig{Name: "linux-amd64-clang", Image: "gobuilders/linux-x86-clang"}) |
| |
| // VMs: |
| addBuilder(BuildConfig{ |
| Name: "openbsd-amd64-gce56", |
| VMImage: "openbsd-amd64-56", |
| machineType: "n1-highcpu-2", |
| }) |
| addBuilder(BuildConfig{ |
| // It's named "partial" because the buildlet sets |
| // GOTESTONLY=std to stop after the "go test std" |
| // tests because it's so slow otherwise. |
| // TODO(braditz): move that env variable to the |
| // coordinator and into this config. |
| Name: "plan9-386-gcepartial", |
| VMImage: "plan9-386", |
| // We *were* using n1-standard-1 because Plan 9 can only |
| // reliably use a single CPU. Using 2 or 4 and we see |
| // test failures. See: |
| // https://golang.org/issue/8393 |
| // https://golang.org/issue/9491 |
| // n1-standard-1 has 3.6 GB of memory which is |
| // overkill (userspace probably only sees 2GB anyway), |
| // but it's the cheapest option. And plenty to keep |
| // our ~250 MB of inputs+outputs in its ramfs. |
| // |
| // But the docs says "For the n1 series of machine |
| // types, a virtual CPU is implemented as a single |
| // hyperthread on a 2.6GHz Intel Sandy Bridge Xeon or |
| // Intel Ivy Bridge Xeon (or newer) processor. This |
| // means that the n1-standard-2 machine type will see |
| // a whole physical core." |
| // |
| // ... so we use n1-highcpu-2 (1.80 RAM, still |
| // plenty), just so we can get 1 whole core for the |
| // single-core Plan 9. It will see 2 virtual cores and |
| // only use 1, but we hope that 1 will be more powerful |
| // and we'll stop timing out on tests. |
| machineType: "n1-highcpu-2", |
| }) |
| |
| } |
| |
| func addBuilder(c BuildConfig) { |
| if c.tool == "gccgo" { |
| // TODO(cmang,bradfitz,adg): fix gccgo |
| return |
| } |
| if c.Name == "" { |
| panic("empty name") |
| } |
| if _, dup := Builders[c.Name]; dup { |
| panic("dup name") |
| } |
| if c.dashURL == "" { |
| c.dashURL = "https://build.golang.org" |
| } |
| if c.tool == "" { |
| c.tool = "go" |
| } |
| |
| if strings.HasPrefix(c.Name, "nacl-") { |
| if c.Image == "" { |
| c.Image = "gobuilders/linux-x86-nacl" |
| } |
| if c.cmd == "" { |
| c.cmd = "/usr/local/bin/build-command.pl" |
| } |
| } |
| if strings.HasPrefix(c.Name, "linux-") && c.Image == "" { |
| c.Image = "gobuilders/linux-x86-base" |
| } |
| if c.Image == "" && c.VMImage == "" { |
| panic("empty image and vmImage") |
| } |
| if c.Image != "" && c.VMImage != "" { |
| panic("can't specify both image and vmImage") |
| } |
| Builders[c.Name] = c |
| } |