Order a branch's plans by its merges, and build the newest commit (hq issue 349)

A merge acted on late by the catch-up made its plan after the plan of the
merge that followed it, superseded it by creation time, and folded its
unbuilt modules into a plan at the older commit: on 2026-10-09 the
forge's security fix (a082615b) was superseded by 8ff8197a. A plan now
keeps its merge time (migration 0086), supersession follows it, and a
merge older than an open plan of its branch is planned at that plan's
commit, which contains it.
This commit is contained in:
2026-10-09 15:00:56 +02:00
committed by jochen
parent 077ddf0eb8
commit 997a4925b0
5 changed files with 184 additions and 8 deletions
+14
View File
@@ -345,6 +345,20 @@ func (f following) SourceMoved(ctx context.Context, m link.SourceMoved) error {
e.Manifest.Module, m.Owner, m.Repo, e.Source.Ref, m.Base)
}
}
// **A merge older than an open plan of its branch is planned at that plan's commit** (novox/hq issue
// 349): the catch-up acts on a merge the bus did not hand over after the merges that came after it,
// and planned at its own commit it built what the later merge had fixed from the commit before the fix.
// The later commit contains this merge's change, so what this merge moved is built from there, and the
// plan made here supersedes that one as any newer plan does.
if open, err := inv.OpenPlans(ctx); err == nil {
if newest, later := newestOnTheBranch(m, open); later {
fmt.Printf(" %s/%s %.8s was merged before %.8s, which %s is planning: what it moved is built "+
"from %.8s, which contains it\n", m.Owner, m.Repo, m.Commit, newest.Commit, newest.ID, newest.Commit)
m.Commit, m.MergedAt = newest.Commit, newest.Merged.Format(time.RFC3339)
}
} else {
return notNow(err)
}
touched, added, _ := touchedBy(from, entries, m)
// **A module the merge deleted is not built** (novox/hq ADR 0236): its manifest is gone, so the build
// seat finds nothing saying what it is, and the plan failed on it (`has no module.json at …`) with