//go:build integration package main import ( "context" "encoding/json" "errors" "fmt" "os" "os/exec" "slices" "strings" "testing" "time" "git.novox.be/novox/mesh-sdk/go/asks" "github.com/novox/mesh-controller/internal/inventory" "github.com/novox/mesh-controller/internal/link" ) func theCatalogue(t *testing.T) *stores { t.Helper() open := aMesh(t) ctx := t.Context() for _, b := range []link.BuildResult{ onTrunk("build-sudo", "novox/mesh-catalog", "git", "modules/sudo", map[string]any{"module": "sudo", "version": "1"}), onTrunk("build-host", "novox/mesh-host", "git", "", map[string]any{"module": "mesh-host", "version": "1"}), } { keptAsked(t, open.inventory, b.ID, b.Source.Repository, b.Path, true) if _, _, err := takeIn(ctx, open.inventory, b); err != nil { t.Fatal(err) } } return open } func TestABuildFromAnAgentsRepositoryIsNotRegisteredAsAModuleTheMeshHolds(t *testing.T) { open := theCatalogue(t) ctx := t.Context() for _, c := range []struct { name, repository, path, module string }{ {"its own repository naming sudo", "agent/sudo", "modules/sudo", "sudo"}, {"a fork of the catalogue", "agent/mesh-catalog", "modules/sudo", "sudo"}, {"a fork of the node-engine", "agent/mesh-host", "", "mesh-host"}, } { t.Run(c.name, func(t *testing.T) { id := "build-" + strings.ReplaceAll(c.repository, "/", "-") keptAsked(t, open.inventory, id, c.repository, c.path, false) // through the build verb evil := onTrunk(id, c.repository, "git", c.path, map[string]any{"module": c.module, "version": "evil"}) _, _, err := takeIn(ctx, open.inventory, evil) if !errors.Is(err, errNotItsSource) { t.Fatalf("a build of %s was taken in as %s: %v", c.repository, c.module, err) } shelf, err := open.inventory.Catalogue(ctx) if err != nil { t.Fatal(err) } if got := shelf[c.module].Version; got != "1" { t.Fatalf("%s is now %q, from %s", c.module, got, c.repository) } if _, found, _ := open.inventory.BuildByID(ctx, id); !found { t.Errorf("the refused build %s is not recorded", id) } }) } } func TestANewModuleFromARepositoryTheCatalogueDoesNotBuildFromIsNotRegistered(t *testing.T) { open := theCatalogue(t) ctx := t.Context() keptAsked(t, open.inventory, "build-new", "agent/tools", "", false) _, _, err := takeIn(ctx, open.inventory, onTrunk("build-new", "agent/tools", "git", "", map[string]any{"module": "agent-tools", "version": "1"})) if !errors.Is(err, errNotItsSource) { t.Fatalf("a new module from an agent's repository was taken in: %v", err) } // And one asked of nobody here — an outcome on the bus no request was kept for — the same. _, _, err = takeIn(ctx, open.inventory, onTrunk("build-unasked", "agent/tools", "git", "", map[string]any{"module": "agent-tools", "version": "1"})) if !errors.Is(err, errNotItsSource) { t.Fatalf("an outcome nobody asked for was taken in: %v", err) } if shelf, _ := open.inventory.Catalogue(ctx); shelf["agent-tools"].Module != "" { t.Fatal("the refused module is in the catalogue") } } func TestAtTheTerminalAnotherRepositoryIsRegistered(t *testing.T) { open := theCatalogue(t) ctx := t.Context() keptAsked(t, open.inventory, "build-moved", "novox/sudo", "", true) if _, _, err := takeIn(ctx, open.inventory, onTrunk("build-moved", "novox/sudo", "git", "", map[string]any{"module": "sudo", "version": "2"})); err != nil { t.Fatalf("a move the operator asked for at the terminal was refused: %v", err) } if src, _ := open.inventory.SourceOf(ctx, "sudo"); src.Repository != "novox/sudo" { t.Fatalf("sudo is built from %q", src.Repository) } if err := open.inventory.RecordBuildRequest(ctx, inventory.BuildRequest{ID: "build-external", Repository: "http://forge.internal:20000/someone/app.git", For: "build", AtTerminal: true}); err != nil { t.Fatal(err) } if _, _, err := takeIn(ctx, open.inventory, onTrunk("build-external", "someone/app", "", "", map[string]any{"module": "app", "version": "1"})); err != nil { t.Fatalf("a new module the operator asked for at the terminal was refused: %v", err) } } func TestADeliveryFromTheRegisteredRepositoryIsRegistered(t *testing.T) { open := theCatalogue(t) ctx := t.Context() rebuilt := onTrunk("build-plan", "novox/mesh-catalog", "git", "modules/sudo", map[string]any{"module": "sudo", "version": "2"}) if err := open.inventory.RecordBuildRequest(ctx, inventory.BuildRequest{ID: rebuilt.ID, Repository: "novox/mesh-catalog", Seat: "git", Path: "modules/sudo", For: "plan"}); err != nil { t.Fatal(err) } if _, _, err := takeIn(ctx, open.inventory, rebuilt); err != nil { t.Fatalf("a plan's build of the module's own repository was refused: %v", err) } added := onTrunk("build-merge", "novox/mesh-catalog", "git", "modules/zram", map[string]any{"module": "zram", "version": "1"}) if _, _, err := takeIn(ctx, open.inventory, added); err != nil { t.Fatalf("a module a merge added to the catalogue repository was refused: %v", err) } shelf, _ := open.inventory.Catalogue(ctx) if shelf["sudo"].Version != "2" || shelf["zram"].Module == "" { t.Fatalf("not registered: sudo %q, zram %q", shelf["sudo"].Version, shelf["zram"].Module) } } func TestATrunkTheForgeDoesNotProtectRegistersNothing(t *testing.T) { open := theCatalogue(t) ctx := t.Context() theForge.Store("novox/unguarded", forgeFacts{ID: 7, Why: "the rule main lets a person push to main directly"}) t.Cleanup(func() { theForge.Delete("novox/unguarded") }) first := onTrunk("build-unguarded-1", "novox/unguarded", "git", "", map[string]any{"module": "unguarded", "version": "1"}) keptAsked(t, open.inventory, first.ID, "novox/unguarded", "", true) if _, _, err := takeIn(ctx, open.inventory, first); err != nil { t.Fatalf("at the terminal: %v", err) } again := onTrunk("build-unguarded-2", "novox/unguarded", "git", "", map[string]any{"module": "unguarded", "version": "2"}) if _, _, err := takeIn(ctx, open.inventory, again); !errors.Is(err, errNotItsSource) || !strings.Contains(err.Error(), "push to main directly") { t.Fatalf("a rebuild from an unprotected trunk was taken in: %v", err) } theForge.Store("novox/unguarded", errors.New("nothing serves gitea.gitea_api")) if _, _, err := takeIn(ctx, open.inventory, onTrunk("build-unguarded-3", "novox/unguarded", "git", "", map[string]any{"module": "unguarded", "version": "3"})); !errors.Is(err, errNotItsSource) { t.Fatalf("a forge that could not say was read as a protected trunk: %v", err) } if shelf, _ := open.inventory.Catalogue(ctx); shelf["unguarded"].Version != "1" { t.Fatalf("unguarded is %q", shelf["unguarded"].Version) } } func TestARepositoryMadeAgainUnderItsNameIsNotTheModulesSource(t *testing.T) { open := theCatalogue(t) ctx := t.Context() theForge.Store("novox/remade", forgeFacts{ID: 100, Guarded: true}) t.Cleanup(func() { theForge.Delete("novox/remade") }) first := onTrunk("build-remade-1", "novox/remade", "git", "", map[string]any{"module": "remade", "version": "1"}) keptAsked(t, open.inventory, first.ID, "novox/remade", "", true) if _, _, err := takeIn(ctx, open.inventory, first); err != nil { t.Fatal(err) } if id, _ := open.inventory.SourceIdentity(ctx, "remade"); id != 100 { t.Fatalf("the forge's id was not recorded: %d", id) } theForge.Store("novox/remade", forgeFacts{ID: 101, Guarded: true}) // deleted, and made again by an agent if _, _, err := takeIn(ctx, open.inventory, onTrunk("build-remade-2", "novox/remade", "git", "", map[string]any{"module": "remade", "version": "evil"})); !errors.Is(err, errNotItsSource) || !strings.Contains(err.Error(), "made again") { t.Fatalf("a repository made again under the name was taken in: %v", err) } // And a new module from it, beside the one registered from the first, the same. if _, _, err := takeIn(ctx, open.inventory, onTrunk("build-remade-3", "novox/remade", "git", "modules/other", map[string]any{"module": "other", "version": "1"})); !errors.Is(err, errNotItsSource) { t.Fatalf("a new module from a repository made again was taken in: %v", err) } } func TestATerminalRequestCoversOnlyWhatItAsked(t *testing.T) { open := theCatalogue(t) ctx := t.Context() if err := open.inventory.RecordBuildRequest(ctx, inventory.BuildRequest{ID: "build-asked", Repository: "novox/app", Seat: "git", Path: "modules/app", For: "build", AtTerminal: true}); err != nil { t.Fatal(err) } other := onTrunk("build-asked", "agent/sudo", "git", "modules/app", map[string]any{"module": "sudo", "version": "evil"}) if _, _, err := takeIn(ctx, open.inventory, other); !errors.Is(err, errNotItsSource) { t.Fatalf("an outcome of another repository under a terminal request's id was taken in: %v", err) } elsewhere := onTrunk("build-asked", "novox/app", "git", "modules/sudo", map[string]any{"module": "sudo", "version": "evil"}) if _, _, err := takeIn(ctx, open.inventory, elsewhere); !errors.Is(err, errNotItsSource) { t.Fatalf("an outcome of another path under a terminal request's id was taken in: %v", err) } } func TestTheServingControllerIsNeverTheTerminal(t *testing.T) { t.Setenv(verbVar, "") t.Setenv(link.CallerVar, "") t.Setenv(servedVar, "") if !startedAtTheTerminal() { t.Fatal("a process started by hand is not the terminal") } markServed() if startedAtTheTerminal() { t.Fatal("the serving controller reads as the terminal") } child := exec.Command(os.Args[0], "-test.run=^$") child.Env = os.Environ() if !slices.Contains(child.Env, servedVar+"=1") { t.Fatal("what the serving controller starts does not carry its mark") } } func TestAnUnknownIdentityKeepsTheRecordedOne(t *testing.T) { open := theCatalogue(t) ctx := t.Context() if err := open.inventory.SetSourceIdentity(ctx, "sudo", 100); err != nil { t.Fatal(err) } if err := open.inventory.SetSourceIdentity(ctx, "sudo", 0); err != nil { t.Fatal(err) } if id, _ := open.inventory.SourceIdentity(ctx, "sudo"); id != 100 { t.Fatalf("the recorded id became %d", id) } } func TestAModuleMovesOnTheOperatorsApproveOfTheMergeThatMovedIt(t *testing.T) { const commit = "c0ffee0123456789" for _, c := range []struct { what string change func(*anApprovedMerge) unkept bool request string // who asked: "merge", or "build" through a verb moved bool }{ {what: "the operator's Approve of the merged head", request: "merge", moved: true}, {what: "no merge mesh-delivery announced", unkept: true, request: "merge"}, {what: "a warrant for other heads", request: "merge", change: func(a *anApprovedMerge) { a.merge.Heads = map[string]string{"novox/mesh-host@aaaaaaaaaaaa": "e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5"} }}, {what: "a Decline", request: "merge", change: func(a *anApprovedMerge) { a.warrant.Option, a.warrant.Label, a.merge.Option = "decline", "Decline", "decline" }}, {what: "a person who is not the operator", request: "merge", change: func(a *anApprovedMerge) { a.warrant.By.Who = "agent" }}, {what: "a build asked through a verb", request: "build"}, } { open := theCatalogue(t) ctx := t.Context() inv := open.inventory a := approvedMerge(t) a.merge.Owner, a.merge.Repo, a.merge.Number, a.merge.HeadSHA = "novox", "mesh-host", 7, "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1" if c.change != nil { c.change(&a) } wasKept, wasAsk := keptDeliveryMerge, routerAskOf keptDeliveryMerge = func(_ context.Context, owner, repo string, number int, head string) (deliveryMerge, bool, error) { return a.merge, !c.unkept && owner == "novox" && repo == "mesh-host" && number == 7 && head == a.merge.HeadSHA, nil } routerAskOf = func(_ context.Context, _ catalogueReader, _, id string) (*asks.Ask, *asks.Warrant, error) { if id != a.merge.AskID { t.Errorf("%s: the router was asked for %q", c.what, id) } return &a.ask, &a.warrant, nil } t.Cleanup(func() { keptDeliveryMerge, routerAskOf = wasKept, wasAsk }) event, _ := json.Marshal(map[string]any{"owner": "novox", "repo": "mesh-host", "base": "main", "number": 7, "head_sha": a.merge.HeadSHA, "merge_commit_sha": commit}) var forgeMerge keptMerge _ = json.Unmarshal(event, &forgeMerge) wasForge := keptForgeMerge t.Cleanup(func() { keptForgeMerge = wasForge }) keptForgeMerge = func(context.Context, string, string, string) (keptMerge, bool, error) { return forgeMerge, true, nil } id := fmt.Sprintf("build-%d", time.Now().Add(time.Hour).UnixNano()) if err := inv.RecordBuildRequest(ctx, inventory.BuildRequest{ID: id, Repository: "novox/mesh-host", Seat: "git", Path: "modules/sudo", Ref: "main", Commit: commit, For: c.request}); err != nil { t.Fatal(err) } moved := onTrunk(id, "novox/mesh-host", "git", "modules/sudo", map[string]any{"module": "sudo", "version": "2"}) moved.Commit = commit _, _, err := takeIn(ctx, inv, moved) src, _ := inv.SourceOf(ctx, "sudo") switch { case c.moved && err != nil: t.Errorf("%s: the move was refused: %v", c.what, err) case c.moved && src.Repository != "novox/mesh-host": t.Errorf("%s: sudo is built from %q", c.what, src.Repository) case !c.moved && !errors.Is(err, errNotItsSource): t.Errorf("%s: the move was not refused as ADR 0266 has it: %v", c.what, err) case !c.moved && src.Repository != "novox/mesh-catalog": t.Errorf("%s: a refused move changed sudo's source to %q", c.what, src.Repository) } } }