diff --git a/contracts/go/seats/meshpipelinerunner/contract.go b/contracts/go/seats/meshpipelinerunner/contract.go index 9a5d4c11..39817255 100644 --- a/contracts/go/seats/meshpipelinerunner/contract.go +++ b/contracts/go/seats/meshpipelinerunner/contract.go @@ -418,8 +418,10 @@ type Pipeline struct { // the watched branch, or the branch of a run on request Branch string `json:"branch"` // the commit the module's entry was last changed at - Commit string `json:"commit"` - Ended *time.Time `json:"ended,omitempty"` + Commit string `json:"commit"` + // how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325) + EndCount int64 `json:"end-count,omitempty"` + Ended *time.Time `json:"ended,omitempty"` // the module's build-input fingerprint at the commit Fp string `json:"fp,omitempty"` // the gathered group, when the pipeline is its @@ -463,8 +465,10 @@ type PipelineEnded struct { // the watched branch, or the branch of a run on request Branch string `json:"branch"` // the commit the module's entry was last changed at - Commit string `json:"commit"` - Ended *time.Time `json:"ended,omitempty"` + Commit string `json:"commit"` + // how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325) + EndCount int64 `json:"end-count,omitempty"` + Ended *time.Time `json:"ended,omitempty"` // the module's build-input fingerprint at the commit Fp string `json:"fp,omitempty"` // the gathered group, when the pipeline is its @@ -630,6 +634,7 @@ const ( StepResultOutcomeWaitingForABuildNode = "waiting for a build node" StepResultOutcomeDidNotBuild = "did not build" StepResultOutcomeAccepted = "accepted" + StepResultOutcomeNotAsked = "not asked" StepResultOutcomeDeclined = "declined" StepResultOutcomeSuperseded = "superseded" StepResultOutcomeCancelled = "cancelled" diff --git a/contracts/go/seats/meshpipelinerunner/contract_test.go b/contracts/go/seats/meshpipelinerunner/contract_test.go index 44f3768e..ded5552b 100644 --- a/contracts/go/seats/meshpipelinerunner/contract_test.go +++ b/contracts/go/seats/meshpipelinerunner/contract_test.go @@ -19,9 +19,9 @@ func TestFixtures(t *testing.T) { }{ {name: "a pipeline started with the steps its policy gives", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-started.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"status\":\"required\",\"step\":\"lint\"},{\"status\":\"bypass\",\"step\":\"review\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"status\":\"required\",\"step\":\"lint\"},{\"status\":\"bypass\",\"step\":\"review\"}],\"v\":1}", decode: func(b []byte) (any, error) { var v PipelineStartedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-started\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")}, - {name: "a pipeline ended passed, an optional step failed, over budget and widening named", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}", + {name: "a pipeline ended passed, an optional step failed, over budget and widening named", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}", decode: func(b []byte) (any, error) { var v PipelineEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")}, - {name: "a pipeline ended failed, naming the step that held it", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"on\":\"the operator\",\"outcome\":\"waiting\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"on\":\"the operator\",\"outcome\":\"waiting\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}", + {name: "a pipeline ended failed, naming the step that held it, its approval not asked", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"outcome\":\"not asked\",\"status\":\"required\",\"step\":\"approval\",\"why\":\"unit of nats:program failed\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"outcome\":\"not asked\",\"status\":\"required\",\"step\":\"approval\",\"why\":\"unit of nats:program failed\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}", decode: func(b []byte) (any, error) { var v PipelineEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")}, {name: "a group's one pipeline ended on a watched branch", subject: "mesh.seat.mesh-pipeline-runner.event.group-ended.main.registry-1966", given: "{\"branch\":\"main\",\"ended\":\"2026-11-10T10:20:00Z\",\"group\":\"registry-1966\",\"outcome\":\"passed\",\"pipelines\":[{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"group\":\"registry-1966\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}],\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"branch\":\"main\",\"ended\":\"2026-11-10T10:20:00Z\",\"group\":\"registry-1966\",\"outcome\":\"passed\",\"pipelines\":[{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"group\":\"registry-1966\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}],\"revision\":12,\"source\":3589,\"v\":1}", decode: func(b []byte) (any, error) { var v GroupEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.group-ended\\.[^.*> ]+\\.[^.*> ]+$")}, @@ -37,7 +37,7 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v WaitHeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.wait-held\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")}, {name: "the wait ended answered", subject: "mesh.seat.mesh-pipeline-runner.event.wait-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"how\":\"answered\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"how\":\"answered\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}", decode: func(b []byte) (any, error) { var v WaitEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.wait-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")}, - {name: "a pipeline kept", subject: "", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}", + {name: "a pipeline kept", subject: "", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"end-count\":1,\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}", decode: func(b []byte) (any, error) { var v PipelinesByBranchRevisionModuleValue err := json.Unmarshal(b, &v) diff --git a/contracts/go/seats/nodebuildgo/contract.go b/contracts/go/seats/nodebuildgo/contract.go index 1356a60b..34785b37 100644 --- a/contracts/go/seats/nodebuildgo/contract.go +++ b/contracts/go/seats/nodebuildgo/contract.go @@ -24,11 +24,12 @@ const ( ) const ( - AcceptDelivery = "delivery" - AcceptCheck = "check" - AcceptStep = "step" - AcceptRecheck = "recheck" - AcceptRun = "run" + AcceptDelivery = "delivery" + AcceptCheck = "check" + AcceptCheckStep = "check.step" + AcceptDeliveryStep = "delivery.step" + AcceptRecheck = "recheck" + AcceptCheckRun = "check.run" ) const ( @@ -66,14 +67,17 @@ const AcceptSubjectDelivery = "mesh.seat.node-build-go.accept.delivery" // AcceptSubjectCheck is where check is sent. const AcceptSubjectCheck = "mesh.seat.node-build-go.accept.check" -// AcceptSubjectStep is where step is sent. -const AcceptSubjectStep = "mesh.seat.node-build-go.accept.step" +// AcceptSubjectCheckStep is where check.step is sent. +const AcceptSubjectCheckStep = "mesh.seat.node-build-go.accept.check.step" + +// AcceptSubjectDeliveryStep is where delivery.step is sent. +const AcceptSubjectDeliveryStep = "mesh.seat.node-build-go.accept.delivery.step" // AcceptSubjectRecheck is where recheck is sent. const AcceptSubjectRecheck = "mesh.seat.node-build-go.accept.recheck" -// AcceptSubjectRun is where run is sent. -const AcceptSubjectRun = "mesh.seat.node-build-go.accept.run" +// AcceptSubjectCheckRun is where check.run is sent. +const AcceptSubjectCheckRun = "mesh.seat.node-build-go.accept.check.run" const ( StateSteps = "steps" @@ -930,14 +934,17 @@ type DeliveryAccept = StepAsk // CheckAccept is the body of check. type CheckAccept = StepAsk -// StepAccept is the body of step. -type StepAccept = StepAsk +// CheckStepAccept is the body of check.step. +type CheckStepAccept = StepAsk + +// DeliveryStepAccept is the body of delivery.step. +type DeliveryStepAccept = StepAsk // RecheckAccept is the body of recheck. type RecheckAccept = StepAsk -// RunAccept is the body of run. -type RunAccept = StepAsk +// CheckRunAccept is the body of check.run. +type CheckRunAccept = StepAsk // StepEndedEvent is the body of the event step-ended. type StepEndedEvent = StepEnded diff --git a/contracts/go/seats/nodebuildgo/contract_test.go b/contracts/go/seats/nodebuildgo/contract_test.go index b2da57f0..b35c655d 100644 --- a/contracts/go/seats/nodebuildgo/contract_test.go +++ b/contracts/go/seats/nodebuildgo/contract_test.go @@ -63,10 +63,12 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, - {name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-go.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", - decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.step$")}, - {name: "a run ask of the runner, the program built from the change and run over its heads", subject: "mesh.seat.node-build-go.accept.run", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}", - decode: func(b []byte) (any, error) { var v RunAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.run$")}, + {name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-go.accept.check.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v CheckStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.check\\.step$")}, + {name: "a recovery's step ask of the runner, on the stream delivery", subject: "mesh.seat.node-build-go.accept.delivery.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v DeliveryStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.delivery\\.step$")}, + {name: "a run ask of the runner, the program built from the change and run over its heads", subject: "mesh.seat.node-build-go.accept.check.run", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v CheckRunAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.check\\.run$")}, {name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", decode: func(b []byte) (any, error) { var v DetectedStepsByModuleArtifactValue diff --git a/contracts/go/seats/nodebuildimage/contract.go b/contracts/go/seats/nodebuildimage/contract.go index d8dd929a..00f25faa 100644 --- a/contracts/go/seats/nodebuildimage/contract.go +++ b/contracts/go/seats/nodebuildimage/contract.go @@ -24,10 +24,11 @@ const ( ) const ( - AcceptDelivery = "delivery" - AcceptCheck = "check" - AcceptStep = "step" - AcceptRecheck = "recheck" + AcceptDelivery = "delivery" + AcceptCheck = "check" + AcceptCheckStep = "check.step" + AcceptDeliveryStep = "delivery.step" + AcceptRecheck = "recheck" ) const ( @@ -67,8 +68,11 @@ const AcceptSubjectDelivery = "mesh.seat.node-build-image.accept.delivery" // AcceptSubjectCheck is where check is sent. const AcceptSubjectCheck = "mesh.seat.node-build-image.accept.check" -// AcceptSubjectStep is where step is sent. -const AcceptSubjectStep = "mesh.seat.node-build-image.accept.step" +// AcceptSubjectCheckStep is where check.step is sent. +const AcceptSubjectCheckStep = "mesh.seat.node-build-image.accept.check.step" + +// AcceptSubjectDeliveryStep is where delivery.step is sent. +const AcceptSubjectDeliveryStep = "mesh.seat.node-build-image.accept.delivery.step" // AcceptSubjectRecheck is where recheck is sent. const AcceptSubjectRecheck = "mesh.seat.node-build-image.accept.recheck" @@ -928,8 +932,11 @@ type DeliveryAccept = StepAsk // CheckAccept is the body of check. type CheckAccept = StepAsk -// StepAccept is the body of step. -type StepAccept = StepAsk +// CheckStepAccept is the body of check.step. +type CheckStepAccept = StepAsk + +// DeliveryStepAccept is the body of delivery.step. +type DeliveryStepAccept = StepAsk // RecheckAccept is the body of recheck. type RecheckAccept = StepAsk diff --git a/contracts/go/seats/nodebuildimage/contract_test.go b/contracts/go/seats/nodebuildimage/contract_test.go index 516abfae..fbbbb9c8 100644 --- a/contracts/go/seats/nodebuildimage/contract_test.go +++ b/contracts/go/seats/nodebuildimage/contract_test.go @@ -47,8 +47,10 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, - {name: "a lint step ask of the runner with the names", subject: "mesh.seat.node-build-image.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", - decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.step$")}, + {name: "a lint step ask of the runner with the names", subject: "mesh.seat.node-build-image.accept.check.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v CheckStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.check\\.step$")}, + {name: "a recovery's step ask of the runner, on the stream delivery", subject: "mesh.seat.node-build-image.accept.delivery.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v DeliveryStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.delivery\\.step$")}, {name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", decode: func(b []byte) (any, error) { var v DetectedStepsByModuleArtifactValue diff --git a/contracts/go/seats/nodebuildnode/contract.go b/contracts/go/seats/nodebuildnode/contract.go index 27d87a30..2df88e8f 100644 --- a/contracts/go/seats/nodebuildnode/contract.go +++ b/contracts/go/seats/nodebuildnode/contract.go @@ -24,10 +24,11 @@ const ( ) const ( - AcceptDelivery = "delivery" - AcceptCheck = "check" - AcceptStep = "step" - AcceptRecheck = "recheck" + AcceptDelivery = "delivery" + AcceptCheck = "check" + AcceptCheckStep = "check.step" + AcceptDeliveryStep = "delivery.step" + AcceptRecheck = "recheck" ) const ( @@ -67,8 +68,11 @@ const AcceptSubjectDelivery = "mesh.seat.node-build-node.accept.delivery" // AcceptSubjectCheck is where check is sent. const AcceptSubjectCheck = "mesh.seat.node-build-node.accept.check" -// AcceptSubjectStep is where step is sent. -const AcceptSubjectStep = "mesh.seat.node-build-node.accept.step" +// AcceptSubjectCheckStep is where check.step is sent. +const AcceptSubjectCheckStep = "mesh.seat.node-build-node.accept.check.step" + +// AcceptSubjectDeliveryStep is where delivery.step is sent. +const AcceptSubjectDeliveryStep = "mesh.seat.node-build-node.accept.delivery.step" // AcceptSubjectRecheck is where recheck is sent. const AcceptSubjectRecheck = "mesh.seat.node-build-node.accept.recheck" @@ -928,8 +932,11 @@ type DeliveryAccept = StepAsk // CheckAccept is the body of check. type CheckAccept = StepAsk -// StepAccept is the body of step. -type StepAccept = StepAsk +// CheckStepAccept is the body of check.step. +type CheckStepAccept = StepAsk + +// DeliveryStepAccept is the body of delivery.step. +type DeliveryStepAccept = StepAsk // RecheckAccept is the body of recheck. type RecheckAccept = StepAsk diff --git a/contracts/go/seats/nodebuildnode/contract_test.go b/contracts/go/seats/nodebuildnode/contract_test.go index 7392b258..982cd713 100644 --- a/contracts/go/seats/nodebuildnode/contract_test.go +++ b/contracts/go/seats/nodebuildnode/contract_test.go @@ -51,8 +51,10 @@ func TestFixtures(t *testing.T) { decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, {name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil}, - {name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-node.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", - decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.step$")}, + {name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-node.accept.check.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v CheckStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.check\\.step$")}, + {name: "a recovery's step ask of the runner, on the stream delivery", subject: "mesh.seat.node-build-node.accept.delivery.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", + decode: func(b []byte) (any, error) { var v DeliveryStepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.delivery\\.step$")}, {name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", decode: func(b []byte) (any, error) { var v DetectedStepsByModuleArtifactValue diff --git a/contracts/seats/mesh-pipeline-runner/fixtures/events.json b/contracts/seats/mesh-pipeline-runner/fixtures/events.json index cdd9d6c9..3eb22465 100644 --- a/contracts/seats/mesh-pipeline-runner/fixtures/events.json +++ b/contracts/seats/mesh-pipeline-runner/fixtures/events.json @@ -36,6 +36,7 @@ "branch": "main", "revision": 12, "source": 3589, + "end-count": 1, "commit": "0123456789abcdef0123456789abcdef01234567", "fp": "fp-0123", "v": 1, @@ -109,7 +110,7 @@ } }, { - "name": "a pipeline ended failed, naming the step that held it", + "name": "a pipeline ended failed, naming the step that held it, its approval not asked", "of": "event:pipeline-ended", "subject": "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", "given": { @@ -118,6 +119,7 @@ "branch": "main", "revision": 12, "source": 3589, + "end-count": 1, "commit": "0123456789abcdef0123456789abcdef01234567", "fp": "fp-0123", "v": 1, @@ -134,8 +136,8 @@ { "step": "approval", "status": "required", - "outcome": "waiting", - "on": "the operator" + "outcome": "not asked", + "why": "unit of nats:program failed" } ], "over-budget": true diff --git a/contracts/seats/mesh-pipeline-runner/fixtures/states.json b/contracts/seats/mesh-pipeline-runner/fixtures/states.json index 318e10d5..f5873247 100644 --- a/contracts/seats/mesh-pipeline-runner/fixtures/states.json +++ b/contracts/seats/mesh-pipeline-runner/fixtures/states.json @@ -8,6 +8,7 @@ "branch": "main", "revision": 12, "source": 3589, + "end-count": 1, "commit": "0123456789abcdef0123456789abcdef01234567", "fp": "fp-0123", "v": 1, diff --git a/contracts/seats/mesh-pipeline-runner/seat.json b/contracts/seats/mesh-pipeline-runner/seat.json index 91df6fff..5d972333 100644 --- a/contracts/seats/mesh-pipeline-runner/seat.json +++ b/contracts/seats/mesh-pipeline-runner/seat.json @@ -678,7 +678,7 @@ { "name": "step-log", "template": "log", - "max-age-days": 90, + "max-age-days": 100, "description": "one entry per step's start and end, its output by name; kept on the runner's old streams section", "key-forms": [ { @@ -856,6 +856,7 @@ "waiting for a build node", "did not build", "accepted", + "not asked", "declined", "superseded", "cancelled" @@ -974,6 +975,10 @@ "type": "integer", "description": "the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)" }, + "end-count": { + "type": "integer", + "description": "how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325)" + }, "commit": { "type": "string", "description": "the commit the module's entry was last changed at" @@ -1072,6 +1077,10 @@ "type": "integer", "description": "the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)" }, + "end-count": { + "type": "integer", + "description": "how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325)" + }, "commit": { "type": "string", "description": "the commit the module's entry was last changed at" diff --git a/contracts/seats/node-build-go/fixtures/states.json b/contracts/seats/node-build-go/fixtures/states.json index 88351639..9ee56a47 100644 --- a/contracts/seats/node-build-go/fixtures/states.json +++ b/contracts/seats/node-build-go/fixtures/states.json @@ -373,8 +373,56 @@ }, { "name": "a step ask of the runner with the names and kept results", - "of": "accept:step", - "subject": "mesh.seat.node-build-go.accept.step", + "of": "accept:check.step", + "subject": "mesh.seat.node-build-go.accept.check.step", + "given": { + "v": 1, + "id": "m2kx9a1b3c4d5e", + "kind": "step", + "language": "go", + "asker": "mesh-delivery-pipeline", + "at": "2026-11-10T10:00:00Z", + "step": { + "pipeline": "main.12.nats", + "step": "unit", + "module": "nats", + "artifact": "nats:program", + "branch": "main", + "commit": "0123456789abcdef0123456789abcdef01234567", + "revision": 12, + "fingerprint": "fp-0123", + "fetch": { + "repository": "novox/mesh-catalog", + "commit": "0123456789abcdef0123456789abcdef01234567" + }, + "names": { + "modules": [ + "nats", + "mesh-sdk" + ], + "repositories": [ + "novox/mesh-catalog", + "novox/mesh-sdk" + ], + "branches": [ + "main" + ] + }, + "kept": [ + { + "package": "./modules/nats/a", + "digest": "sha256:bbbb", + "level": "unit", + "pipeline": "main.11.nats" + } + ] + } + } + }, + { + "name": "a recovery's step ask of the runner, on the stream delivery", + "of": "accept:delivery.step", + "subject": "mesh.seat.node-build-go.accept.delivery.step", "given": { "v": 1, "id": "m2kx9a1b3c4d5e", @@ -421,8 +469,8 @@ }, { "name": "a run ask of the runner, the program built from the change and run over its heads", - "of": "accept:run", - "subject": "mesh.seat.node-build-go.accept.run", + "of": "accept:check.run", + "subject": "mesh.seat.node-build-go.accept.check.run", "given": { "v": 1, "id": "r5e6", diff --git a/contracts/seats/node-build-go/seat.json b/contracts/seats/node-build-go/seat.json index 0e720750..4d30fcd7 100644 --- a/contracts/seats/node-build-go/seat.json +++ b/contracts/seats/node-build-go/seat.json @@ -37,6 +37,17 @@ }, { "name": "step", + "stream": "check", + "body": { + "$ref": "#/defs/StepAsk" + }, + "callers": [ + "seat:mesh-pipeline-runner" + ] + }, + { + "name": "step", + "stream": "delivery", "body": { "$ref": "#/defs/StepAsk" }, @@ -55,6 +66,7 @@ }, { "name": "run", + "stream": "check", "body": { "$ref": "#/defs/StepAsk" }, diff --git a/contracts/seats/node-build-image/fixtures/states.json b/contracts/seats/node-build-image/fixtures/states.json index 0053f603..3cbef09e 100644 --- a/contracts/seats/node-build-image/fixtures/states.json +++ b/contracts/seats/node-build-image/fixtures/states.json @@ -89,8 +89,48 @@ }, { "name": "a lint step ask of the runner with the names", - "of": "accept:step", - "subject": "mesh.seat.node-build-image.accept.step", + "of": "accept:check.step", + "subject": "mesh.seat.node-build-image.accept.check.step", + "given": { + "v": 1, + "id": "m2kx9a1b3c4d5e", + "kind": "step", + "language": "image", + "asker": "mesh-delivery-pipeline", + "at": "2026-11-10T10:00:00Z", + "step": { + "pipeline": "main.12.nats", + "step": "lint", + "module": "nats", + "artifact": "nats:program", + "branch": "main", + "commit": "0123456789abcdef0123456789abcdef01234567", + "revision": 12, + "fingerprint": "fp-0123", + "fetch": { + "repository": "novox/mesh-catalog", + "commit": "0123456789abcdef0123456789abcdef01234567" + }, + "names": { + "modules": [ + "nats", + "mesh-sdk" + ], + "repositories": [ + "novox/mesh-catalog", + "novox/mesh-sdk" + ], + "branches": [ + "main" + ] + } + } + } + }, + { + "name": "a recovery's step ask of the runner, on the stream delivery", + "of": "accept:delivery.step", + "subject": "mesh.seat.node-build-image.accept.delivery.step", "given": { "v": 1, "id": "m2kx9a1b3c4d5e", diff --git a/contracts/seats/node-build-image/seat.json b/contracts/seats/node-build-image/seat.json index 383860af..2d5f83ab 100644 --- a/contracts/seats/node-build-image/seat.json +++ b/contracts/seats/node-build-image/seat.json @@ -28,6 +28,17 @@ }, { "name": "step", + "stream": "check", + "body": { + "$ref": "#/defs/StepAsk" + }, + "callers": [ + "seat:mesh-pipeline-runner" + ] + }, + { + "name": "step", + "stream": "delivery", "body": { "$ref": "#/defs/StepAsk" }, diff --git a/contracts/seats/node-build-node/fixtures/states.json b/contracts/seats/node-build-node/fixtures/states.json index 8e4c9fe0..ccf06869 100644 --- a/contracts/seats/node-build-node/fixtures/states.json +++ b/contracts/seats/node-build-node/fixtures/states.json @@ -161,8 +161,56 @@ }, { "name": "a step ask of the runner with the names and kept results", - "of": "accept:step", - "subject": "mesh.seat.node-build-node.accept.step", + "of": "accept:check.step", + "subject": "mesh.seat.node-build-node.accept.check.step", + "given": { + "v": 1, + "id": "m2kx9a1b3c4d5e", + "kind": "step", + "language": "typescript", + "asker": "mesh-delivery-pipeline", + "at": "2026-11-10T10:00:00Z", + "step": { + "pipeline": "main.12.nats", + "step": "unit", + "module": "nats", + "artifact": "nats:program", + "branch": "main", + "commit": "0123456789abcdef0123456789abcdef01234567", + "revision": 12, + "fingerprint": "fp-0123", + "fetch": { + "repository": "novox/mesh-catalog", + "commit": "0123456789abcdef0123456789abcdef01234567" + }, + "names": { + "modules": [ + "nats", + "mesh-sdk" + ], + "repositories": [ + "novox/mesh-catalog", + "novox/mesh-sdk" + ], + "branches": [ + "main" + ] + }, + "kept": [ + { + "package": "./modules/nats/a", + "digest": "sha256:bbbb", + "level": "unit", + "pipeline": "main.11.nats" + } + ] + } + } + }, + { + "name": "a recovery's step ask of the runner, on the stream delivery", + "of": "accept:delivery.step", + "subject": "mesh.seat.node-build-node.accept.delivery.step", "given": { "v": 1, "id": "m2kx9a1b3c4d5e", diff --git a/contracts/seats/node-build-node/seat.json b/contracts/seats/node-build-node/seat.json index dd03154f..978f9dde 100644 --- a/contracts/seats/node-build-node/seat.json +++ b/contracts/seats/node-build-node/seat.json @@ -35,6 +35,17 @@ }, { "name": "step", + "stream": "check", + "body": { + "$ref": "#/defs/StepAsk" + }, + "callers": [ + "seat:mesh-pipeline-runner" + ] + }, + { + "name": "step", + "stream": "delivery", "body": { "$ref": "#/defs/StepAsk" }, diff --git a/contracts/ts/seats/meshpipelinerunner/index.d.ts b/contracts/ts/seats/meshpipelinerunner/index.d.ts index e824d349..cf1d8263 100644 --- a/contracts/ts/seats/meshpipelinerunner/index.d.ts +++ b/contracts/ts/seats/meshpipelinerunner/index.d.ts @@ -182,6 +182,8 @@ export interface Pipeline { "branch": string; /** the commit the module's entry was last changed at */ "commit": string; + /** how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325) */ + "end-count"?: number; "ended"?: string; /** the module's build-input fingerprint at the commit */ "fp"?: string; @@ -217,6 +219,8 @@ export interface PipelineEnded { "branch": string; /** the commit the module's entry was last changed at */ "commit": string; + /** how often the pipeline has ended: 1 at its first end, one higher at each end again after a passing rerun, so the assigner takes a later end of the same source revision (design 47 G sections 29, 325) */ + "end-count"?: number; "ended"?: string; /** the module's build-input fingerprint at the commit */ "fp"?: string; @@ -326,7 +330,7 @@ export interface StepResult { /** for a waiting step, who or what it waits on: a person, a build node, the revision view */ "on"?: string; /** never passed for a step that ran nothing (design 47 *Pipeline steps and the policy*) */ - "outcome": "running" | "waiting" | "passed" | "failed" | "nothing to run" | "bypassed" | "carried" | "could not run" | "waiting for a build node" | "did not build" | "accepted" | "declined" | "superseded" | "cancelled"; + "outcome": "running" | "waiting" | "passed" | "failed" | "nothing to run" | "bypassed" | "carried" | "could not run" | "waiting for a build node" | "did not build" | "accepted" | "not asked" | "declined" | "superseded" | "cancelled"; /** the step's output, by its name in the runner's objects step-outputs */ "output"?: string; /** the step was asked again by the runner's rerun */ diff --git a/contracts/ts/seats/nodebuildgo/index.d.ts b/contracts/ts/seats/nodebuildgo/index.d.ts index 0cd57cea..ff6e8d0e 100644 --- a/contracts/ts/seats/nodebuildgo/index.d.ts +++ b/contracts/ts/seats/nodebuildgo/index.d.ts @@ -18,9 +18,10 @@ export declare const verbs: { export declare const accepts: { readonly delivery: "delivery"; readonly check: "check"; - readonly step: "step"; + readonly checkStep: "check.step"; + readonly deliveryStep: "delivery.step"; readonly recheck: "recheck"; - readonly run: "run"; + readonly checkRun: "check.run"; }; export declare const events: { @@ -39,11 +40,13 @@ export declare const deliverySubject: "mesh.seat.node-build-go.accept.delivery"; export declare const checkSubject: "mesh.seat.node-build-go.accept.check"; -export declare const stepSubject: "mesh.seat.node-build-go.accept.step"; +export declare const checkStepSubject: "mesh.seat.node-build-go.accept.check.step"; + +export declare const deliveryStepSubject: "mesh.seat.node-build-go.accept.delivery.step"; export declare const recheckSubject: "mesh.seat.node-build-go.accept.recheck"; -export declare const runSubject: "mesh.seat.node-build-go.accept.run"; +export declare const checkRunSubject: "mesh.seat.node-build-go.accept.check.run"; export declare const states: { readonly steps: "steps"; @@ -151,14 +154,17 @@ export type DeliveryAccept = StepAsk; /** is the body of check. */ export type CheckAccept = StepAsk; -/** is the body of step. */ -export type StepAccept = StepAsk; +/** is the body of check.step. */ +export type CheckStepAccept = StepAsk; + +/** is the body of delivery.step. */ +export type DeliveryStepAccept = StepAsk; /** is the body of recheck. */ export type RecheckAccept = StepAsk; -/** is the body of run. */ -export type RunAccept = StepAsk; +/** is the body of check.run. */ +export type CheckRunAccept = StepAsk; /** is one value of the state steps under the key .. */ export type StepsByNodeIDValue = Step; diff --git a/contracts/ts/seats/nodebuildgo/index.js b/contracts/ts/seats/nodebuildgo/index.js index cd6aadd5..e80d7956 100644 --- a/contracts/ts/seats/nodebuildgo/index.js +++ b/contracts/ts/seats/nodebuildgo/index.js @@ -16,9 +16,10 @@ export const verbs = { export const accepts = { delivery: "delivery", check: "check", - step: "step", + checkStep: "check.step", + deliveryStep: "delivery.step", recheck: "recheck", - run: "run", + checkRun: "check.run", }; export const events = { @@ -39,11 +40,13 @@ export const deliverySubject = "mesh.seat.node-build-go.accept.delivery"; export const checkSubject = "mesh.seat.node-build-go.accept.check"; -export const stepSubject = "mesh.seat.node-build-go.accept.step"; +export const checkStepSubject = "mesh.seat.node-build-go.accept.check.step"; + +export const deliveryStepSubject = "mesh.seat.node-build-go.accept.delivery.step"; export const recheckSubject = "mesh.seat.node-build-go.accept.recheck"; -export const runSubject = "mesh.seat.node-build-go.accept.run"; +export const checkRunSubject = "mesh.seat.node-build-go.accept.check.run"; export const states = { steps: "steps", diff --git a/contracts/ts/seats/nodebuildimage/index.d.ts b/contracts/ts/seats/nodebuildimage/index.d.ts index 719801c8..2cfdc13b 100644 --- a/contracts/ts/seats/nodebuildimage/index.d.ts +++ b/contracts/ts/seats/nodebuildimage/index.d.ts @@ -18,7 +18,8 @@ export declare const verbs: { export declare const accepts: { readonly delivery: "delivery"; readonly check: "check"; - readonly step: "step"; + readonly checkStep: "check.step"; + readonly deliveryStep: "delivery.step"; readonly recheck: "recheck"; }; @@ -38,7 +39,9 @@ export declare const deliverySubject: "mesh.seat.node-build-image.accept.deliver export declare const checkSubject: "mesh.seat.node-build-image.accept.check"; -export declare const stepSubject: "mesh.seat.node-build-image.accept.step"; +export declare const checkStepSubject: "mesh.seat.node-build-image.accept.check.step"; + +export declare const deliveryStepSubject: "mesh.seat.node-build-image.accept.delivery.step"; export declare const recheckSubject: "mesh.seat.node-build-image.accept.recheck"; @@ -148,8 +151,11 @@ export type DeliveryAccept = StepAsk; /** is the body of check. */ export type CheckAccept = StepAsk; -/** is the body of step. */ -export type StepAccept = StepAsk; +/** is the body of check.step. */ +export type CheckStepAccept = StepAsk; + +/** is the body of delivery.step. */ +export type DeliveryStepAccept = StepAsk; /** is the body of recheck. */ export type RecheckAccept = StepAsk; diff --git a/contracts/ts/seats/nodebuildimage/index.js b/contracts/ts/seats/nodebuildimage/index.js index ff428f65..6df298da 100644 --- a/contracts/ts/seats/nodebuildimage/index.js +++ b/contracts/ts/seats/nodebuildimage/index.js @@ -16,7 +16,8 @@ export const verbs = { export const accepts = { delivery: "delivery", check: "check", - step: "step", + checkStep: "check.step", + deliveryStep: "delivery.step", recheck: "recheck", }; @@ -38,7 +39,9 @@ export const deliverySubject = "mesh.seat.node-build-image.accept.delivery"; export const checkSubject = "mesh.seat.node-build-image.accept.check"; -export const stepSubject = "mesh.seat.node-build-image.accept.step"; +export const checkStepSubject = "mesh.seat.node-build-image.accept.check.step"; + +export const deliveryStepSubject = "mesh.seat.node-build-image.accept.delivery.step"; export const recheckSubject = "mesh.seat.node-build-image.accept.recheck"; diff --git a/contracts/ts/seats/nodebuildnode/index.d.ts b/contracts/ts/seats/nodebuildnode/index.d.ts index 179ffa27..3a87dc86 100644 --- a/contracts/ts/seats/nodebuildnode/index.d.ts +++ b/contracts/ts/seats/nodebuildnode/index.d.ts @@ -18,7 +18,8 @@ export declare const verbs: { export declare const accepts: { readonly delivery: "delivery"; readonly check: "check"; - readonly step: "step"; + readonly checkStep: "check.step"; + readonly deliveryStep: "delivery.step"; readonly recheck: "recheck"; }; @@ -38,7 +39,9 @@ export declare const deliverySubject: "mesh.seat.node-build-node.accept.delivery export declare const checkSubject: "mesh.seat.node-build-node.accept.check"; -export declare const stepSubject: "mesh.seat.node-build-node.accept.step"; +export declare const checkStepSubject: "mesh.seat.node-build-node.accept.check.step"; + +export declare const deliveryStepSubject: "mesh.seat.node-build-node.accept.delivery.step"; export declare const recheckSubject: "mesh.seat.node-build-node.accept.recheck"; @@ -148,8 +151,11 @@ export type DeliveryAccept = StepAsk; /** is the body of check. */ export type CheckAccept = StepAsk; -/** is the body of step. */ -export type StepAccept = StepAsk; +/** is the body of check.step. */ +export type CheckStepAccept = StepAsk; + +/** is the body of delivery.step. */ +export type DeliveryStepAccept = StepAsk; /** is the body of recheck. */ export type RecheckAccept = StepAsk; diff --git a/contracts/ts/seats/nodebuildnode/index.js b/contracts/ts/seats/nodebuildnode/index.js index 68b613c4..3c9047d8 100644 --- a/contracts/ts/seats/nodebuildnode/index.js +++ b/contracts/ts/seats/nodebuildnode/index.js @@ -16,7 +16,8 @@ export const verbs = { export const accepts = { delivery: "delivery", check: "check", - step: "step", + checkStep: "check.step", + deliveryStep: "delivery.step", recheck: "recheck", }; @@ -38,7 +39,9 @@ export const deliverySubject = "mesh.seat.node-build-node.accept.delivery"; export const checkSubject = "mesh.seat.node-build-node.accept.check"; -export const stepSubject = "mesh.seat.node-build-node.accept.step"; +export const checkStepSubject = "mesh.seat.node-build-node.accept.check.step"; + +export const deliveryStepSubject = "mesh.seat.node-build-node.accept.delivery.step"; export const recheckSubject = "mesh.seat.node-build-node.accept.recheck"; diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go index a1f9db6a..9c949810 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go @@ -197,11 +197,11 @@ const trunkHead = "3333333333333333333333333333333333333333" // trunk writes the gate's source.main naming head as novox/mesh-catalog's trunk head, and answers its revision. func (b *bed) trunk(t *testing.T, head string) uint64 { t.Helper() - data, err := meshdeliveryclient.EncodeSource(meshdelivery.SourceByMainValue{V: keys.Version, Group: "g", Heads: map[string]string{"novox/mesh-catalog": head}}) + data, err := meshdeliveryclient.EncodeSource(meshdelivery.SourceByBranchValue{V: keys.Version, Group: "g", Heads: map[string]string{"novox/mesh-catalog": head}}) if err != nil { t.Fatal(err) } - rev, err := b.source.Put(b.ctx, meshdeliveryclient.SourceMainKey, data) + rev, err := b.source.Put(b.ctx, meshdeliveryclient.SourceKey("main"), data) if err != nil { t.Fatal(err) } diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/optional.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/optional.go index 09324c26..87ba0c67 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/optional.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/optional.go @@ -6,8 +6,6 @@ import ( "sync" "github.com/nats-io/nats.go/jetstream" - - "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient" ) // **A part does not stop for a bucket it can work without** (mesh-sdk process.EssentialBucket, OptionalBucket) (novox/hq issue 1945, met twice on 2026-10-25: the builder of @@ -43,7 +41,7 @@ func (t *trunkSource) ensure() error { if err != nil { return fmt.Errorf("the bucket %s cannot be read (%v)", sourceBucket, err) } - w, err := kv.Watch(t.ctx, meshdeliveryclient.SourceMainKey, jetstream.IncludeHistory()) + w, err := kv.WatchAll(t.ctx, jetstream.IncludeHistory()) // every watched branch's key: a revision names its head whichever branch it is of (design 47 G ยง15) if err != nil { return fmt.Errorf("the bucket %s cannot be watched (%v)", sourceBucket, err) }