103 lines
4.2 KiB
Go
103 lines
4.2 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
)
|
|
|
|
func TestOnlyAWalksAskTakesAChecksBuildAndADryRunNever(t *testing.T) {
|
|
p := &inventory.Plan{Delivery: &inventory.PlanDelivery{Merges: []inventory.PlanMerge{
|
|
{Repository: "novox/shop", Number: 7}, {Repository: "http://forge.invalid/novox/web.git", Number: 3},
|
|
{Repository: "novox/shop", Number: 7}, {Repository: "novox/shop"}}}}
|
|
asked := reuseAskOf(p)
|
|
if want := []link.PullRef{{Owner: "novox", Repo: "shop", Number: 7}, {Owner: "novox", Repo: "web", Number: 3}}; !reflect.DeepEqual(asked.Pulls, want) {
|
|
t.Fatalf("the walk names %+v", asked.Pulls)
|
|
}
|
|
walk := withReuse(t.Context(), asked)
|
|
if reuseAsked(walk, false) != asked {
|
|
t.Fatal("a walk's ask does not carry its leave")
|
|
}
|
|
if reuseAsked(walk, true) != nil {
|
|
t.Fatal("a dry run carries a leave to take a check's build")
|
|
}
|
|
if reuseAsked(t.Context(), false) != nil {
|
|
t.Fatal("an ask that is not a walk's carries a leave")
|
|
}
|
|
}
|
|
|
|
func TestAReusedCheckBuildIsRegisteredByItsDigestAndGatedAsABuiltOne(t *testing.T) {
|
|
withTheGate(t) // the first-machine gate's own path (novox/hq ADR 0360 keeps it for earlier walks)
|
|
g := aGateMesh(t)
|
|
ctx := t.Context()
|
|
inv := g.open.inventory
|
|
gateEvery = 0
|
|
|
|
digest := "sha256:" + strings.Repeat("c", 64)
|
|
reused := func(id, reference string) link.BuildResult {
|
|
manifest := mustJSON(t, catalogue.Manifest{Module: "app", Version: "c3", Resources: []map[string]any{
|
|
{"id": "svc", "type": "container", "name": "app", "image": reference}}})
|
|
return link.BuildResult{ID: id, Repository: "novox/mesh-catalog", Path: "modules/app", Ref: "main", On: "anchor",
|
|
Commit: "c3", Manifest: manifest, Trunk: "main", OnTrunk: true, Branches: []string{"main"},
|
|
Made: []link.MadeArtifact{{Name: "server", Kind: "image", Reference: reference}},
|
|
Source: &link.SourceOnSeat{Seat: "git", Repository: "novox/mesh-catalog"},
|
|
Reused: "reused from the check of novox/mesh-catalog#9 at head abcdefabcdef (merged into trunk 123456123456): server " + digest,
|
|
ReusedFrom: &link.ReusedFrom{Pull: link.PullRef{Owner: "novox", Repo: "mesh-catalog", Number: 9},
|
|
Head: "abcdefabcdef", Trunk: "123456123456", Key: "r1:" + strings.Repeat("1", 64)}}
|
|
}
|
|
if _, _, err := takeIn(ctx, inv, reused(link.NewBuildID(time.Now()), "store.internal:5000/scratch/app/server@"+digest)); err == nil ||
|
|
!strings.Contains(err.Error(), "scratch") {
|
|
t.Fatalf("a build in the scratch namespace was registered: %v", err)
|
|
}
|
|
id := link.NewBuildID(time.Now().Add(time.Second))
|
|
result := reused(id, "store.internal:5000/app/server@"+digest)
|
|
if _, _, err := takeIn(ctx, inv, result); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
current, err := inv.CurrentBuilds(ctx)
|
|
if err != nil || current["app"].Commit != "c3" {
|
|
t.Fatalf("the reused build is not what app is registered at: %+v %v", current["app"], err)
|
|
}
|
|
shelf, err := inv.Catalogue(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, _ := json.Marshal(shelf["app"].Resources)
|
|
if !strings.Contains(string(raw), "app/server@"+digest) {
|
|
t.Fatalf("app is registered as %s, not by the check's digest in its own namespace", raw)
|
|
}
|
|
|
|
// The walk asked it: the walk keeps what its build did, and its gate judges the registered build.
|
|
asked := time.Now().UTC()
|
|
p := g.plan(t)
|
|
p.Commit = "c3"
|
|
p.Modules["app"] = &inventory.PlanModule{State: "asked", AskedAt: &asked, Build: id}
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
planBuiltSaying(ctx, g.open, "app", "c3", "", asked, id, result.MadeWords())
|
|
p = g.plan(t)
|
|
if m := p.Modules["app"]; m.State != "built" || !strings.HasPrefix(m.Made, "reused from the check of novox/mesh-catalog#9") {
|
|
t.Fatalf("the walk keeps %+v", m)
|
|
}
|
|
for i := 0; i < 6; i++ {
|
|
advancePlans(ctx, g.open)
|
|
}
|
|
p = g.plan(t)
|
|
gate := p.Modules["app"].Gate
|
|
if gate == nil || gate.To != "c3" || gate.Verdict != inventory.GatePassed {
|
|
t.Fatalf("the gate judged %+v, not the reused build", gate)
|
|
}
|
|
if sent, _, _ := inv.SentBuilds(ctx, "anchor"); sent["app"] != "c3" {
|
|
t.Fatalf("the first machine was sent %v, not the reused build", sent)
|
|
}
|
|
}
|