diff --git a/modules/mesh-delivery-checker/internal/check/line.go b/modules/mesh-delivery-checker/internal/check/line.go index 0882cf1..cedef15 100644 --- a/modules/mesh-delivery-checker/internal/check/line.go +++ b/modules/mesh-delivery-checker/internal/check/line.go @@ -2,6 +2,7 @@ package check import ( "fmt" + "slices" "strings" "unicode/utf8" @@ -50,7 +51,7 @@ func firstFailed(v delivery.Verdict) string { // pieces are the parts of a line, from the most to the least needed. type pieces struct { - head, commits, counts, shortCounts, times, shortTimes, over, builds, composition, group string + head, commits, counts, shortCounts, times, shortTimes, over, builds, composition, shortComposition, group string } func (p pieces) join(drop int) string { @@ -70,7 +71,10 @@ func (p pieces) join(drop int) string { if drop < 2 && p.group != "" { parts = append(parts, p.group) } - if p.composition != "" { + switch { + case drop >= 3 && p.shortComposition != "": + parts = append(parts, p.shortComposition) + case p.composition != "": parts = append(parts, p.composition) } out := make([]string, 0, len(parts)) @@ -90,14 +94,37 @@ func levelWords(name string, r delivery.LevelResult) string { return s } -func compositionWords(c *delivery.Composition) string { - switch { - case c == nil, c.State == delivery.CompositionNotRun: +// compositionWords says the composition: not yet run, or once the assigner's check reports it (issue 1297) passed or +// failed, with the time it took and the machines it composed (issue 1300). +func compositionWords(c *delivery.Composition, took int64) string { return composition(c, took, false) } + +// composition is compositionWords; short counts the machines and leaves the SDK commit to the report. +func composition(c *delivery.Composition, took int64, short bool) string { + if c == nil || c.State == delivery.CompositionNotRun { return "composition not yet run" - case c.State == delivery.CompositionPass: - return "composition passed with " + short12(c.SDK) } - return "composition failed: " + c.Words + in := "" + if took > 0 { + in = " in " + seconds(took) + } + on := "" + if len(c.Machines) > 0 { + machines := slices.Sorted(slices.Values(c.Machines)) + on = " on " + strings.Join(machines, ", ") + switch { + case len(machines) > 1 && short: + on = fmt.Sprintf(" on %d machines", len(machines)) + case len(machines) > 1: + on = fmt.Sprintf(" on %d machines: %s", len(machines), strings.Join(machines, ", ")) + } + } + switch { + case c.State == delivery.CompositionPass && short: + return "composition passed" + in + on // the SDK it composed with is in the report + case c.State == delivery.CompositionPass: + return "composition passed" + in + " with " + short12(c.SDK) + on + } + return "composition failed" + in + on + ": " + c.Words } func buildWords(builds []BuildNote) string { @@ -149,7 +176,7 @@ func parts(v delivery.Verdict, cs *Case, p Pull, builds []BuildNote, slowest []s for _, x := range []struct { name string ms int64 - }{{"queue", t.Queue}, {"clone", t.Clone}, {"unit", t.Unit}, {"int setup", t.IntegrationSetup}, {"int run", t.IntegrationRun}, {"composition", t.Composition}} { + }{{"queue", t.Queue}, {"clone", t.Clone}, {"unit", t.Unit}, {"int setup", t.IntegrationSetup}, {"int run", t.IntegrationRun}} { if x.ms > 0 { times = append(times, x.name+" "+seconds(x.ms)) } @@ -181,7 +208,8 @@ func parts(v delivery.Verdict, cs *Case, p Pull, builds []BuildNote, slowest []s } pc.builds = buildWords(builds) if v.State != delivery.VerdictRunning { - pc.composition = compositionWords(v.Composition) + pc.composition = compositionWords(v.Composition, v.Took.Composition) + pc.shortComposition = composition(v.Composition, v.Took.Composition, true) } if cs != nil && len(cs.Pulls) > 1 { pc.group = fmt.Sprintf("group %s of %d pull requests", cs.Group, len(cs.Pulls)) diff --git a/modules/mesh-delivery-checker/internal/check/line_test.go b/modules/mesh-delivery-checker/internal/check/line_test.go index 6ea2499..662db1d 100644 --- a/modules/mesh-delivery-checker/internal/check/line_test.go +++ b/modules/mesh-delivery-checker/internal/check/line_test.go @@ -133,3 +133,24 @@ func TestThePassedCompositionIsSaidOnlyWhenItWasRun(t *testing.T) { // ADR 0484 t.Errorf("a verdict with no composition: %q", r) } } + +func TestTheCompositionsTimeAndMachinesAreSaidOnceTheAssignerReportsThem(t *testing.T) { // 1300 (C10), the assigner's verdict (issue 1297) + cs, p := lineCase(t, pullOf(repoA, 7, head1)) + v := passVerdict() + v.Took.Composition = 2400 + v.Composition = &delivery.Composition{State: delivery.CompositionPass, SDK: "afbe371003a570f088be4a394d83aa7a9458f7ab", Machines: []string{"g14", "ace", "novox", "shanks"}} + r := Report(v, cs, p, nil, nil) + for _, want := range []string{"composition passed in 2.4s with afbe371003a5 on 4 machines: ace, g14, novox, shanks"} { + if !strings.Contains(r, want) { + t.Errorf("report %q lacks %q", r, want) + } + } + if l := Line(v, cs, p, nil, nil); !strings.Contains(l, "composition passed in 2.4s") || !strings.Contains(l, "on 4 machines") || utf8.RuneCountInString(l) > MaxLine { + t.Errorf("line = %q", l) + } + v.State, v.Failed = delivery.VerdictFail, delivery.FailedFirst{Machine: "novox", Words: "composition refused"} + v.Composition = &delivery.Composition{State: delivery.CompositionFail, Words: "novox: two seats claim dns", Machines: []string{"novox"}} + if r := Report(v, cs, p, nil, nil); !strings.Contains(r, "composition failed in 2.4s on novox: novox: two seats claim dns") { + t.Errorf("failed composition report = %q", r) + } +}