gate: an approved merge whose trunk moved waits for its carried verdict and merges on it with no second ask, never on the old one (ADR 0548 §8; issue 568 G4)
This commit is contained in:
@@ -164,6 +164,45 @@ func TestOneCheckPerDeliveryAtTheGate(t *testing.T) {
|
||||
t.Fatalf("merges %v; the turns were %q, want %q", w.forge.merges, turns.said(), want)
|
||||
}
|
||||
},
|
||||
// §8: an approved delivery whose trunk moved goes back to proposed, waits for its carried verdict rather than being
|
||||
// handed on the old one, and merges on it with no second ask.
|
||||
"an approved merge whose trunk moved merges on its carried verdict with no second ask": func(t *testing.T) {
|
||||
w := newWorld(t)
|
||||
putCheckerVerdict(w, "running", headOf(oneRepo, 9, otherHead)) // holds the approved merge (§2)
|
||||
id := approvedLone(w)
|
||||
w.settleAll()
|
||||
if w.op.count() != 1 || len(w.forge.merges) != 0 {
|
||||
t.Fatalf("asked %d times, merges %v; want approved and held", w.op.count(), w.forge.merges)
|
||||
}
|
||||
w.h.PullMerged(merged(oneRepo, 5, otherHead, oneTrunk2)) // a merge at the forge moves the trunk
|
||||
putCheckerVerdict(w, "pass", headOf(oneRepo, 9, otherHead))
|
||||
w.settleAll()
|
||||
if len(w.forge.merges) != 0 {
|
||||
t.Fatalf("merges %v: handed on a verdict judged on the old trunk", w.forge.merges)
|
||||
}
|
||||
d := w.delivery(id)
|
||||
if d.Ready == nil || !strings.Contains(d.Ready.Waits, "being carried") {
|
||||
t.Fatalf("after the trunk moved it waits for %q, want its verdict carried", d.Ready.Waits)
|
||||
}
|
||||
// The checker's carried line: the head on the new trunk, carried from the old one.
|
||||
carried := checkStatus(oneRepo, oneHead, "success", oneTrunk2)
|
||||
carried.Description = "pass " + oneHead[:12] + " on " + oneTrunk2[:12] + " | carried from " + oneTrunk[:12] + " | unit 0 run, 4 kept"
|
||||
if head, trunk := checkLine(carried.Description); head != oneHead[:12] || trunk != oneTrunk2[:12] {
|
||||
t.Fatalf("the carried line reads as %s on %s", head, trunk)
|
||||
}
|
||||
if head, trunk := checkLine("failed: a test"); head != "" || trunk != "" {
|
||||
t.Fatalf("a line that names no commits gave %q %q", head, trunk)
|
||||
}
|
||||
putCheckerVerdict(w, "pass", headOf(oneRepo, 1, oneHead))
|
||||
w.h.CommitStatus(carried)
|
||||
w.settleAll()
|
||||
if w.op.count() != 1 {
|
||||
t.Errorf("the Approve was asked %d times, want once: it stands through the carry", w.op.count())
|
||||
}
|
||||
if d := w.delivery(id); d.Check == nil || d.Check.Trunk != oneTrunk2[:12] || len(w.forge.merges) != 1 {
|
||||
t.Errorf("after the carry: verdict %+v, merges %v; want merged on the carried verdict", d.Check, w.forge.merges)
|
||||
}
|
||||
},
|
||||
} {
|
||||
t.Run(name, run)
|
||||
}
|
||||
|
||||
@@ -199,14 +199,3 @@ func TestAClosedPullRequestAsksNoForgetChecks(t *testing.T) {
|
||||
w.h.PullUpdated(p)
|
||||
w.h.PullClosed(p)
|
||||
}
|
||||
|
||||
// 1302: the mesh/check line gives the head and the trunk it judged.
|
||||
func TestTheCheckLineGivesHeadAndTrunk(t *testing.T) {
|
||||
head, trunk := checkLine("pass " + oneHead[:12] + " on " + oneTrunk[:12] + " | unit 4 run, 0 kept | group g of 2 pull requests")
|
||||
if head != oneHead[:12] || trunk != oneTrunk[:12] {
|
||||
t.Fatalf("head %q trunk %q", head, trunk)
|
||||
}
|
||||
if head, trunk = checkLine("failed: a test"); head != "" || trunk != "" {
|
||||
t.Fatalf("a line that names no commits gave %q %q", head, trunk)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +387,9 @@ func (h *Holder) readyWaits(d *Delivery) string {
|
||||
case d.State == Proposed && d.outOfDate() != "" && d.AskedAgain != nil:
|
||||
return "its check against the trunk's head is asked and has not answered"
|
||||
case d.State == Proposed && d.outOfDate() != "" && d.Check.Passes() && h.covering(d) != nil:
|
||||
// Approved, and its trunk moved: the checker carries its verdict to the trunk's head by its package digests (ADR 0548
|
||||
// §5, §8). The Approve stands and is not asked again; the merge waits for the carried verdict, not a fresh check.
|
||||
return "approved; its verdict is being carried to the trunk's head " + shortOf(d.TrunkNow, 12) + " (" + d.outOfDate() + ")"
|
||||
case d.State == Proposed && d.outOfDate() != "":
|
||||
return "its verdict is out of date: its check against the trunk's head is asked before the operator is"
|
||||
case d.State == Proposed && d.AskedAgain != nil:
|
||||
|
||||
Reference in New Issue
Block a user