Answer review round 1: fresh is only what a take-in newly wrote, a merge keeps the verdict, the check compares with the trunk (ADR 0578, 0579)
Issue 1585, R1: fresh holds the digests a take-in newly wrote (a new module, a changed manifest); a registered or taken-in module is judged too; a start pass that fails is judged again at the next message heard, no timer. R2: a module's verdict, problems and warnings are carried while its digest stands and are no part of the compare. R3: the checker judges the trunk beside the change and fails on every problem the change case adds, an untouched manifest's included. R4: the judge reads the indexer's kept predefined keys, or the catalogue member's when it changes them. A log line names a package no held module publishes. Every module pins mesh-sdk 62cddf4. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -3,7 +3,7 @@ module mesh-delivery-assigner
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-builder
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -31,7 +33,31 @@ type judgeDeps struct {
|
||||
compositions check.CompositionReader
|
||||
// nodes names every node with a record; nil hands no names.
|
||||
nodes *nodeNames
|
||||
logf func(format string, args ...any)
|
||||
// predefined is the indexer's kept list of predefined keys; nil reads none.
|
||||
predefined check.PredefinedList
|
||||
logf func(format string, args ...any)
|
||||
}
|
||||
|
||||
// keptPredefined reads the indexer's key predefined.list (delivery.PredefinedKept), bound once its state appears.
|
||||
type keptPredefined struct{ b *process.AwaitedBucket }
|
||||
|
||||
func (k keptPredefined) PredefinedList(ctx context.Context) (json.RawMessage, error) {
|
||||
kv := k.b.KV()
|
||||
if kv == nil {
|
||||
return nil, process.ErrNotYet
|
||||
}
|
||||
e, err := kv.Get(ctx, delivery.PredefinedListKey)
|
||||
if errors.Is(err, jetstream.ErrKeyNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var kept delivery.PredefinedKept
|
||||
if err := json.Unmarshal(e.Value(), &kept); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kept.List, nil
|
||||
}
|
||||
|
||||
// nodeNames reads every node's name from the node-engine's have, one key `<node>.node` per node with a record (novox/hq
|
||||
@@ -69,7 +95,7 @@ func newJudge(d judgeDeps) check.Judge {
|
||||
nodes = d.nodes
|
||||
}
|
||||
return &check.Examiner{Nodes: nodes, Compositions: d.compositions, Asks: d.asks, Toolchains: d.tools,
|
||||
Kept: check.Kept{Store: d.kept}, Previews: d.previews, Modules: d.repos, Packages: d.repos, Published: d.repos, Forge: d.forge, Runs: d.repos, Builds: d.builds, Announce: d.announce, Trunks: d.trunks, Manifests: d.repos, Logf: d.logf}
|
||||
Kept: check.Kept{Store: d.kept}, Previews: d.previews, Modules: d.repos, Packages: d.repos, Published: d.repos, Forge: d.forge, Runs: d.repos, Builds: d.builds, Announce: d.announce, Trunks: d.trunks, Manifests: d.repos, Predefined: d.predefined, Logf: d.logf}
|
||||
}
|
||||
|
||||
// manifestKV reads a manifest by its digest.
|
||||
|
||||
@@ -202,6 +202,8 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
repos: repos, builds: builds, forge: forgeReads{call: caller.Call}, logf: logger.Printf,
|
||||
announce: announce, compositions: compositions,
|
||||
nodes: openNodeNames(ctx, js, logger.Printf),
|
||||
predefined: keptPredefined{process.AwaitBucket(ctx, js, conn, delivery.IndexerModule+"_"+delivery.IndexerPredefinedState,
|
||||
"a change's manifests are judged with no predefined keys, each fallback as its value declares it", logger.Printf)},
|
||||
})
|
||||
ch.Announce = announce
|
||||
tryer.Judge = ch.Judge
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-checker
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -930,6 +930,13 @@ func TestASecondCheckOfTheSameHeadsKeepsWhatTheFirstPassed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// keptList is the indexer's kept predefined list as a test gives it.
|
||||
type keptList string
|
||||
|
||||
func (k keptList) PredefinedList(context.Context) (json.RawMessage, error) {
|
||||
return json.RawMessage(k), nil
|
||||
}
|
||||
|
||||
// fixedDigests are the indexer's manifest digests as a test gives them.
|
||||
type fixedDigests map[string]string
|
||||
|
||||
@@ -944,16 +951,20 @@ func TestTheIndexersJudgeJudgesTheChangesManifests(t *testing.T) {
|
||||
name string
|
||||
refused string
|
||||
fails string
|
||||
// untouched is the judge's refusal of mail, which the change leaves as it is: a warning, never a failure (ADR 0579 §2)
|
||||
untouched string
|
||||
// untouched is the judge's refusal of mail, which the change leaves as it is, and trunkMail its refusal on the trunk:
|
||||
// a problem the trunk had is a warning, one the change causes fails (ADR 0579 §2)
|
||||
untouched, trunkMail string
|
||||
}{
|
||||
{name: "accepted"},
|
||||
{name: "an untouched manifest's problem", untouched: "mail says no credential form"},
|
||||
{name: "an untouched manifest's problem the trunk had", untouched: "mail says no credential form", trunkMail: "mail says no credential form"},
|
||||
{name: "a problem the change causes in an untouched manifest", untouched: "mail reads a state web no longer keeps",
|
||||
fails: "refuses the manifest of mail: mail reads a state web no longer keeps"},
|
||||
{name: "refused", refused: "web requires \"amqp\"\nweb has no id", fails: "the indexer's judge at mesh-delivery's trunk " + strings.Repeat("d", 40) + ` refuses the manifest of web: web requires "amqp"; web has no id`},
|
||||
} {
|
||||
b := newBench(t)
|
||||
b.ex.Manifests = fixedDigests{"mail": strings.Repeat("a", 64), "web": strings.Repeat("b", 64)}
|
||||
b.ex.Trunks = fixedTrunks{heads: map[string]string{DeliveryRepository: trunk}}
|
||||
b.ex.Predefined = keptList(`{"font-size": {"type": "number", "description": "the size"}}`)
|
||||
var judged []delivery.ComposeJob
|
||||
answer := b.asks.Answer
|
||||
b.asks.Answer = func(a delivery.StepAsk) delivery.Step {
|
||||
@@ -963,7 +974,8 @@ func TestTheIndexersJudgeJudgesTheChangesManifests(t *testing.T) {
|
||||
judged = append(judged, *a.Compose)
|
||||
read := composer.ManifestRead{Accepted: row.refused == "", Refused: row.refused}
|
||||
verdict, _ := json.Marshal(composer.Verdict{V: composer.Version, SDK: "exe:1", Cases: []composer.CaseVerdict{{Name: JudgeCase,
|
||||
Manifests: map[string]composer.ManifestRead{"web": read, "mail": {Accepted: row.untouched == "", Refused: row.untouched}}}}})
|
||||
Manifests: map[string]composer.ManifestRead{"web": read, "mail": {Accepted: row.untouched == "", Refused: row.untouched}}},
|
||||
{Name: JudgeTrunk, Manifests: map[string]composer.ManifestRead{"web": {Accepted: true}, "mail": {Accepted: row.trunkMail == "", Refused: row.trunkMail}}}}})
|
||||
result, _ := json.Marshal(delivery.ComposeAnswer{Key: "k", Verdict: verdict})
|
||||
return delivery.Step{ID: a.ID, State: delivery.StepPassed, Result: result}
|
||||
}
|
||||
@@ -977,6 +989,8 @@ func TestTheIndexersJudgeJudgesTheChangesManifests(t *testing.T) {
|
||||
}
|
||||
var req composer.Request
|
||||
if err := json.Unmarshal(judged[0].Request, &req); err != nil || req.Cases[0].Manifests["web"].Digest != web ||
|
||||
req.Cases[1].Name != JudgeTrunk || req.Cases[1].Manifests["web"].Digest != strings.Repeat("b", 64) ||
|
||||
req.Predefined["font-size"].Type != "number" ||
|
||||
req.Cases[0].Manifests["mail"].Digest != strings.Repeat("a", 64) {
|
||||
t.Fatalf("%s: the request %+v: %v", row.name, req, err)
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ type Examiner struct {
|
||||
// Manifests are the indexer's manifest digests by module: the catalogue a change's manifests are judged in by the
|
||||
// indexer's judge (manifests_judge.go, novox/hq ADR 0578 §2); nil judges no manifest.
|
||||
Manifests TrunkManifests
|
||||
// Predefined reads the catalogue's predefined keys the indexer keeps (manifests_judge.go); nil reads none.
|
||||
Predefined PredefinedList
|
||||
// Compositions answers the assigner's composition check of a check by the check's key (delivery.CompositionKey),
|
||||
// waiting until the assigner wrote a verdict that does not wait, or ctx ends (ADR 0528 clause 5, issue 1297); nil
|
||||
// leaves the composition not run.
|
||||
@@ -225,6 +227,8 @@ type state struct {
|
||||
// judgeHead is the group's mesh-delivery member head when its merge changes the judge (ADR 0578 §2); empty judges
|
||||
// with mesh-delivery's trunk.
|
||||
judgeHead string
|
||||
// predefinedHead is the catalogue member's head when its merge changes predefined.json: the list is read there.
|
||||
predefinedHead string
|
||||
}
|
||||
|
||||
// Judge runs the case (it is the Judge of a Checker). A failure of the change, of a merge or of a step is a verdict; an error is only a case that cannot
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/composer"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
@@ -25,8 +26,10 @@ const (
|
||||
DeliveryRepository = "novox/mesh-delivery"
|
||||
JudgeDir = "modules/mesh-delivery-indexer"
|
||||
JudgePackage = "mesh-delivery-indexer/cmd/mesh-judge"
|
||||
// JudgeCase is the one case a judge request holds: the catalogue as the change leaves it.
|
||||
JudgeCase = "change"
|
||||
// JudgeCase is the case of a judge request holding the catalogue as the change leaves it, and JudgeTrunk the one
|
||||
// holding it as the trunk holds it: a problem the change case has and the trunk case lacks is the change's (ADR 0579 §2).
|
||||
JudgeCase = "change"
|
||||
JudgeTrunk = "trunk"
|
||||
// judgeBetween is how the judge names the problems between manifests that no one module's removal ends.
|
||||
judgeBetween = "(between manifests)"
|
||||
)
|
||||
@@ -57,14 +60,21 @@ type TrunkManifests interface {
|
||||
ManifestDigests() map[string]string
|
||||
}
|
||||
|
||||
// PredefinedList is the catalogue's list of predefined keys the indexer keeps (its state predefined, key list), the one a
|
||||
// config value falling back to a key is judged against (ADR 0348 §7); nil when it keeps none.
|
||||
type PredefinedList interface {
|
||||
PredefinedList(ctx context.Context) (json.RawMessage, error)
|
||||
}
|
||||
|
||||
// judgeRequest is the judge's request over the catalogue as the case leaves it: every trunk manifest by its digest, each
|
||||
// one a pull request touches replaced by the digest its candidate names; touched are the modules whose manifest the
|
||||
// change adds or changes (a digest the trunk does not hold for it), sorted (novox/hq ADR 0579 §2).
|
||||
func judgeRequest(trunk map[string]string, pulls []Pull) (req composer.Request, touched []string) {
|
||||
manifests := map[string]composer.Manifest{}
|
||||
manifests, before := map[string]composer.Manifest{}, map[string]composer.Manifest{}
|
||||
for module, digest := range trunk {
|
||||
if digest != "" {
|
||||
manifests[module] = composer.Manifest{Digest: digest}
|
||||
before[module] = composer.Manifest{Digest: digest}
|
||||
}
|
||||
}
|
||||
seen := map[string]bool{}
|
||||
@@ -79,8 +89,8 @@ func judgeRequest(trunk map[string]string, pulls []Pull) (req composer.Request,
|
||||
}
|
||||
}
|
||||
}
|
||||
return composer.Request{V: composer.Version, Cases: []composer.Case{{Name: JudgeCase, Manifests: manifests}}},
|
||||
slices.Sorted(maps.Keys(seen))
|
||||
return composer.Request{V: composer.Version, Cases: []composer.Case{{Name: JudgeCase, Manifests: manifests},
|
||||
{Name: JudgeTrunk, Manifests: before}}}, slices.Sorted(maps.Keys(seen))
|
||||
}
|
||||
|
||||
// judgeManifests runs the indexer's judge over the case's manifests and fails the check for each touched manifest it
|
||||
@@ -104,6 +114,12 @@ func (st *state) judgeManifests(ctx context.Context) *delivery.Verdict {
|
||||
if commit == "" {
|
||||
return fail(goModule, "the change's manifests cannot be judged: the trunk head of "+DeliveryRepository+" is not known")
|
||||
}
|
||||
// The list of predefined keys the manifests are judged against (ADR 0578 §2): the catalogue member's predefined.json
|
||||
// when the change alters it, else the one the indexer keeps.
|
||||
if list, from := st.predefinedList(ctx); list != nil {
|
||||
req.Predefined = list
|
||||
st.c.note("the manifests are judged against the predefined keys of " + from)
|
||||
}
|
||||
raw, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return fail(goModule, err.Error())
|
||||
@@ -121,32 +137,45 @@ func (st *state) judgeManifests(ctx context.Context) *delivery.Verdict {
|
||||
if err != nil {
|
||||
return fail(goModule, "the judge of the change's manifests: "+err.Error())
|
||||
}
|
||||
cv, why := judgeAnswer(step)
|
||||
cv, trunkCase, why := judgeAnswer(step)
|
||||
if why != "" {
|
||||
return fail(goModule, fmt.Sprintf("the indexer's judge at %s did not judge the change's manifests: %s", at, why))
|
||||
}
|
||||
// Only a new or changed manifest is refused (ADR 0579 §2); one the change leaves as it is is named as a warning, never
|
||||
// a failure: it is not refused for a rule it already broke.
|
||||
// A new or changed manifest is judged in full; of one the change leaves as it is, a problem the trunk already had is a
|
||||
// warning (it is not refused for a rule it already broke), and a problem the change causes in it, which the trunk case
|
||||
// lacks, fails the check as the change's (ADR 0579 §2).
|
||||
var refused, warned []string
|
||||
for _, module := range slices.Sorted(maps.Keys(cv.Manifests)) {
|
||||
r := cv.Manifests[module]
|
||||
if r.Accepted || module == judgeBetween {
|
||||
if r.Accepted || r.Refused == "" {
|
||||
continue
|
||||
}
|
||||
words := strings.ReplaceAll(r.Refused, "\n", "; ")
|
||||
if slices.Contains(touched, module) {
|
||||
refused = append(refused, fmt.Sprintf("the indexer's judge at %s refuses the manifest of %s: %s", at, module, words))
|
||||
} else {
|
||||
warned = append(warned, module+": "+words)
|
||||
had := map[string]bool{}
|
||||
for _, p := range strings.Split(trunkCase.Manifests[module].Refused, "\n") {
|
||||
had[p] = true
|
||||
}
|
||||
var caused, old []string
|
||||
for _, p := range strings.Split(r.Refused, "\n") {
|
||||
if slices.Contains(touched, module) || !had[p] {
|
||||
caused = append(caused, p)
|
||||
} else {
|
||||
old = append(old, p)
|
||||
}
|
||||
}
|
||||
if len(caused) > 0 {
|
||||
what := "the manifest of " + module
|
||||
if module == judgeBetween {
|
||||
what = "the catalogue"
|
||||
}
|
||||
refused = append(refused, fmt.Sprintf("the indexer's judge at %s refuses %s: %s", at, what, strings.Join(caused, "; ")))
|
||||
}
|
||||
if len(old) > 0 {
|
||||
warned = append(warned, module+": "+strings.Join(old, "; "))
|
||||
}
|
||||
}
|
||||
if len(warned) > 0 {
|
||||
st.c.note("warnings of the indexer's judge on manifests the change leaves as they are (ADR 0579 §2): " + strings.Join(warned, " | "))
|
||||
}
|
||||
if between := cv.Manifests[judgeBetween]; between.Refused != "" {
|
||||
st.c.note("the indexer's judge names problems between manifests that no one module's removal ends: " +
|
||||
strings.ReplaceAll(between.Refused, "\n", "; "))
|
||||
}
|
||||
if len(refused) > 0 {
|
||||
return fail(goModule, strings.Join(refused, "\n"))
|
||||
}
|
||||
@@ -154,30 +183,77 @@ func (st *state) judgeManifests(ctx context.Context) *delivery.Verdict {
|
||||
return nil
|
||||
}
|
||||
|
||||
// judgeAnswer reads the judge's case from its step, or why it cannot.
|
||||
func judgeAnswer(step delivery.Step) (composer.CaseVerdict, string) {
|
||||
// judgeAnswer reads the judge's change and trunk cases from its step, or why it cannot.
|
||||
func judgeAnswer(step delivery.Step) (change, trunk composer.CaseVerdict, why string) {
|
||||
if step.State != delivery.StepPassed {
|
||||
return composer.CaseVerdict{}, fmt.Sprintf("its step %s: %s", step.State, step.Reason)
|
||||
return change, trunk, fmt.Sprintf("its step %s: %s", step.State, step.Reason)
|
||||
}
|
||||
var a delivery.ComposeAnswer
|
||||
if err := json.Unmarshal(step.Result, &a); err != nil {
|
||||
return composer.CaseVerdict{}, "its step's answer cannot be read: " + err.Error()
|
||||
return change, trunk, "its step's answer cannot be read: " + err.Error()
|
||||
}
|
||||
var v composer.Verdict
|
||||
if err := json.Unmarshal(a.Verdict, &v); err != nil || v.V != composer.Version {
|
||||
return composer.CaseVerdict{}, fmt.Sprintf("its verdict cannot be read (version %d): %v", v.V, err)
|
||||
return change, trunk, fmt.Sprintf("its verdict cannot be read (version %d): %v", v.V, err)
|
||||
}
|
||||
found := 0
|
||||
for _, c := range v.Cases {
|
||||
if c.Name == JudgeCase {
|
||||
return c, ""
|
||||
switch c.Name {
|
||||
case JudgeCase:
|
||||
change, found = c, found+1
|
||||
case JudgeTrunk:
|
||||
trunk, found = c, found+1
|
||||
}
|
||||
}
|
||||
return composer.CaseVerdict{}, "its verdict holds no case " + JudgeCase
|
||||
if found != 2 {
|
||||
return change, trunk, "its verdict does not hold both the cases " + JudgeCase + " and " + JudgeTrunk
|
||||
}
|
||||
return change, trunk, ""
|
||||
}
|
||||
|
||||
// judgedByMember notes the group's mesh-delivery member head as the judge's when its merge changes the judge.
|
||||
// predefinedList is the list of predefined keys a case's manifests are judged against, and where it comes from: the
|
||||
// catalogue member's predefined.json at its head when its merge changes it, else the one the indexer keeps; nil when
|
||||
// neither can be read, said, and the judge then takes each fallback as its value declares it.
|
||||
func (st *state) predefinedList(ctx context.Context) (catalogue.PredefinedList, string) {
|
||||
read := func(raw []byte, from string) (catalogue.PredefinedList, string) {
|
||||
list, err := catalogue.ParsePredefined(raw)
|
||||
if err != nil {
|
||||
st.c.note("the predefined keys of " + from + " cannot be read, so fallbacks are judged as their values declare them: " + err.Error())
|
||||
return nil, ""
|
||||
}
|
||||
return list, from
|
||||
}
|
||||
if st.predefinedHead != "" && st.j.Forge != nil {
|
||||
text, err := st.j.Forge.File(ctx, catalogueRepository, catalogue.PredefinedFile, st.predefinedHead)
|
||||
if err == nil {
|
||||
return read([]byte(text), "the catalogue member's head "+st.predefinedHead)
|
||||
}
|
||||
st.c.note("the catalogue member's predefined.json cannot be read: " + err.Error())
|
||||
}
|
||||
if st.j.Predefined == nil {
|
||||
return nil, ""
|
||||
}
|
||||
raw, err := st.j.Predefined.PredefinedList(ctx)
|
||||
if err != nil || raw == nil {
|
||||
if err != nil {
|
||||
st.c.note("the indexer's predefined keys cannot be read: " + err.Error())
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
return read(raw, "the indexer's kept list")
|
||||
}
|
||||
|
||||
// judgedByMember notes the group's mesh-delivery member head as the judge's when its merge changes the judge, and the
|
||||
// catalogue member's head as where the predefined keys are read when its merge changes predefined.json.
|
||||
func (st *state) judgedByMember(p Pull, merged []Fetched) {
|
||||
if changesJudge(p.Repository, merged) {
|
||||
st.judgeHead = p.Head
|
||||
}
|
||||
if p.Repository == catalogueRepository {
|
||||
for _, f := range merged {
|
||||
if slices.Contains(f.Changed, catalogue.PredefinedFile) {
|
||||
st.predefinedHead = p.Head
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestManifestDeclarations(t *testing.T) { // 1678/AC1
|
||||
}
|
||||
if want := []string{"mesh-build-go.steps", "mesh-build-go.toolchains", "mesh-build-node.steps", "mesh-build-node.toolchains",
|
||||
"mesh-delivery-assigner.compositions", "mesh-delivery-assigner.placement", "mesh-delivery-builder.builds", "mesh-delivery-gate.source", "mesh-delivery-gate.turns", "mesh-delivery-indexer.candidates",
|
||||
"mesh-delivery-indexer.manifests", "mesh-delivery-indexer.modules", "mesh-delivery-watchman.presence", "node-engine.have"}; !reflect.DeepEqual(sorted(m.Reads), want) {
|
||||
"mesh-delivery-indexer.manifests", "mesh-delivery-indexer.modules", "mesh-delivery-indexer.predefined", "mesh-delivery-watchman.presence", "node-engine.have"}; !reflect.DeepEqual(sorted(m.Reads), want) {
|
||||
t.Errorf("reads = %v, want %v", m.Reads, want)
|
||||
}
|
||||
// 1887/A5b: the checker reads nothing of the controller's plans-building (ADR 0483 superseded by ADR 0525 §7), calls no
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"mesh-delivery-indexer.candidates",
|
||||
"mesh-delivery-indexer.manifests",
|
||||
"mesh-delivery-indexer.modules",
|
||||
"mesh-delivery-indexer.predefined",
|
||||
"mesh-delivery-watchman.presence",
|
||||
"node-engine.have"
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-forge-bridge
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -6,6 +6,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -391,9 +391,11 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
// Every manifest judged at the start, so a judge that changed with this program judges every one again (ADR 0578
|
||||
// §1), once the verdicts state is there; each merge judges them again (index.ApplyMessage).
|
||||
verdicts.Ready(func(jetstream.KeyValue) {
|
||||
j, err := ix.JudgeAll(ctx, nil)
|
||||
// A pass that fails (a read the bus did not answer) is judged again at the next message or source revision the
|
||||
// indexer hears (index.kickJudge): no timer.
|
||||
j, err := ix.JudgeAtStart(ctx)
|
||||
if err != nil {
|
||||
logger.Printf("judging the manifests at start: %v", err)
|
||||
logger.Printf("judging the manifests at start: %v; judged again at the next message heard", err)
|
||||
return
|
||||
}
|
||||
logger.Printf("judged %d manifests at start: %d verdicts written, %d with problems, of which outgrown and kept accepted: %v",
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-indexer
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -78,19 +78,20 @@ type Indexer struct {
|
||||
// closed message the indexer missed heals at the next one (issue 1126); nil asks none.
|
||||
ReadOpen func(ctx context.Context) ([]delivery.OpenPull, error)
|
||||
|
||||
mu sync.Mutex // guards source, toolchains and previews, which the watches and the forge messages all reach
|
||||
source sourceNow
|
||||
previews map[string]delivery.Preview // by previews key (previews.go)
|
||||
toolchains map[string]map[string]delivery.Toolchain // language, then node (toolchains.go)
|
||||
tried map[string]bool // repository, commit and directory a registered module's manifest was tried at (registered.go)
|
||||
unread map[string]bool // registered modules whose last read the forge could not answer, read again by RetryUnread
|
||||
retrying atomic.Bool // a RetryUnread runs in the background (kickRetry)
|
||||
retryAgain atomic.Bool // an event asked for one more RetryUnread after the running one
|
||||
retryWG sync.WaitGroup // the background RetryUnread, for tests to wait on
|
||||
recompute sync.Mutex // one Recompute at a time
|
||||
untaken map[string]string // repository to the latest merge applied while the taken state was missing (taken.go)
|
||||
filling atomic.Bool // a FillTaken runs in the background (KickFill)
|
||||
fillAgain atomic.Bool // a kick arrived while it ran
|
||||
mu sync.Mutex // guards source, toolchains and previews, which the watches and the forge messages all reach
|
||||
source sourceNow
|
||||
previews map[string]delivery.Preview // by previews key (previews.go)
|
||||
toolchains map[string]map[string]delivery.Toolchain // language, then node (toolchains.go)
|
||||
tried map[string]bool // repository, commit and directory a registered module's manifest was tried at (registered.go)
|
||||
unread map[string]bool // registered modules whose last read the forge could not answer, read again by RetryUnread
|
||||
retrying atomic.Bool // a RetryUnread runs in the background (kickRetry)
|
||||
retryAgain atomic.Bool // an event asked for one more RetryUnread after the running one
|
||||
retryWG sync.WaitGroup // the background RetryUnread, for tests to wait on
|
||||
recompute sync.Mutex // one Recompute at a time
|
||||
untaken map[string]string // repository to the latest merge applied while the taken state was missing (taken.go)
|
||||
filling atomic.Bool // a FillTaken runs in the background (KickFill)
|
||||
fillAgain atomic.Bool // a kick arrived while it ran
|
||||
judgePending atomic.Bool // the start's judge pass failed: judged again at the next message (verdicts.go)
|
||||
}
|
||||
|
||||
func (ix *Indexer) logf(format string, args ...any) {
|
||||
@@ -111,6 +112,7 @@ func (ix *Indexer) Apply(ctx context.Context, f delivery.Forge) error {
|
||||
// ApplyMessage is Apply, and answers which modules a merged message wrote and kept (for the indexer's heard state). Each
|
||||
// applied merged message is said in one line: its repository, commit and pull request, and the modules written.
|
||||
func (ix *Indexer) ApplyMessage(ctx context.Context, f delivery.Forge) (Applied, error) {
|
||||
ix.kickJudge(ctx)
|
||||
var applied Applied
|
||||
if f.Kind == delivery.ForgeOpen {
|
||||
return applied, ix.applyOpen(ctx, f)
|
||||
@@ -138,12 +140,8 @@ func (ix *Indexer) ApplyMessage(ctx context.Context, f delivery.Forge) (Applied,
|
||||
return applied, err
|
||||
}
|
||||
// Every manifest judged again: a rule between manifests can turn on the one this merge moved (ADR 0578 §1).
|
||||
// The merge's own manifests are fresh: one with no verdict yet is judged in full (ADR 0579 §1).
|
||||
fresh := map[string]bool{}
|
||||
for _, raw := range f.Manifests {
|
||||
fresh[delivery.ManifestDigest([]byte(raw))] = true
|
||||
}
|
||||
if _, err := ix.JudgeAll(ctx, fresh); err != nil {
|
||||
// What this take-in newly wrote is fresh: judged in full (ADR 0579 §1).
|
||||
if _, err := ix.JudgeAll(ctx, w.fresh); err != nil {
|
||||
ix.logf("judge: the manifests are not judged after %s#%d: %v", f.Repository, f.Number, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,16 @@ type mergeWrite struct {
|
||||
late string // the taken merge this one is older than, or ""
|
||||
asked string // the taken merge the order was asked against, or "" when none was asked
|
||||
written []string
|
||||
// fresh are the manifest digests this take-in newly wrote: a new module's, or a changed one's (ADR 0579 §1).
|
||||
fresh map[string]bool
|
||||
}
|
||||
|
||||
// taken marks a digest this take-in newly wrote.
|
||||
func (w *mergeWrite) taken(digest string) {
|
||||
if w.fresh == nil {
|
||||
w.fresh = map[string]bool{}
|
||||
}
|
||||
w.fresh[digest] = true
|
||||
}
|
||||
|
||||
func newMergeWrite(f delivery.Forge) *mergeWrite {
|
||||
|
||||
@@ -134,9 +134,14 @@ func (ix *Indexer) indexAt(ctx context.Context, r Registration, force, reread bo
|
||||
if p := read.Packages[dir]; len(p) > 0 {
|
||||
f.Packages = map[string][]string{dir: p}
|
||||
}
|
||||
if _, err := ix.applyManifests(ctx, f, false); err != nil {
|
||||
w, err := ix.applyManifests(ctx, f, false)
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
// A module registered or taken in is judged as a merge's are (ADR 0578 §1, ADR 0579 §1).
|
||||
if _, err := ix.JudgeAll(ctx, w.fresh); err != nil {
|
||||
ix.logf("judge: the manifests are not judged after taking in %s: %v", r.Module, err)
|
||||
}
|
||||
if _, _, found, err := ix.Modules.Get(ctx, key); err != nil {
|
||||
return t, fmt.Errorf("modules.%s: %w", key, err)
|
||||
} else if !found {
|
||||
|
||||
@@ -37,6 +37,7 @@ func (ix *Indexer) srcOf(repository, merge string) uint64 {
|
||||
// when it is written, applyMerged), and a repository none of the indexer's modules is built from writes nothing. The
|
||||
// modules of a repository are those the modules bucket holds of it (ADR 0501 clause 6).
|
||||
func (ix *Indexer) ApplySource(ctx context.Context, rev uint64, s delivery.Source) error {
|
||||
ix.kickJudge(ctx)
|
||||
ix.mu.Lock()
|
||||
if rev < ix.source.rev {
|
||||
ix.mu.Unlock()
|
||||
|
||||
@@ -256,7 +256,10 @@ func (ix *Indexer) recomputeModules(ctx context.Context, overlay map[string]deli
|
||||
}
|
||||
// The latest published version of each mesh package the module uses: the trunk merge of the module that holds it,
|
||||
// as this recompute holds it, so a package's merge moves every dependent in the same recompute (ADR 0573 §2).
|
||||
versions, _ := delivery.PackageVersionsOf(kept.Packages, held)
|
||||
versions, unpublished := delivery.PackageVersionsOf(kept.Packages, held)
|
||||
if len(unpublished) > 0 {
|
||||
ix.logf("%s: no module the indexer holds publishes %s, so its fingerprint takes no version of it", module, strings.Join(unpublished, ", "))
|
||||
}
|
||||
var r result
|
||||
switch {
|
||||
case k.contexts:
|
||||
@@ -348,10 +351,19 @@ func (ix *Indexer) writeOverlay(ctx context.Context, overlay, finals map[string]
|
||||
wrote := false
|
||||
err := write(ctx, ix.Modules, key, func(value []byte, found bool) ([]byte, bool, error) {
|
||||
wrote = false
|
||||
if found {
|
||||
if cur, err := delivery.DecodeModule(value); err == nil && sameButWhere(cur, next) {
|
||||
return nil, false, nil
|
||||
}
|
||||
next := next
|
||||
cur, err := delivery.DecodeModule(value)
|
||||
held := found && err == nil
|
||||
if held && cur.Manifest == next.Manifest {
|
||||
// The judge's verdict stands while the digest does (ADR 0578 §3, ADR 0579 §1): a recompute never writes a
|
||||
// refused or outgrown module as accepted; only the judge changes it.
|
||||
next.Verdict, next.Problems, next.Warnings = cur.Verdict, cur.Problems, cur.Warnings
|
||||
}
|
||||
if held && sameButWhere(cur, next) {
|
||||
return nil, false, nil
|
||||
}
|
||||
if next.Manifest != "" && (!held || cur.Manifest != next.Manifest) {
|
||||
w.taken(next.Manifest) // a new module, or a changed manifest: fresh, judged in full (ADR 0579 §1)
|
||||
}
|
||||
data, err := delivery.EncodeModule(next)
|
||||
wrote = err == nil
|
||||
@@ -367,10 +379,12 @@ func (ix *Indexer) writeOverlay(ctx context.Context, overlay, finals map[string]
|
||||
return nil
|
||||
}
|
||||
|
||||
// sameButWhere says the held value cur is next but for where it was computed (Commit and Src): the module is unchanged.
|
||||
// sameButWhere says the held value cur is next but for where it was computed (Commit and Src) and the judge's verdict,
|
||||
// which only the judge writes: the module is unchanged.
|
||||
func sameButWhere(cur, next delivery.Module) bool {
|
||||
next = withV(next)
|
||||
next.Commit, next.Src = cur.Commit, cur.Src
|
||||
next.Verdict, next.Problems, next.Warnings = cur.Verdict, cur.Problems, cur.Warnings
|
||||
return reflect.DeepEqual(cur, next)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,26 @@ func (ix *Indexer) JudgeAll(ctx context.Context, fresh map[string]bool) (Judged,
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// JudgeAtStart is JudgeAll of every manifest held, none fresh, as the indexer starts (a judge that changed judges every
|
||||
// one again); one that fails is judged again at the next message or source revision heard (kickJudge).
|
||||
func (ix *Indexer) JudgeAtStart(ctx context.Context) (Judged, error) {
|
||||
j, err := ix.JudgeAll(ctx, nil)
|
||||
ix.judgePending.Store(err != nil)
|
||||
return j, err
|
||||
}
|
||||
|
||||
// kickJudge judges again a start pass that failed, when the indexer hears something: never on a timer.
|
||||
func (ix *Indexer) kickJudge(ctx context.Context) {
|
||||
if !ix.judgePending.Load() {
|
||||
return
|
||||
}
|
||||
if j, err := ix.JudgeAtStart(ctx); err != nil {
|
||||
ix.logf("judge: the manifests are still not judged: %v", err)
|
||||
} else {
|
||||
ix.logf("judge: judged %d manifests again after a failed start: %d verdicts written", j.Judged, j.Written)
|
||||
}
|
||||
}
|
||||
|
||||
// acceptedBefore says whether the manifest of digest was accepted before this judgement: its verdict says accepted, or
|
||||
// it has none and is not fresh (held before any verdict, so taken in under the judges that ran until then).
|
||||
func (ix *Indexer) acceptedBefore(ctx context.Context, digest string, fresh map[string]bool) bool {
|
||||
|
||||
@@ -103,6 +103,21 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
|
||||
if !verdict(changed).Refused() || !verdict(fresh).Refused() || module("old").Verdict != delivery.VerdictRefused || len(module("old").Warnings) != 0 {
|
||||
t.Fatalf("the changed and the new manifest are not refused: %+v %+v", verdict(changed), verdict(fresh))
|
||||
}
|
||||
// A merge's write of a module whose digest it leaves as it is carries the verdict over, and nothing is fresh; a changed
|
||||
// digest is fresh, judged in full (review R1, R2).
|
||||
w := &mergeWrite{}
|
||||
same := delivery.Module{FP2: "src2:" + strings.Repeat("c", 64), Manifest: changed, Repository: "novox/mesh-catalog", Commit: "c2"}
|
||||
if err := ix.writeOverlay(ctx, map[string]delivery.Module{"old": same}, nil, w); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m := module("old"); m.Verdict != delivery.VerdictRefused || len(m.Problems) == 0 || len(w.fresh) != 0 {
|
||||
t.Fatalf("a merge rewrote a refused module as %+v, fresh %v", m, w.fresh)
|
||||
}
|
||||
other := strings.Repeat("d", 64)
|
||||
same.Manifest = other
|
||||
if err := ix.writeOverlay(ctx, map[string]delivery.Module{"old": same}, nil, w); err != nil || !w.fresh[other] {
|
||||
t.Fatalf("a changed digest is not fresh: %v %v", w.fresh, err)
|
||||
}
|
||||
// Without the verdicts state the indexer judges nothing.
|
||||
ix.Verdicts = nil
|
||||
if j, err := ix.JudgeAll(ctx, nil); err != nil || j.Judged != 0 {
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-teller
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -4,6 +4,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-view
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -4,6 +4,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-delivery-watchman
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.8.0-default-no-op h1:1BOWQJweNyvZMlpAHXGLiZQn9S+QXGcz3xh94lC0w6E=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.8.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-grants
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236 h1:JEkSnrmH
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014012-a20bdf795236/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc h1:kVq7sS4I0EnL8DcAA2a3YstnXS6WmYYzJz7eK7IZ9RY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101014310-19c204273bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62 h1:R5C8ICjiaDITHRFR/uIATwARPPXKxssUC70m0svstb0=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101020750-62cddf4efc62/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
Reference in New Issue
Block a user