dashboard: report the running build to admins !119
2 files changed, +62 −0
Layout: unified · split
e2e/dashboardbuild_test.go added +48
| @@ -0,0 +1,48 @@ | ||
| 1 | package e2e | |
| 2 | ||
| 3 | import ( | |
| 4 | "strings" | |
| 5 | "testing" | |
| 6 | ) | |
| 7 | ||
| 8 | // The dashboard reports which build is serving, so the running commit is | |
| 9 | // visible without reading the journal. It is admin-only: the exact build a | |
| 10 | // host runs narrows down which known issues apply to it. | |
| 11 | func TestDashboardReportsTheServerBuild(t *testing.T) { | |
| 12 | inst := startInstance(t) | |
| 13 | ||
| 14 | adminKey := inst.newKey(t, "root") | |
| 15 | userKey := inst.newKey(t, "plain") | |
| 16 | inst.admin(t, "admin", "user", "create", "root", "--key", adminKey+".pub", "--admin") | |
| 17 | inst.admin(t, "admin", "user", "create", "plain", "--key", userKey+".pub") | |
| 18 | ||
| 19 | out, errOut, code := inst.ssh(t, adminKey, "", "dashboard", "--json") | |
| 20 | if code != 0 { | |
| 21 | t.Fatalf("admin dashboard: %s", errOut) | |
| 22 | } | |
| 23 | if !strings.Contains(out, `"server":{"commit":"`) { | |
| 24 | t.Fatalf("admin dashboard did not report the build:\n%s", out) | |
| 25 | } | |
| 26 | ||
| 27 | // A non-admin gets the same dashboard without it. omitempty drops the key | |
| 28 | // entirely rather than reporting an empty string. | |
| 29 | out, errOut, code = inst.ssh(t, userKey, "", "dashboard", "--json") | |
| 30 | if code != 0 { | |
| 31 | t.Fatalf("user dashboard: %s", errOut) | |
| 32 | } | |
| 33 | if strings.Contains(out, `"server"`) { | |
| 34 | t.Fatalf("a non-admin was told the server build:\n%s", out) | |
| 35 | } | |
| 36 | if !strings.Contains(out, `"review_queue"`) { | |
| 37 | t.Fatalf("user dashboard is missing its usual contents:\n%s", out) | |
| 38 | } | |
| 39 | ||
| 40 | // Human output carries it too, for the operator who did not ask for JSON. | |
| 41 | out, errOut, code = inst.ssh(t, adminKey, "", "dashboard") | |
| 42 | if code != 0 { | |
| 43 | t.Fatalf("admin dashboard (human): %s", errOut) | |
| 44 | } | |
| 45 | if !strings.Contains(out, "server:") || !strings.Contains(out, "build ") { | |
| 46 | t.Fatalf("human dashboard did not report the build:\n%s", out) | |
| 47 | } | |
| 48 | } | |
internal/control/dashboard.go +14
| @@ -6,6 +6,7 @@ import ( | ||
| 6 | 6 | "io" |
| 7 | 7 | "strconv" |
| 8 | 8 | |
| 9 | "gitbay.org/gitbay/internal/buildinfo" | |
| 9 | 10 | "gitbay.org/gitbay/internal/gitutil" |
| 10 | 11 | "gitbay.org/gitbay/internal/policy" |
| 11 | 12 | "gitbay.org/gitbay/internal/protocol" |
| @@ -52,6 +53,12 @@ func runDashboard(c *Ctx, args []string) int { | ||
| 52 | 53 | CreatedAt string `json:"created_at"` |
| 53 | 54 | FinishedAt string `json:"finished_at,omitempty"` |
| 54 | 55 | } |
| 56 | // serverOut is admin-only. The exact build a host is running narrows down | |
| 57 | // which known issues apply to it, so it is not everyone's to read; the | |
| 58 | // person who needs it is the operator. | |
| 59 | type serverOut struct { | |
| 60 | Commit string `json:"commit"` | |
| 61 | } | |
| 55 | 62 | type out struct { |
| 56 | 63 | Reviews []dashboardItem `json:"review_queue"` |
| 57 | 64 | Assigned []dashboardItem `json:"assigned_issues"` |
| @@ -60,6 +67,7 @@ func runDashboard(c *Ctx, args []string) int { | ||
| 60 | 67 | Pinned []pinnedOut `json:"pinned"` |
| 61 | 68 | Activity []feedOut `json:"recent_activity"` |
| 62 | 69 | Builds []buildOut `json:"builds"` |
| 70 | Server *serverOut `json:"server,omitempty"` | |
| 63 | 71 | } |
| 64 | 72 | d := out{ |
| 65 | 73 | Reviews: []dashboardItem{}, Assigned: []dashboardItem{}, MRs: []dashboardItem{}, |
| @@ -127,6 +135,9 @@ func runDashboard(c *Ctx, args []string) int { | ||
| 127 | 135 | for _, b := range builds { |
| 128 | 136 | d.Builds = append(d.Builds, buildOut{b.RepoPath, b.Number, b.Job, b.Status, b.SHA, b.Ref, b.CreatedAt, b.FinishedAt}) |
| 129 | 137 | } |
| 138 | if c.User.IsAdmin { | |
| 139 | d.Server = &serverOut{Commit: buildinfo.String()} | |
| 140 | } | |
| 130 | 141 | |
| 131 | 142 | return c.emit(d, func(w io.Writer) { |
| 132 | 143 | fmt.Fprintln(w, "waiting on your review:") |
| @@ -153,6 +164,9 @@ func runDashboard(c *Ctx, args []string) int { | ||
| 153 | 164 | for _, b := range d.Builds { |
| 154 | 165 | fmt.Fprintf(w, " %s\t%d\t%s\t%s\t%.10s\t%s\n", b.Repo, b.Number, b.Job, b.Status, b.SHA, b.Ref) |
| 155 | 166 | } |
| 167 | if d.Server != nil { | |
| 168 | fmt.Fprintf(w, "server:\n build %s\n", d.Server.Commit) | |
| 169 | } | |
| 156 | 170 | }) |
| 157 | 171 | } |
| 158 | 172 | |