Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: appengine/cmd/milo/swarming/build.go

Issue 2155313002: milo: add builder title to swarming build page (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: nits Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | appengine/cmd/milo/swarming/expectations/build-canceled.json » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package swarming 5 package swarming
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "encoding/json" 9 "encoding/json"
10 "fmt" 10 "fmt"
11 "io/ioutil" 11 "io/ioutil"
12 "path/filepath" 12 "path/filepath"
13 "strings" 13 "strings"
14 "sync" 14 "sync"
15 "time" 15 "time"
16 16
17 "golang.org/x/net/context" 17 "golang.org/x/net/context"
18 18
19 "github.com/luci/luci-go/appengine/cmd/milo/logdog" 19 "github.com/luci/luci-go/appengine/cmd/milo/logdog"
20 "github.com/luci/luci-go/appengine/cmd/milo/resp" 20 "github.com/luci/luci-go/appengine/cmd/milo/resp"
21 "github.com/luci/luci-go/appengine/gaeauth/client" 21 "github.com/luci/luci-go/appengine/gaeauth/client"
22 "github.com/luci/luci-go/client/logdog/annotee" 22 "github.com/luci/luci-go/client/logdog/annotee"
23 swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1" 23 swarming "github.com/luci/luci-go/common/api/swarming/swarming/v1"
24 "github.com/luci/luci-go/common/clock" 24 "github.com/luci/luci-go/common/clock"
25 "github.com/luci/luci-go/common/logdog/types" 25 "github.com/luci/luci-go/common/logdog/types"
26 "github.com/luci/luci-go/common/logging"
26 "github.com/luci/luci-go/common/transport" 27 "github.com/luci/luci-go/common/transport"
27 ) 28 )
28 29
29 // SwarmingTimeLayout is time layout used by swarming. 30 // SwarmingTimeLayout is time layout used by swarming.
30 const SwarmingTimeLayout = "2006-01-02T15:04:05.999999999" 31 const SwarmingTimeLayout = "2006-01-02T15:04:05.999999999"
31 32
32 // Swarming task states.. 33 // Swarming task states..
33 const ( 34 const (
34 // TaskRunning means task is running. 35 // TaskRunning means task is running.
35 TaskRunning = "RUNNING" 36 TaskRunning = "RUNNING"
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 Key: parts[0], 176 Key: parts[0],
176 } 177 }
177 if len(parts) == 2 { 178 if len(parts) == 2 {
178 p.Value = parts[1] 179 p.Value = parts[1]
179 } 180 }
180 props.Property = append(props.Property, p) 181 props.Property = append(props.Property, p)
181 } 182 }
182 return props 183 return props
183 } 184 }
184 185
186 // tagValue returns a value of the first tag matching the tag key. If not found
187 // returns "".
188 func tagValue(tags []string, key string) string {
189 prefix := key + ":"
190 for _, t := range tags {
191 if strings.HasPrefix(t, prefix) {
192 return strings.TrimPrefix(t, prefix)
193 }
194 }
195 return ""
196 }
197
198 // addBuilderLink adds a link to the buildbucket builder view.
199 func addBuilderLink(c context.Context, build *resp.MiloBuild, swarmingHostname s tring, sr *swarming.SwarmingRpcsTaskResult) {
200 bbHost := tagValue(sr.Tags, "buildbucket_hostname")
201 bucket := tagValue(sr.Tags, "buildbucket_bucket")
202 builder := tagValue(sr.Tags, "builder")
203 if bucket == "" {
204 logging.Errorf(
205 c, "Could not extract buidlbucket bucket from task %s",
206 taskPageURL(swarmingHostname, sr.TaskId))
207 }
208 if builder == "" {
209 logging.Errorf(
210 c, "Could not extract builder name from task %s",
211 taskPageURL(swarmingHostname, sr.TaskId))
212 }
213 if bucket != "" && builder != "" {
214 build.Summary.ParentLabel = &resp.Link{
215 Label: builder,
216 URL: fmt.Sprintf("/buildbucket/%s/%s?server=%s", bucke t, builder, bbHost),
217 }
218 }
219 }
220
221 // addBanner adds an OS banner derived from "os" swarming tag, if present.
222 func addBanner(build *resp.MiloBuild, sr *swarming.SwarmingRpcsTaskResult) {
223 var os, ver string
224 for _, t := range sr.Tags {
225 value := strings.TrimPrefix(t, "os:")
226 if value == t {
227 // t does not have the prefix
228 continue
229 }
230 parts := strings.SplitN(value, "-", 2)
231 if len(parts) == 2 {
232 os = parts[0]
233 ver = parts[1]
234 break
235 }
236 }
237
238 var base resp.LogoBase
239 switch os {
240 case "Ubuntu":
241 base = resp.Ubuntu
242 case "Windows":
243 base = resp.Windows
244 case "Mac":
245 base = resp.OSX
246 case "Android":
247 base = resp.Android
248 default:
249 return
250 }
251
252 build.Summary.Banner = &resp.LogoBanner{
253 OS: []resp.Logo{{
254 LogoBase: base,
255 Subtitle: ver,
256 Count: 1,
257 }},
258 }
259 }
260
185 func taskToBuild(c context.Context, server string, sr *swarming.SwarmingRpcsTask Result) (*resp.MiloBuild, error) { 261 func taskToBuild(c context.Context, server string, sr *swarming.SwarmingRpcsTask Result) (*resp.MiloBuild, error) {
186 build := &resp.MiloBuild{ 262 build := &resp.MiloBuild{
187 Summary: resp.BuildComponent{ 263 Summary: resp.BuildComponent{
264 Label: sr.TaskId,
188 Source: &resp.Link{ 265 Source: &resp.Link{
189 Label: "Task " + sr.TaskId, 266 Label: "Task " + sr.TaskId,
190 URL: taskPageURL(server, sr.TaskId), 267 URL: taskPageURL(server, sr.TaskId),
191 }, 268 },
192 }, 269 },
193 } 270 }
194 271
195 switch sr.State { 272 switch sr.State {
196 case TaskRunning: 273 case TaskRunning:
197 build.Summary.Status = resp.Running 274 build.Summary.Status = resp.Running
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 } 308 }
232 309
233 // Extract more swarming specific information into the properties. 310 // Extract more swarming specific information into the properties.
234 if props := taskProperties(sr); len(props.Property) > 0 { 311 if props := taskProperties(sr); len(props.Property) > 0 {
235 build.PropertyGroup = append(build.PropertyGroup, props) 312 build.PropertyGroup = append(build.PropertyGroup, props)
236 } 313 }
237 if props := tagsToProperties(sr.Tags); len(props.Property) > 0 { 314 if props := tagsToProperties(sr.Tags); len(props.Property) > 0 {
238 build.PropertyGroup = append(build.PropertyGroup, props) 315 build.PropertyGroup = append(build.PropertyGroup, props)
239 } 316 }
240 317
318 addBuilderLink(c, build, server, sr)
319 addBanner(build, sr)
320
321 // Add a link to the bot.
241 if sr.BotId != "" { 322 if sr.BotId != "" {
242 build.Summary.Bot = &resp.Link{ 323 build.Summary.Bot = &resp.Link{
243 Label: sr.BotId, 324 Label: sr.BotId,
244 URL: botPageURL(server, sr.BotId), 325 URL: botPageURL(server, sr.BotId),
245 } 326 }
246 } 327 }
247 328
329 // Compute start and finished times, and duration.
248 var err error 330 var err error
249 if sr.StartedTs != "" { 331 if sr.StartedTs != "" {
250 build.Summary.Started, err = time.Parse(SwarmingTimeLayout, sr.S tartedTs) 332 build.Summary.Started, err = time.Parse(SwarmingTimeLayout, sr.S tartedTs)
251 if err != nil { 333 if err != nil {
252 return nil, fmt.Errorf("invalid task StartedTs: %s", err ) 334 return nil, fmt.Errorf("invalid task StartedTs: %s", err )
253 } 335 }
254 } 336 }
255 if sr.CompletedTs != "" { 337 if sr.CompletedTs != "" {
256 build.Summary.Finished, err = time.Parse(SwarmingTimeLayout, sr. CompletedTs) 338 build.Summary.Finished, err = time.Parse(SwarmingTimeLayout, sr. CompletedTs)
257 if err != nil { 339 if err != nil {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 // Supports server aliases. 428 // Supports server aliases.
347 func taskPageURL(swarmingHostname, taskID string) string { 429 func taskPageURL(swarmingHostname, taskID string) string {
348 return fmt.Sprintf("https://%s/user/task/%s", swarmingHostname, taskID) 430 return fmt.Sprintf("https://%s/user/task/%s", swarmingHostname, taskID)
349 } 431 }
350 432
351 // botPageURL returns a URL to a human-consumable page of a swarming bot. 433 // botPageURL returns a URL to a human-consumable page of a swarming bot.
352 // Supports server aliases. 434 // Supports server aliases.
353 func botPageURL(swarmingHostname, botID string) string { 435 func botPageURL(swarmingHostname, botID string) string {
354 return fmt.Sprintf("https://%s/restricted/bot/%s", swarmingHostname, bot ID) 436 return fmt.Sprintf("https://%s/restricted/bot/%s", swarmingHostname, bot ID)
355 } 437 }
OLDNEW
« no previous file with comments | « no previous file | appengine/cmd/milo/swarming/expectations/build-canceled.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698