The controller asks no build of anybody (ADR 0501 §5, ADR 0525 clause 6, ADR 0503 §3). Every module of a walk is taken from the builder's done key; a key not done yet waits, named in the plan, and never fails it. - C2b/C2c: internal/builder and cmd/mesh-controller's asks go (askABuild, onlyTheBuildersOwn, buildOneAsked, takeIn from an outcome, buildAgentsOwn, the builder's say and its fallback, the daemon hearing an outcome). The server follows the retired seats' built subjects only to let go of them, because the installer's carried user list names them. - C2d: replay, queue, cancel, clear, kill, pause, resume, delivery-check, check-here and merge-gate are refused by name. - C3: the check queues (CHECKS_READY, CHECKS_OTHER) and their workers, the checks-running and plans-building buckets and their grants, the build queue and its hold (plans_building.go, queue.go, link/holds.go, builds_nats.go, checks_nats.go). - C4: merge_gate*.go, the pull request's repo-check path, the Checked event and its layers; a pull request asks the controller nothing but to tell mesh-config what its head declares. - C5: the builds bucket is written only by key_takein. - C10 (help and refusals): the terminal's help lists only what is served. Integration tests of the plan's tiers, sends, stops and retries now run on a stand-in builder with a done key for every module (walk_keys_scaffold_integration_test.go); the tests of the asks, the queue, the merge gate and the replays are deleted.
110 lines
3.4 KiB
Go
110 lines
3.4 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/testbus"
|
|
)
|
|
|
|
// builderOnTheBus is the builder's and the indexer's buckets on a test's own bus, which the controller's connection for
|
|
// the moment (servingBus) reaches: what a take-in from a key reads (R4e, issue 1851).
|
|
type builderOnTheBus struct {
|
|
js *broker.JetStream
|
|
builds, modules, manifests jetstream.KeyValue
|
|
}
|
|
|
|
func aBuilderOnTheBus(t *testing.T) builderOnTheBus {
|
|
t.Helper()
|
|
js, err := broker.Dial(testbus.URL(t))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(js.Close)
|
|
api, err := jetstream.New(js.Conn())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := t.Context()
|
|
b := builderOnTheBus{js: js}
|
|
for _, c := range []struct {
|
|
into *jetstream.KeyValue
|
|
bucket string
|
|
history uint8
|
|
}{
|
|
{&b.builds, sdkdelivery.BuilderBuildsBucket, sdkdelivery.BuilderBuildsHistory},
|
|
{&b.modules, sdkdelivery.ModulesBucket, sdkdelivery.ModulesHistory},
|
|
{&b.manifests, sdkdelivery.ManifestsBucket, 1},
|
|
} {
|
|
kv, err := api.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: c.bucket, History: c.history})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
*c.into = kv
|
|
}
|
|
servingBus.Store(js)
|
|
t.Cleanup(func() { servingBus.Store(nil) })
|
|
withTrunkList(t, true)
|
|
// The indexer on this bus is read, not the "not held" a mesh with no bus reads (aMeshOnTheStore).
|
|
wasIndexed := indexedModule
|
|
indexedModule = theIndexedModule
|
|
t.Cleanup(func() { indexedModule = wasIndexed })
|
|
return b
|
|
}
|
|
|
|
// indexed writes the indexer's trunk value of module at commit, naming fp, and its manifest: a module of one archive.
|
|
func (b builderOnTheBus) indexed(t *testing.T, module, version, repository, path, commit, fp string) string {
|
|
t.Helper()
|
|
keys, trunk := aKeyFor(module, version, fp, repository, path, commit)
|
|
raw := keys.manifests[trunk.Manifest]
|
|
value, err := sdkdelivery.EncodeManifest(sdkdelivery.Manifest{Module: module, JSON: raw})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := b.manifests.Put(context.Background(), trunk.Manifest, value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
trunk.FP = "src1:" + fp[len("src2:"):]
|
|
encoded, err := sdkdelivery.EncodeModule(trunk)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := b.modules.Put(context.Background(), module, encoded); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return trunk.Manifest
|
|
}
|
|
|
|
// built writes the builder's key of module at fp: done, its one archive named with a reference, or in another state.
|
|
func (b builderOnTheBus) built(t *testing.T, module, version, fp, manifest, state string) {
|
|
t.Helper()
|
|
keys, _ := aKeyFor(module, version, fp, "", "", "")
|
|
v := keys.keys[module].Build
|
|
v.Manifest = manifest
|
|
if state != sdkdelivery.BuildDone {
|
|
v = sdkdelivery.BuilderBuild{State: state, By: "ace"}
|
|
if state == sdkdelivery.BuildFailed {
|
|
v.Error = "digests differ: ace sha256:1, g14 sha256:2"
|
|
}
|
|
}
|
|
value, err := sdkdelivery.EncodeBuilderBuild(v)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
key, err := sdkdelivery.BuilderBuildKey(module, fp)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := b.builds.Put(context.Background(), key, value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// theIndexedModule is the look at the indexer as the controller makes it, kept before any test replaces it.
|
|
var theIndexedModule = indexedModule
|