From d5491ebc6b1c4196ff28a5b361ebdaa7c967e7bf Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 5 Jan 2015 03:02:59 +0000 Subject: [PATCH] dashboard/app: add a JSON output mode for the data on the front page Fixes golang/go#9493 Change-Id: I4891abf530901c620c2923e9f2d3e3227dd7ced9 Reviewed-on: https://go-review.googlesource.com/2290 Reviewed-by: Andrew Gerrand --- README | 40 +++++++++++++----------------- app/build/ui.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++- types/types.go | 40 ++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 24 deletions(-) create mode 100644 types/types.go diff --git a/README b/README index 59b1504c..d9f62bef 100644 --- a/README +++ b/README @@ -2,35 +2,29 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -The files in this directory constitute the continuous builder: +The files in these directories constitute the continuous builder: -app/: an AppEngine server. The code that runs http://build.golang.org/ +app/: a.k.a the "dashboard"; the App Engine code that runs http://build.golang.org/ buildlet/: HTTP server that runs on a VM and is told what to write to disk - and what command to run. This is cross-compiled to all architectures + and what command to run. This is cross-compiled to different architectures and is the first program run when a builder VM comes up. It then - is contacted by the coordinator to do a build. -builder/: gobuilder, a Go continuous build client + is contacted by the coordinator to do a build. Not all builders use + the buildlet (at least not yet). +builder/: gobuilder, a Go continuous build client. The original Go builder program. coordinator/: daemon that runs on CoreOS on Google Compute Engine and manages - builds (using the builder in single-shot mode) in Docker containers. -env/: configuration files describing the environment of builders and related binaries. - Many builders are still configured ad-hoc. + builds using Docker containers and/or VMs as needed. +env/: configuration files describing the environment of builders and related + binaries. Many builders are still configured ad-hoc, without a hermetic + environment. +retrybuilds/: a Go client program to delete build results from the dashboard (app) +types/: a Go package contain common types used by other pieces. watcher/: a daemon that watches for new commits to the Go repository and its sub-repositories, and notifies the dashboard of those commits. -If you wish to run a Go builder, please email golang-dev@googlegroups.com +If you wish to run a Go builder, please email golang-dev@googlegroups.com first. +There is documentation at https://golang.org/wiki/DashboardBuilders but +depending on the type of builder, we may want to run it ourselves, after you +prepare an environment description (resulting in a VM image) of it. See the env +directory. -To run a builder: - -* Write the key ~gobuild/.gobuildkey - You need to get it from someone who knows the key. - You may also use a filename of the form .gobuildkey-$BUILDER if you - wish to run builders for multiple targets. - -* Append your username and password googlecode.com credentials from - https://code.google.com/hosting/settings - to the buildkey file in the format "Username\nPassword\n". - (This is for uploading tarballs to the project downloads section, - and is an optional step.) - -* Build and run gobuilder (see its documentation for command-line options). diff --git a/app/build/ui.go b/app/build/ui.go index 6e90de80..e62380ff 100644 --- a/app/build/ui.go +++ b/app/build/ui.go @@ -11,6 +11,7 @@ package build import ( "bytes" + "encoding/json" "errors" "fmt" "html/template" @@ -20,6 +21,8 @@ import ( "strconv" "strings" + "golang.org/x/tools/dashboard/types" + "cache" "appengine" @@ -95,9 +98,13 @@ func uiHandler(w http.ResponseWriter, r *http.Request) { } data := &uiTemplateData{d, pkg, commits, builders, tipState, p, branch} - if r.FormValue("mode") == "failures" { + switch r.FormValue("mode") { + case "failures": failuresHandler(w, r, data) return + case "json": + jsonHandler(w, r, data) + return } var buf bytes.Buffer @@ -129,6 +136,62 @@ func failuresHandler(w http.ResponseWriter, r *http.Request, data *uiTemplateDat } } +// jsonHandler is https://build.golang.org/?mode=json +// The output is a types.BuildStatus JSON object. +func jsonHandler(w http.ResponseWriter, r *http.Request, data *uiTemplateData) { + d := dashboardForRequest(r) + + // cell returns one of "" (no data), "ok", or a failure URL. + cell := func(res *Result) string { + switch { + case res == nil: + return "" + case res.OK: + return "ok" + } + return fmt.Sprintf("https://%v%v/log/%v", r.Host, d.Prefix, res.LogHash) + } + + var res types.BuildStatus + res.Builders = data.Builders + + // First the commits from the main section (the "go" repo) + for _, c := range data.Commits { + rev := types.BuildRevision{ + Repo: "go", + Revision: c.Hash, + Results: make([]string, len(data.Builders)), + } + for i, b := range data.Builders { + rev.Results[i] = cell(c.Result(b, "")) + } + res.Revisions = append(res.Revisions, rev) + } + + // Then the one commit each for the subrepos. + // TODO(bradfitz): we'll probably want more than one later, for people looking at + // the subrepo-specific build history pages. But for now this gets me some data + // to make forward progress. + tip := data.TipState // a TagState + for _, pkgState := range tip.Packages { + goRev := tip.Tag.Hash + rev := types.BuildRevision{ + Repo: pkgState.Package.Name, + Revision: pkgState.Commit.Hash, + GoRevision: goRev, + Results: make([]string, len(data.Builders)), + } + for i, b := range res.Builders { + rev.Results[i] = cell(pkgState.Commit.Result(b, goRev)) + } + res.Revisions = append(res.Revisions, rev) + } + + v, _ := json.MarshalIndent(res, "", "\t") + w.Header().Set("Content-Type", "text/json; charset=utf-8") + w.Write(v) +} + type Pagination struct { Next, Prev int HasPrev bool diff --git a/types/types.go b/types/types.go new file mode 100644 index 00000000..b8dfa48c --- /dev/null +++ b/types/types.go @@ -0,0 +1,40 @@ +// Copyright 2011 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 types contains common types used by the Go continuous build +// system. +package types + +// BuildStatus is the data structure that's marshalled as JSON +// for the http://build.golang.org/?mode=json page. +type BuildStatus struct { + // Builders is a list of all known builders. + // The order that builders appear is the same order as the build results for a revision. + Builders []string `json:"builders"` + + // Revisions are the revisions shown on the front page of build.golang.org, + // in the same order. It starts with the "go" repo, from recent to old, and then + // it has 1 each of the subrepos, with only their most recent commit. + Revisions []BuildRevision `json:"revisions"` +} + +// BuildRevision is the status of a commit across all builders. +// It corresponds to a single row of http://build.golang.org/ +type BuildRevision struct { + // Repo is "go" for the main repo, else "tools", "crypto", "net", etc. + // These are repos as listed at https://go.googlesource.com/ + Repo string `json:"repo"` + + // Revision is the full git hash of the repo. + Revision string `json:"revision"` + + // GoRevision is the full git hash of the "go" repo, if Repo is not "go" itself. + // Otherwise this is empty. + GoRevision string `json:"goRevision,omitempty"` + + // Results are the build results for each of the builders in + // the same length slice BuildStatus.Builders. + // Each string is either "" (if no data), "ok", or the URL to failure logs. + Results []string `json:"results"` +}