| OLD | NEW |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 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 buildbot | 5 package buildbot |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| 11 "io/ioutil" | 11 "io/ioutil" |
| 12 "math" | 12 "math" |
| 13 "path/filepath" | 13 "path/filepath" |
| 14 "regexp" | 14 "regexp" |
| 15 "sort" | 15 "sort" |
| 16 "strconv" |
| 16 "strings" | 17 "strings" |
| 17 "time" | 18 "time" |
| 18 | 19 |
| 19 "golang.org/x/net/context" | 20 "golang.org/x/net/context" |
| 20 | 21 |
| 21 "github.com/luci/gae/service/datastore" | 22 "github.com/luci/gae/service/datastore" |
| 22 "github.com/luci/luci-go/common/data/stringset" | 23 "github.com/luci/luci-go/common/data/stringset" |
| 23 "github.com/luci/luci-go/common/logging" | 24 "github.com/luci/luci-go/common/logging" |
| 24 "github.com/luci/luci-go/milo/api/resp" | 25 "github.com/luci/luci-go/milo/api/resp" |
| 25 "github.com/luci/luci-go/milo/appengine/common/model" | 26 "github.com/luci/luci-go/milo/appengine/common/model" |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 }) | 389 }) |
| 389 } | 390 } |
| 390 return | 391 return |
| 391 } | 392 } |
| 392 | 393 |
| 393 // sourcestamp extracts the source stamp from various parts of a buildbot build, | 394 // sourcestamp extracts the source stamp from various parts of a buildbot build, |
| 394 // including the properties. | 395 // including the properties. |
| 395 func sourcestamp(c context.Context, b *buildbotBuild) *resp.SourceStamp { | 396 func sourcestamp(c context.Context, b *buildbotBuild) *resp.SourceStamp { |
| 396 ss := &resp.SourceStamp{} | 397 ss := &resp.SourceStamp{} |
| 397 rietveld := "" | 398 rietveld := "" |
| 399 gerrit := "" |
| 398 got_revision := "" | 400 got_revision := "" |
| 399 repository := "" | 401 repository := "" |
| 400 issue := int64(-1) | 402 issue := int64(-1) |
| 401 // TODO(hinoka): Gerrit URLs. | |
| 402 for _, prop := range b.Properties { | 403 for _, prop := range b.Properties { |
| 403 switch prop.Name { | 404 switch prop.Name { |
| 404 case "rietveld": | 405 case "rietveld": |
| 405 if v, ok := prop.Value.(string); ok { | 406 if v, ok := prop.Value.(string); ok { |
| 406 rietveld = v | 407 rietveld = v |
| 407 } else { | 408 } else { |
| 408 logging.Warningf(c, "Field rietveld is not a str
ing: %#v", prop.Value) | 409 logging.Warningf(c, "Field rietveld is not a str
ing: %#v", prop.Value) |
| 409 } | 410 } |
| 410 case "issue": | 411 case "issue": |
| 412 // Sometime this is a number (float), sometime it is a s
tring. |
| 411 if v, ok := prop.Value.(float64); ok { | 413 if v, ok := prop.Value.(float64); ok { |
| 412 issue = int64(v) | 414 issue = int64(v) |
| 415 } else if v, ok := prop.Value.(string); ok { |
| 416 if vi, err := strconv.ParseInt(v, 10, 64); err =
= nil { |
| 417 issue = int64(vi) |
| 418 } else { |
| 419 logging.Warningf(c, "Could not decode fi
eld issue: %q - %s", prop.Value, err) |
| 420 } |
| 413 } else { | 421 } else { |
| 414 » » » » logging.Warningf(c, "Field issue is not a float:
%#v", prop.Value) | 422 » » » » logging.Warningf(c, "Field issue is not a string
or float: %#v", prop.Value) |
| 415 } | 423 } |
| 416 | 424 |
| 417 case "got_revision": | 425 case "got_revision": |
| 418 if v, ok := prop.Value.(string); ok { | 426 if v, ok := prop.Value.(string); ok { |
| 419 got_revision = v | 427 got_revision = v |
| 420 } else { | 428 } else { |
| 421 logging.Warningf(c, "Field got_revision is not a
string: %#v", prop.Value) | 429 logging.Warningf(c, "Field got_revision is not a
string: %#v", prop.Value) |
| 422 } | 430 } |
| 423 | 431 |
| 432 case "patch_issue": |
| 433 if v, ok := prop.Value.(float64); ok { |
| 434 issue = int64(v) |
| 435 } else { |
| 436 logging.Warningf(c, "Field patch_issue is not a
float: %#v", prop.Value) |
| 437 } |
| 438 |
| 439 case "patch_gerrit_url": |
| 440 if v, ok := prop.Value.(string); ok { |
| 441 gerrit = v |
| 442 } else { |
| 443 logging.Warningf(c, "Field gerrit is not a strin
g: %#v", prop.Value) |
| 444 } |
| 445 |
| 424 case "repository": | 446 case "repository": |
| 425 if v, ok := prop.Value.(string); ok { | 447 if v, ok := prop.Value.(string); ok { |
| 426 repository = v | 448 repository = v |
| 427 } | 449 } |
| 428 } | 450 } |
| 429 } | 451 } |
| 430 if issue != -1 { | 452 if issue != -1 { |
| 431 » » if rietveld != "" { | 453 » » switch { |
| 454 » » case rietveld != "": |
| 432 rietveld = strings.TrimRight(rietveld, "/") | 455 rietveld = strings.TrimRight(rietveld, "/") |
| 433 ss.Changelist = resp.NewLink( | 456 ss.Changelist = resp.NewLink( |
| 434 » » » » fmt.Sprintf("Issue %d", issue), | 457 » » » » fmt.Sprintf("Rietveld CL %d", issue), |
| 435 » » » » fmt.Sprintf("%s/%d", rietveld, issue), | 458 » » » » fmt.Sprintf("%s/%d", rietveld, issue)) |
| 436 » » » ) | 459 » » case gerrit != "": |
| 437 » » } else { | 460 » » » gerrit = strings.TrimRight(gerrit, "/") |
| 438 » » » logging.Warningf(c, "Found issue but not rietveld proper
ty.") | 461 » » » ss.Changelist = resp.NewLink( |
| 462 » » » » fmt.Sprintf("Gerrit CL %d", issue), |
| 463 » » » » fmt.Sprintf("%s/c/%d", gerrit, issue)) |
| 439 } | 464 } |
| 440 } | 465 } |
| 466 |
| 441 if got_revision != "" { | 467 if got_revision != "" { |
| 442 ss.Revision = resp.NewLink(got_revision, "") | 468 ss.Revision = resp.NewLink(got_revision, "") |
| 443 if repository != "" { | 469 if repository != "" { |
| 444 ss.Revision.URL = repository + "/+/" + got_revision | 470 ss.Revision.URL = repository + "/+/" + got_revision |
| 445 } | 471 } |
| 446 } | 472 } |
| 447 return ss | 473 return ss |
| 448 } | 474 } |
| 449 | 475 |
| 450 func renderBuild(c context.Context, b *buildbotBuild) *resp.MiloBuild { | 476 func renderBuild(c context.Context, b *buildbotBuild) *resp.MiloBuild { |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 var newAliases map[string][]*buildbotLinkAlias | 652 var newAliases map[string][]*buildbotLinkAlias |
| 627 if l := remainingAliases.Len(); l > 0 { | 653 if l := remainingAliases.Len(); l > 0 { |
| 628 newAliases = make(map[string][]*buildbotLinkAlias, l) | 654 newAliases = make(map[string][]*buildbotLinkAlias, l) |
| 629 remainingAliases.Iter(func(v string) bool { | 655 remainingAliases.Iter(func(v string) bool { |
| 630 newAliases[v] = s.Aliases[v] | 656 newAliases[v] = s.Aliases[v] |
| 631 return true | 657 return true |
| 632 }) | 658 }) |
| 633 } | 659 } |
| 634 s.Aliases = newAliases | 660 s.Aliases = newAliases |
| 635 } | 661 } |
| OLD | NEW |