mesh/merge-gate head 060f2a9ca5fd merged into trunk 04730b54a8f2 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head 060f2a9ca5fd merged into trunk 04730b54a8f2 — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
The gate and the repository's check mount the workspace read-write, so a build from that tree could hold what the tests wrote under a key that describes the merge. A check now clones the merge outside the workspace before anything of the change runs, and builds from that. A check keeps, and a walk takes, only a build an earlier check of the same pull request at the same head made: another pull request's build, or an earlier head's, is never registered. The walk reads the verdicts once (novox/hq issue 703, review of #328).
88 lines
3.4 KiB
Go
88 lines
3.4 KiB
Go
package link
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// The builds a walk may take are read from the build seat's own outcomes of its checks (novox/hq ADR 0350 §2): only
|
|
// checks of the walk's pull requests, only builds made, newest first.
|
|
func TestNatsTheBuildsAWalkMayTakeAreTheChecksOutcomesOfItsPullRequests(t *testing.T) {
|
|
js := aBus(t)
|
|
since := time.Now().Add(-time.Minute)
|
|
say := func(r BuildResult) {
|
|
body, _ := json.Marshal(r)
|
|
if _, err := js.Context().Publish(BuildOutcomeOf(TheBuildMachine), body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
mine := &CheckRequest{Owner: "novox", Repo: "shop", Number: 7}
|
|
built := CheckBuilt{Module: "app", Key: "r1:1", Made: []MadeArtifact{{Name: "server", Reference: "s/app/server@sha256:a"}}}
|
|
say(BuildResult{ID: "build-1", Checked: mine, Check: &CheckOutcome{Verdict: "pass", Built: []CheckBuilt{built,
|
|
{Module: "web", NotBuilt: "it has no reuse key"}}}})
|
|
say(BuildResult{ID: "build-2", Checked: &CheckRequest{Owner: "novox", Repo: "shop", Number: 8},
|
|
Check: &CheckOutcome{Verdict: "pass", Built: []CheckBuilt{built}}})
|
|
say(BuildResult{ID: "build-3", Repository: "novox/shop", Commit: "c0ffee"}) // a build, not a check
|
|
newer := built
|
|
newer.Key = "r1:2"
|
|
say(BuildResult{ID: "build-4", Checked: mine, Check: &CheckOutcome{Verdict: "pass", Built: []CheckBuilt{newer}}})
|
|
|
|
got, err := ReadCheckBuilds(t.Context(), js, TheBuildMachine, []PullRef{{Owner: "novox", Repo: "shop", Number: 7}}, since)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got) != 2 || got[0].Check != "build-4" || got[0].Built.Key != "r1:2" || got[1].Check != "build-1" ||
|
|
got[1].Pull.Number != 7 {
|
|
t.Fatalf("read %+v", got)
|
|
}
|
|
}
|
|
|
|
// A build is read with the head its check judged, and a kept build is named as the check's that built it (novox/hq
|
|
// issue 703).
|
|
func TestNatsAKeptBuildIsTheBuildersCheckAndEveryBuildSaysItsHead(t *testing.T) {
|
|
js := aBus(t)
|
|
since := time.Now().Add(-time.Minute)
|
|
say := func(r BuildResult) {
|
|
body, _ := json.Marshal(r)
|
|
if _, err := js.Context().Publish(BuildOutcomeOf(TheBuildMachine), body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
mine := &CheckRequest{Owner: "novox", Repo: "shop", Number: 7}
|
|
app := CheckBuilt{Module: "app", Key: "r1:1", Made: []MadeArtifact{{Name: "server", Reference: "s/app/server@sha256:a"}}}
|
|
say(BuildResult{ID: "build-1", Checked: mine, Check: &CheckOutcome{Verdict: "pass", Head: "aaaaaaaaaaaa",
|
|
Built: []CheckBuilt{app}}})
|
|
kept := app
|
|
kept.Kept = "build-1"
|
|
say(BuildResult{ID: "build-2", Checked: mine, Check: &CheckOutcome{Verdict: "pass", Head: "aaaaaaaaaaaa",
|
|
Built: []CheckBuilt{kept}}})
|
|
|
|
got, err := ReadCheckBuilds(t.Context(), js, TheBuildMachine, []PullRef{{Owner: "novox", Repo: "shop", Number: 7}}, since)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got) != 2 || got[0].Check != "build-1" || got[0].Built.Kept != "build-1" || got[0].Head != "aaaaaaaaaaaa" ||
|
|
got[1].Check != "build-1" || got[1].Head != "aaaaaaaaaaaa" {
|
|
t.Fatalf("read %+v", got)
|
|
}
|
|
}
|
|
|
|
// Two spellings of a head are the same head only when both say at least twelve characters of it.
|
|
func TestSameHeadNeedsTwelveCharactersOfBoth(t *testing.T) {
|
|
for _, c := range []struct {
|
|
a, b string
|
|
same bool
|
|
}{
|
|
{"aaaaaaaaaaaa", "aaaaaaaaaaaabbbb", true},
|
|
{"aaaaaaaaaaaabbbb", "aaaaaaaaaaaa", true},
|
|
{"aaaaaaaaaaaa", "aaaaaaaaaaab", false},
|
|
{"", "", false},
|
|
{"aaaa", "aaaaaaaaaaaa", false},
|
|
} {
|
|
if SameHead(c.a, c.b) != c.same {
|
|
t.Errorf("SameHead(%q, %q) is %v", c.a, c.b, !c.same)
|
|
}
|
|
}
|
|
}
|