| Index: appengine/cmd/milo/logdog/logDogBuild.go
|
| diff --git a/appengine/cmd/milo/logdog/logDogBuild.go b/appengine/cmd/milo/logdog/logDogBuild.go
|
| index 27ae39b791292fe6fc769c214e3ffe21445dd476..2d8f3e862c1fcaa4ebf231c6dc1d9ea13feb7d16 100644
|
| --- a/appengine/cmd/milo/logdog/logDogBuild.go
|
| +++ b/appengine/cmd/milo/logdog/logDogBuild.go
|
| @@ -6,21 +6,27 @@ package logdog
|
|
|
| import (
|
| "fmt"
|
| - "strings"
|
| "time"
|
|
|
| "golang.org/x/net/context"
|
|
|
| "github.com/luci/luci-go/appengine/cmd/milo/resp"
|
| "github.com/luci/luci-go/common/clock"
|
| - "github.com/luci/luci-go/common/logging"
|
| miloProto "github.com/luci/luci-go/common/proto/milo"
|
| )
|
|
|
| +// URLBuilder constructs URLs for various link types.
|
| +type URLBuilder interface {
|
| + // LinkURL returns the URL associated with the supplied Link.
|
| + //
|
| + // If no URL could be built for that Link, nil will be returned.
|
| + BuildLink(l *miloProto.Link) *resp.Link
|
| +}
|
| +
|
| // miloBuildStep converts a logdog/milo step to a BuildComponent struct.
|
| // buildCompletedTime must be zero if build did not complete yet.
|
| -func miloBuildStep(c context.Context, linkBase string, anno *miloProto.Step, buildCompletedTime time.Time) *resp.BuildComponent {
|
| - linkBase = strings.TrimSuffix(linkBase, "/")
|
| +func miloBuildStep(ub URLBuilder, anno *miloProto.Step, buildCompletedTime, now time.Time) *resp.BuildComponent {
|
| +
|
| comp := &resp.BuildComponent{Label: anno.Name}
|
| switch anno.Status {
|
| case miloProto.Status_RUNNING:
|
| @@ -30,8 +36,8 @@ func miloBuildStep(c context.Context, linkBase string, anno *miloProto.Step, bui
|
| comp.Status = resp.Success
|
|
|
| case miloProto.Status_FAILURE:
|
| - if anno.GetFailureDetails() != nil {
|
| - switch anno.GetFailureDetails().Type {
|
| + if fd := anno.GetFailureDetails(); fd != nil {
|
| + switch fd.Type {
|
| case miloProto.FailureDetails_EXCEPTION, miloProto.FailureDetails_INFRA:
|
| comp.Status = resp.InfraFailure
|
|
|
| @@ -41,39 +47,54 @@ func miloBuildStep(c context.Context, linkBase string, anno *miloProto.Step, bui
|
| default:
|
| comp.Status = resp.Failure
|
| }
|
| +
|
| + if fd.Text != "" {
|
| + comp.Text = append(comp.Text, fd.Text)
|
| + }
|
| } else {
|
| comp.Status = resp.Failure
|
| }
|
|
|
| + case miloProto.Status_PENDING:
|
| + comp.Status = resp.NotRun
|
| +
|
| // Missing the case of waiting on unfinished dependency...
|
| default:
|
| comp.Status = resp.NotRun
|
| }
|
|
|
| - if !buildCompletedTime.IsZero() && !comp.Status.Terminal() {
|
| - // we cannot have unfinished steps in finished builds.
|
| + if !(buildCompletedTime.IsZero() || comp.Status.Terminal()) {
|
| + // The build has completed, but this step has not. Mark it as an
|
| + // infrastructure failure.
|
| comp.Status = resp.InfraFailure
|
| }
|
|
|
| - // Sub link is for one link per log that isn't stdout.
|
| - for _, link := range anno.GetOtherLinks() {
|
| - lds := link.GetLogdogStream()
|
| - if lds == nil {
|
| - logging.Warningf(c, "Warning: %v of %v has an empty logdog stream.", link, anno)
|
| - continue // DNE???
|
| + // Main link is a link to the stdout.
|
| + var stdoutLink *miloProto.Link
|
| + if anno.StdoutStream != nil {
|
| + stdoutLink = &miloProto.Link{
|
| + Label: "stdout",
|
| + Value: &miloProto.Link_LogdogStream{
|
| + LogdogStream: anno.StdoutStream,
|
| + },
|
| }
|
| - newLink := &resp.Link{
|
| - Label: lds.Name,
|
| - URL: linkBase + "/" + lds.Name,
|
| + }
|
| +
|
| + if anno.Link != nil {
|
| + comp.MainLink = ub.BuildLink(anno.Link)
|
| +
|
| + // If we also have a STDOUT stream, add it to our OtherLinks.
|
| + if stdoutLink != nil {
|
| + anno.OtherLinks = append([]*miloProto.Link{stdoutLink}, anno.OtherLinks...)
|
| }
|
| - comp.SubLink = append(comp.SubLink, newLink)
|
| + } else if stdoutLink != nil {
|
| + comp.MainLink = ub.BuildLink(stdoutLink)
|
| }
|
|
|
| - // Main link is a link to the stdout.
|
| - if anno.StdoutStream != nil {
|
| - comp.MainLink = &resp.Link{
|
| - Label: "stdout",
|
| - URL: linkBase + "/" + anno.StdoutStream.Name,
|
| + // Sub link is for one link per log that isn't stdout.
|
| + for _, link := range anno.GetOtherLinks() {
|
| + if l := ub.BuildLink(link); l != nil {
|
| + comp.SubLink = append(comp.SubLink, l)
|
| }
|
| }
|
|
|
| @@ -89,34 +110,39 @@ func miloBuildStep(c context.Context, linkBase string, anno *miloProto.Step, bui
|
|
|
| var till time.Time
|
| switch {
|
| - case comp.Status == resp.Running:
|
| - till = clock.Now(c)
|
| case !comp.Finished.IsZero():
|
| till = comp.Finished
|
| - default:
|
| + case comp.Status == resp.Running:
|
| + till = now
|
| + case !buildCompletedTime.IsZero():
|
| till = buildCompletedTime
|
| }
|
| - if !comp.Started.IsZero() && !till.IsZero() {
|
| + if !comp.Started.IsZero() && till.After(comp.Started) {
|
| comp.Duration = till.Sub(comp.Started)
|
| }
|
|
|
| // This should be the exact same thing.
|
| - comp.Text = anno.Text
|
| + comp.Text = append(comp.Text, anno.Text...)
|
|
|
| return comp
|
| }
|
|
|
| // AddLogDogToBuild takes a set of logdog streams and populate a milo build.
|
| // build.Summary.Finished must be set.
|
| -func AddLogDogToBuild(c context.Context, linkBase string, s *Streams, build *resp.MiloBuild) {
|
| +func AddLogDogToBuild(c context.Context, ub URLBuilder, s *Streams, build *resp.MiloBuild) {
|
| if s.MainStream == nil {
|
| panic("missing main stream")
|
| }
|
| // Now Fetch the main annotation of the build.
|
| - mainAnno := s.MainStream.Data
|
| + var (
|
| + mainAnno = s.MainStream.Data
|
| + now = clock.Now(c)
|
| + )
|
|
|
| // Now fill in each of the step components.
|
| // TODO(hinoka): This is totes cachable.
|
| + buildCompletedTime := mainAnno.Ended.Time()
|
| + build.Summary = *(miloBuildStep(ub, mainAnno, buildCompletedTime, now))
|
| for _, substepContainer := range mainAnno.Substep {
|
| anno := substepContainer.GetStep()
|
| if anno == nil {
|
| @@ -124,8 +150,8 @@ func AddLogDogToBuild(c context.Context, linkBase string, s *Streams, build *res
|
| continue
|
| }
|
|
|
| - bs := miloBuildStep(c, linkBase, anno, build.Summary.Finished)
|
| - if bs.Status != resp.Success && bs.Status != resp.NotRun {
|
| + bs := miloBuildStep(ub, anno, buildCompletedTime, now)
|
| + if bs.Status != resp.Success {
|
| build.Summary.Text = append(
|
| build.Summary.Text, fmt.Sprintf("%s %s", bs.Status, bs.Label))
|
| }
|
|
|