зеркало из https://github.com/golang/build.git
cmd/coordinator: style the "trybot status" page
Load style.css so we share some styles with the Go Build Coordinator homepage. Add some custom styles so text in tables is a little bigger - there's less of it on the trybot page. Instead of formatting to the nearest tenth of a minute, we can round to the nearest second - Duration.Round() is now two Go versions old - and use more natural duration formatting. Instead of issuing many small writes to the ResponseWriter, write HTML to a buffer and then write it to the ResponseWriter all at once. (We should just use a template but that's a bigger project.) Add a "/try-dev" handler you can enable with the `-dev` build tag which makes it easy to view and test the "trybot status" page locally, without requiring a builder. Change-Id: I28617d02ed857c28d2bb2d9ccfb05ca9dc572212 Reviewed-on: https://go-review.googlesource.com/103870 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Родитель
5298ba98fb
Коммит
d742befa4d
|
@ -4,9 +4,19 @@
|
|||
|
||||
Run
|
||||
|
||||
go install golang.org/x/build/cmd/coordinator && coordinator --mode=dev
|
||||
go install golang.org/x/build/cmd/coordinator && coordinator --mode=dev --env=dev
|
||||
|
||||
to start a server on https://localhost:8119. Proceed past the TLS warning and
|
||||
you should get the homepage. Some features won't work when running locally,
|
||||
but you should be able to view the homepage and the builders page and do basic
|
||||
sanity checks.
|
||||
|
||||
#### Render the "Trybot Status" page locally
|
||||
|
||||
To view/modify the "Trybot Status" page locally, you can build the coordinator
|
||||
with the `-dev` tag.
|
||||
|
||||
go install -tags=dev golang.org/x/build/cmd/coordinator
|
||||
|
||||
Then start the coordinator and visit https://localhost:8119/try-dev in your
|
||||
browser. You should see a trybot status page with some example data.
|
||||
|
|
|
@ -622,21 +622,38 @@ func serveTryStatusJSON(w http.ResponseWriter, r *http.Request, ts *trySet, tss
|
|||
w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
// Styles unique to the trybot status page.
|
||||
const tryStatusCSS = `
|
||||
<style>
|
||||
p {
|
||||
line-height: 1.15em;
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: 11pt;
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
// tss is a clone that does not require ts' lock.
|
||||
func serveTryStatusHTML(w http.ResponseWriter, ts *trySet, tss trySetState) {
|
||||
if ts == nil {
|
||||
http.Error(w, "TryBot result not found (already done, invalid, or not yet discovered from Gerrit). Check Gerrit for results.", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
fmt.Fprintf(w, "<!DOCTYPE html><title>trybot status</title>")
|
||||
fmt.Fprintf(w, "[<a href='/'>overall status</a>] > %s\n", ts.ChangeID)
|
||||
fmt.Fprintf(w, "<h1>trybot status</h1>")
|
||||
fmt.Fprintf(w, "Change-ID: <a href='https://go-review.googlesource.com/#/q/%s'>%s</a><br>\n", ts.ChangeID, ts.ChangeID)
|
||||
fmt.Fprintf(w, "Commit: <a href='https://go-review.googlesource.com/#/q/%s'>%s</a><br>\n", ts.Commit, ts.Commit)
|
||||
fmt.Fprintf(w, "<p>Builds remain: %d</p>\n", tss.remain)
|
||||
fmt.Fprintf(w, "<p>Builds</p>\n")
|
||||
fmt.Fprintf(w, "<table cellpadding=5 border=0>\n")
|
||||
buf.WriteString("<!DOCTYPE html><head><title>trybot status</title>")
|
||||
buf.WriteString(`<link rel="stylesheet" href="/style.css"/>`)
|
||||
buf.WriteString(tryStatusCSS)
|
||||
buf.WriteString("</head><body>")
|
||||
fmt.Fprintf(buf, "[<a href='/'>homepage</a>] > %s\n", ts.ChangeID)
|
||||
fmt.Fprintf(buf, "<h1>Trybot Status</h1>")
|
||||
fmt.Fprintf(buf, "<p>Change-ID: <a href='https://go-review.googlesource.com/#/q/%s'>%s</a><br />\n", ts.ChangeID, ts.ChangeID)
|
||||
fmt.Fprintf(buf, "Commit: <a href='https://go-review.googlesource.com/#/q/%s'>%s</a></p>\n", ts.Commit, ts.Commit)
|
||||
fmt.Fprintf(buf, "<p>Builds remaining: %d</p>\n", tss.remain)
|
||||
fmt.Fprintf(buf, "<h4>Builds</h4>\n")
|
||||
fmt.Fprintf(buf, "<table cellpadding=5 border=0>\n")
|
||||
for _, bs := range tss.builds {
|
||||
var status string
|
||||
bs.mu.Lock()
|
||||
|
@ -647,13 +664,13 @@ func serveTryStatusHTML(w http.ResponseWriter, ts *trySet, tss trySetState) {
|
|||
status = "<b>FAIL</b>"
|
||||
}
|
||||
} else {
|
||||
status = fmt.Sprintf("<i>running</i> %.1f min", time.Since(bs.startTime).Minutes())
|
||||
status = fmt.Sprintf("<i>running</i> %s", time.Since(bs.startTime).Round(time.Second))
|
||||
}
|
||||
bs.mu.Unlock()
|
||||
fmt.Fprintf(w, "<tr><td>%s</td><td>%s</td></tr>\n", bs.Name, status)
|
||||
fmt.Fprintf(buf, "<tr><td>• %s</td><td>%s</td></tr>\n", bs.Name, status)
|
||||
}
|
||||
fmt.Fprintf(w, "</table>\n")
|
||||
fmt.Fprintf(w, "<p>Full Detail</p><table cellpadding=5 border=1>\n")
|
||||
fmt.Fprintf(buf, "</table>\n")
|
||||
fmt.Fprintf(buf, "<h4>Full Detail</h4><table cellpadding=5 border=1>\n")
|
||||
for _, bs := range tss.builds {
|
||||
status := "<i>(running)</i>"
|
||||
bs.mu.Lock()
|
||||
|
@ -665,12 +682,13 @@ func serveTryStatusHTML(w http.ResponseWriter, ts *trySet, tss trySetState) {
|
|||
}
|
||||
}
|
||||
bs.mu.Unlock()
|
||||
fmt.Fprintf(w, "<tr valign=top><td align=left>%s</td><td align=center>%s</td><td><pre>%s</pre></td></tr>\n",
|
||||
fmt.Fprintf(buf, "<tr valign=top><td align=left>%s</td><td align=center>%s</td><td><pre>%s</pre></td></tr>\n",
|
||||
bs.Name,
|
||||
status,
|
||||
bs.HTMLStatusLine())
|
||||
}
|
||||
fmt.Fprintf(w, "</table>")
|
||||
fmt.Fprintf(buf, "</table>")
|
||||
w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
func trySetOfCommitPrefix(commitPrefix string) *trySet {
|
||||
|
@ -3390,7 +3408,7 @@ func (st *buildStatus) htmlStatusLine(full bool) template.HTML {
|
|||
if t.IsZero() {
|
||||
t = st.startTime
|
||||
}
|
||||
fmt.Fprintf(&buf, ", %v ago", time.Since(t))
|
||||
fmt.Fprintf(&buf, ", %v ago", time.Since(t).Round(time.Second))
|
||||
if full {
|
||||
buf.WriteByte('\n')
|
||||
st.writeEventsLocked(&buf, true)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// This file is designed to make it easier to do local development of the styles
|
||||
// for the trybot status page, by creating a set of builders with dummy data.
|
||||
// Compile it into the binary by running go install -tags=dev, then load the
|
||||
// dummy data at /try-dev in your browser.
|
||||
|
||||
// +build dev
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/build/buildlet"
|
||||
"golang.org/x/build/internal/buildgo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ts := &trySet{
|
||||
tryKey: tryKey{
|
||||
Project: "go",
|
||||
Branch: "master",
|
||||
ChangeID: "I1936e2dbe90634817f1aedabcba3c2b9f94e401b",
|
||||
Commit: "555cfa3ee5e9f3df4b10c96af487424bfde19125",
|
||||
},
|
||||
tryID: "T4bfde19125",
|
||||
trySetState: trySetState{
|
||||
failed: []string{"failed-build"},
|
||||
remain: 1,
|
||||
builds: []*buildStatus{
|
||||
&buildStatus{
|
||||
BuilderRev: buildgo.BuilderRev{
|
||||
Name: "linux-amd64-race",
|
||||
Rev: "555cfa3ee5e9f3df4b10c96af487424bfde19125",
|
||||
},
|
||||
startTime: time.Now(),
|
||||
bc: &buildlet.Client{},
|
||||
},
|
||||
&buildStatus{
|
||||
BuilderRev: buildgo.BuilderRev{
|
||||
Name: "darwin-amd64-race",
|
||||
Rev: "555cfa3ee5e9f3df4b10c96af487424bfde19125",
|
||||
},
|
||||
startTime: time.Now(),
|
||||
done: time.Now().Add(3 * time.Minute),
|
||||
bc: &buildlet.Client{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
http.HandleFunc("/try-dev", func(w http.ResponseWriter, r *http.Request) {
|
||||
tss := ts.trySetState.clone()
|
||||
serveTryStatusHTML(w, ts, tss)
|
||||
})
|
||||
}
|
Загрузка…
Ссылка в новой задаче