Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "fmt" | 9 "fmt" |
| 10 "net/http" | 10 "net/http" |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 240 } |
| 241 if sr.State == TaskCompleted || sr.State == TaskTimedOut { | 241 if sr.State == TaskCompleted || sr.State == TaskTimedOut { |
| 242 props.Property = append(props.Property, &resp.Property{ | 242 props.Property = append(props.Property, &resp.Property{ |
| 243 Key: "Exit Code", | 243 Key: "Exit Code", |
| 244 Value: fmt.Sprintf("%d", sr.ExitCode), | 244 Value: fmt.Sprintf("%d", sr.ExitCode), |
| 245 }) | 245 }) |
| 246 } | 246 } |
| 247 return props | 247 return props |
| 248 } | 248 } |
| 249 | 249 |
| 250 func tagsToProperties(tags []string) *resp.PropertyGroup { | 250 func tagsToMap(tags []string) map[string]string { |
| 251 » props := &resp.PropertyGroup{GroupName: "Swarming Tags"} | 251 » result := map[string]string{} |
|
nodir
2017/03/01 23:25:04
preallocate len(tags) entries
hinoka
2017/03/02 03:44:40
Done.
| |
| 252 for _, t := range tags { | 252 for _, t := range tags { |
| 253 if t == "" { | 253 if t == "" { |
|
nodir
2017/03/01 23:25:04
this if statement is unnecessary: strings.SpinN(""
hinoka
2017/03/02 03:44:40
Done.
| |
| 254 continue | 254 continue |
| 255 } | 255 } |
| 256 parts := strings.SplitN(t, ":", 2) | 256 parts := strings.SplitN(t, ":", 2) |
| 257 » » p := &resp.Property{ | 257 » » if len(parts) == 2 { |
| 258 » » » Key: parts[0], | 258 » » » result[parts[0]] = parts[1] |
| 259 } | 259 } |
| 260 if len(parts) == 2 { | |
| 261 p.Value = parts[1] | |
| 262 } | |
| 263 props.Property = append(props.Property, p) | |
| 264 } | 260 } |
| 265 » return props | 261 » return result |
| 266 } | 262 } |
| 267 | 263 |
| 268 // addBuilderLink adds a link to the buildbucket builder view. | 264 // addBuilderLink adds a link to the buildbucket builder view. |
| 269 func addBuilderLink(c context.Context, build *resp.MiloBuild, swarmingHostname s tring, sr *swarming.SwarmingRpcsTaskResult) { | 265 func addBuilderLink(c context.Context, build *resp.MiloBuild, tags map[string]st ring) { |
| 270 » tags := swarmingTags(sr.Tags) | |
| 271 | |
| 272 bbHost := tags["buildbucket_hostname"] | 266 bbHost := tags["buildbucket_hostname"] |
| 273 bucket := tags["buildbucket_bucket"] | 267 bucket := tags["buildbucket_bucket"] |
| 274 builder := tags["builder"] | 268 builder := tags["builder"] |
| 275 if bucket == "" { | |
| 276 logging.Errorf( | |
| 277 c, "Could not extract buildbucket bucket from task %s", | |
| 278 taskPageURL(swarmingHostname, sr.TaskId)) | |
| 279 } | |
| 280 if builder == "" { | |
| 281 logging.Errorf( | |
| 282 c, "Could not extract builder name from task %s", | |
| 283 taskPageURL(swarmingHostname, sr.TaskId)) | |
| 284 } | |
| 285 if bucket != "" && builder != "" { | 269 if bucket != "" && builder != "" { |
| 286 build.Summary.ParentLabel = &resp.Link{ | 270 build.Summary.ParentLabel = &resp.Link{ |
| 287 Label: builder, | 271 Label: builder, |
| 288 URL: fmt.Sprintf("/buildbucket/%s/%s?server=%s", bucke t, builder, bbHost), | 272 URL: fmt.Sprintf("/buildbucket/%s/%s?server=%s", bucke t, builder, bbHost), |
| 289 } | 273 } |
| 290 } | 274 } |
| 291 } | 275 } |
| 292 | 276 |
| 293 // addBanner adds an OS banner derived from "os" swarming tag, if present. | 277 // addBanner adds an OS banner derived from "os" swarming tag, if present. |
| 294 func addBanner(build *resp.MiloBuild, sr *swarming.SwarmingRpcsTaskResult) { | 278 func addBanner(build *resp.MiloBuild, tags map[string]string) { |
| 295 » var os, ver string | 279 » os := tags["os"] |
| 296 » for _, t := range sr.Tags { | 280 » var ver string |
| 297 » » value := strings.TrimPrefix(t, "os:") | 281 » parts := strings.SplitN(os, "-", 2) |
| 298 » » if value == t { | 282 » if len(parts) == 2 { |
| 299 » » » // t does not have the prefix | 283 » » os = parts[0] |
| 300 » » » continue | 284 » » ver = parts[1] |
| 301 » » } | |
| 302 » » parts := strings.SplitN(value, "-", 2) | |
| 303 » » if len(parts) == 2 { | |
| 304 » » » os = parts[0] | |
| 305 » » » ver = parts[1] | |
| 306 » » » break | |
| 307 » » } | |
| 308 } | 285 } |
| 309 | 286 |
| 310 var base resp.LogoBase | 287 var base resp.LogoBase |
| 311 switch os { | 288 switch os { |
| 312 case "Ubuntu": | 289 case "Ubuntu": |
| 313 base = resp.Ubuntu | 290 base = resp.Ubuntu |
| 314 case "Windows": | 291 case "Windows": |
| 315 base = resp.Windows | 292 base = resp.Windows |
| 316 case "Mac": | 293 case "Mac": |
| 317 base = resp.OSX | 294 base = resp.OSX |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 ts, err := time.Parse(SwarmingTimeLayout, sr.CompletedTs) | 385 ts, err := time.Parse(SwarmingTimeLayout, sr.CompletedTs) |
| 409 if err != nil { | 386 if err != nil { |
| 410 return fmt.Errorf("invalid task CompletedTs: %s", err) | 387 return fmt.Errorf("invalid task CompletedTs: %s", err) |
| 411 } | 388 } |
| 412 step.Ended = google.NewTimestamp(ts) | 389 step.Ended = google.NewTimestamp(ts) |
| 413 } | 390 } |
| 414 | 391 |
| 415 return nil | 392 return nil |
| 416 } | 393 } |
| 417 | 394 |
| 395 func addBuildsetInfo(build *resp.MiloBuild, tags map[string]string) { | |
| 396 buildset := tags["buildset"] | |
| 397 if strings.HasPrefix(buildset, "patch/") { | |
| 398 patchset := strings.TrimLeft(buildset, "patch/") | |
| 399 // TODO(hinoka): Also support Rietveld patches. | |
| 400 if strings.HasPrefix(patchset, "gerrit/") { | |
| 401 gerritPatchset := strings.TrimLeft(patchset, "gerrit/") | |
| 402 parts := strings.Split(gerritPatchset, "/") | |
| 403 if len(parts) == 3 { | |
| 404 if build.SourceStamp == nil { | |
| 405 build.SourceStamp = &resp.SourceStamp{} | |
| 406 } | |
| 407 build.SourceStamp.Changelist = &resp.Link{ | |
| 408 Label: "Gerrit CL", | |
| 409 URL: fmt.Sprintf("https://%s/c/%s/%s", parts[0], parts[1], parts[2]), | |
| 410 } | |
| 411 } | |
| 412 } | |
| 413 } | |
| 414 } | |
|
nodir
2017/03/01 23:25:04
that's a lot of nesting. Consider inverting your i
hinoka
2017/03/02 03:44:40
Done.
| |
| 415 | |
| 416 func addRecipeLink(build *resp.MiloBuild, tags map[string]string) { | |
| 417 name := tags["recipe_name"] | |
|
nodir
2017/03/01 23:25:04
name is not used
hinoka
2017/03/02 03:44:40
It's used as the label
nodir
2017/03/02 04:01:25
oh, sorry, i am blind
| |
| 418 repo := tags["recipe_repository"] | |
| 419 revision := tags["recipe_revision"] | |
| 420 if name != "" && repo != "" { | |
| 421 subpath := "" | |
| 422 if revision != "" { | |
| 423 subpath += revision + "/" | |
| 424 } else { | |
| 425 subpath += "master/" | |
|
nodir
2017/03/01 23:25:04
it is more correct to use HEAD, not master
hinoka
2017/03/02 03:44:40
HEAD doesn't make any sense on git if you don't sp
nodir
2017/03/02 04:01:25
ack
| |
| 426 } | |
| 427 build.Summary.Recipe = &resp.Link{ | |
| 428 Label: name, | |
| 429 URL: fmt.Sprintf("%s/+/%s", repo, subpath), | |
|
nodir
2017/03/01 23:25:04
this works only on Gitiles. Let's not do this on n
hinoka
2017/03/02 03:44:40
Done.
| |
| 430 } | |
| 431 } | |
| 432 } | |
| 433 | |
| 418 func addTaskToBuild(c context.Context, server string, sr *swarming.SwarmingRpcsT askResult, build *resp.MiloBuild) error { | 434 func addTaskToBuild(c context.Context, server string, sr *swarming.SwarmingRpcsT askResult, build *resp.MiloBuild) error { |
| 435 selfURL := taskPageURL(server, sr.TaskId) | |
|
nodir
2017/03/01 23:25:04
s/selfURL/sourceURL/? or taskURL? self is ambiguou
hinoka
2017/03/02 03:44:40
Actually I'll just inline it.
| |
| 419 build.Summary.Label = sr.TaskId | 436 build.Summary.Label = sr.TaskId |
| 420 build.Summary.Type = resp.Recipe | 437 build.Summary.Type = resp.Recipe |
| 421 build.Summary.Source = &resp.Link{ | 438 build.Summary.Source = &resp.Link{ |
| 422 Label: "Task " + sr.TaskId, | 439 Label: "Task " + sr.TaskId, |
| 423 » » URL: taskPageURL(server, sr.TaskId), | 440 » » URL: selfURL, |
| 424 } | 441 } |
| 425 | 442 |
| 426 // Extract more swarming specific information into the properties. | 443 // Extract more swarming specific information into the properties. |
| 427 if props := taskProperties(sr); len(props.Property) > 0 { | 444 if props := taskProperties(sr); len(props.Property) > 0 { |
| 428 build.PropertyGroup = append(build.PropertyGroup, props) | 445 build.PropertyGroup = append(build.PropertyGroup, props) |
| 429 } | 446 } |
| 430 » if props := tagsToProperties(sr.Tags); len(props.Property) > 0 { | 447 » tags := tagsToMap(sr.Tags) |
| 431 » » build.PropertyGroup = append(build.PropertyGroup, props) | |
| 432 » } | |
| 433 | 448 |
| 434 » addBuilderLink(c, build, server, sr) | 449 » addBuildsetInfo(build, tags) |
| 435 » addBanner(build, sr) | 450 » addBanner(build, tags) |
| 451 » addBuilderLink(c, build, tags) | |
| 452 » addRecipeLink(build, tags) | |
| 436 | 453 |
| 437 // Add a link to the bot. | 454 // Add a link to the bot. |
| 438 if sr.BotId != "" { | 455 if sr.BotId != "" { |
| 439 build.Summary.Bot = &resp.Link{ | 456 build.Summary.Bot = &resp.Link{ |
| 440 Label: sr.BotId, | 457 Label: sr.BotId, |
| 441 URL: botPageURL(server, sr.BotId), | 458 URL: botPageURL(server, sr.BotId), |
| 442 } | 459 } |
| 443 } | 460 } |
| 444 | 461 |
| 445 return nil | 462 return nil |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 for _, tag := range v { | 724 for _, tag := range v { |
| 708 var value string | 725 var value string |
| 709 parts := strings.SplitN(tag, ":", 2) | 726 parts := strings.SplitN(tag, ":", 2) |
| 710 if len(parts) == 2 { | 727 if len(parts) == 2 { |
| 711 value = parts[1] | 728 value = parts[1] |
| 712 } | 729 } |
| 713 res[parts[0]] = value | 730 res[parts[0]] = value |
| 714 } | 731 } |
| 715 return res | 732 return res |
| 716 } | 733 } |
| OLD | NEW |