mesh-delivery-contracts: the part build-step and the three build seats defined whole with their states (D-4, ADR 0634 §6; issue 1966)
This commit is contained in:
@@ -0,0 +1,447 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package nodebuildgo is the contract of the seat "node-build-go", defined whole (seats/node-build-go/seat.json): The Go build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
package nodebuildgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "node-build-go"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptRecheck = "recheck"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
const AcceptSubjectDelivery = "mesh.seat.node-build-go.accept.delivery"
|
||||
|
||||
// AcceptSubjectCheck is where check is sent.
|
||||
const AcceptSubjectCheck = "mesh.seat.node-build-go.accept.check"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-go.accept.recheck"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
func StepsByNodeIDKey(node, id string) string { return node + "." + id }
|
||||
|
||||
// ParseStepsByNodeIDKey reads the parts of a key of the form "<node>.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStepsByNodeIDKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeStepsByNodeIDValue reads one value of the state steps under the form "<node>.<id>", refusing a field StepsByNodeIDValue does not know and any text after the value.
|
||||
func DecodeStepsByNodeIDValue(raw []byte) (StepsByNodeIDValue, error) {
|
||||
var v StepsByNodeIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByPausedNodeKey is the key of one value of the state pauses under the form "paused.<node>".
|
||||
func PausesByPausedNodeKey(node string) string { return "paused." + node }
|
||||
|
||||
// ParsePausesByPausedNodeKey reads the parts of a key of the form "paused.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByPausedNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "paused.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByPausedNodeValue reads one value of the state pauses under the form "paused.<node>", refusing a field PausesByPausedNodeValue does not know and any text after the value.
|
||||
func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
// ParsePausesByCapacityNodeKey reads the parts of a key of the form "capacity.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByCapacityNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "capacity.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[9:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByCapacityNodeValue reads one value of the state pauses under the form "capacity.<node>", refusing a field PausesByCapacityNodeValue does not know and any text after the value.
|
||||
func DecodePausesByCapacityNodeValue(raw []byte) (PausesByCapacityNodeValue, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ToolchainsByNodeLanguageKey is the key of one value of the state toolchains under the form "<node>.<language>".
|
||||
func ToolchainsByNodeLanguageKey(node, language string) string { return node + "." + language }
|
||||
|
||||
// ParseToolchainsByNodeLanguageKey reads the parts of a key of the form "<node>.<language>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseToolchainsByNodeLanguageKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeToolchainsByNodeLanguageValue reads one value of the state toolchains under the form "<node>.<language>", refusing a field ToolchainsByNodeLanguageValue does not know and any text after the value.
|
||||
func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageValue, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BuildAnswerArtifactsItem is a type of the contract.
|
||||
type BuildAnswerArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Digest string `json:"digest"`
|
||||
Reference string `json:"reference,omitempty"`
|
||||
}
|
||||
|
||||
// BuildAnswerToolchain is a type of the contract.
|
||||
type BuildAnswerToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// BuildAnswer is a type of the contract.
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuildAnswerArtifactsItem `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *BuildAnswerToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// Capacity is how many steps the node runs at once.
|
||||
type Capacity struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
BuildHours string `json:"build-hours,omitempty"`
|
||||
BuildHoursFault string `json:"build-hours-fault,omitempty"`
|
||||
ByCpu int64 `json:"by-cpu,omitempty"`
|
||||
Configured int64 `json:"configured"`
|
||||
ConfiguredFrom string `json:"configured-from,omitempty"`
|
||||
CoresPerStep float64 `json:"cores-per-step,omitempty"`
|
||||
Effective int64 `json:"effective"`
|
||||
Ineligible string `json:"ineligible,omitempty"`
|
||||
OutsideHours bool `json:"outside-hours,omitempty"`
|
||||
QuotaCores float64 `json:"quota-cores,omitempty"`
|
||||
QuotaFrom string `json:"quota-from,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestNeedsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestPackagesItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestPackagesItem struct {
|
||||
Digest string `json:"digest"`
|
||||
Package string `json:"package"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigest is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigest struct {
|
||||
Beside []string `json:"beside,omitempty"`
|
||||
JudgedBy string `json:"judged_by,omitempty"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Needs []CheckAnswerLevelsItemDigestNeedsItem `json:"needs,omitempty"`
|
||||
Packages []CheckAnswerLevelsItemDigestPackagesItem `json:"packages,omitempty"`
|
||||
WithoutTests []string `json:"without_tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemKeptItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemKeptItem struct {
|
||||
Digest string `json:"digest,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
Tests int64 `json:"tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemUnmetItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemUnmetItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItem struct {
|
||||
Digest *CheckAnswerLevelsItemDigest `json:"digest,omitempty"`
|
||||
Judged string `json:"judged,omitempty"`
|
||||
Kept []CheckAnswerLevelsItemKeptItem `json:"kept,omitempty"`
|
||||
Level string `json:"level"`
|
||||
Tests []any `json:"tests,omitempty"`
|
||||
Unmet []CheckAnswerLevelsItemUnmetItem `json:"unmet,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswer is a type of the contract.
|
||||
type CheckAnswer struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Levels []CheckAnswerLevelsItem `json:"levels,omitempty"`
|
||||
}
|
||||
|
||||
// ComposeAnswer is a type of the contract.
|
||||
type ComposeAnswer struct {
|
||||
Built bool `json:"built"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the compose-candidate verdict
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Pause is whether the node takes no new ask.
|
||||
type Pause struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Paused bool `json:"paused"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when (RFC 3339 time)
|
||||
Ended string `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt string `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// what the step answered
|
||||
Result any `json:"result,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started string `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildArtifactsItem is a type of the contract.
|
||||
type StepAskBuildArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
From string `json:"from,omitempty"`
|
||||
Seat string `json:"seat,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildToolchain is a type of the contract.
|
||||
type StepAskBuildToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// StepAskBuild is a type of the contract.
|
||||
type StepAskBuild struct {
|
||||
Artifacts []StepAskBuildArtifactsItem `json:"artifacts"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch,omitempty"`
|
||||
Fp string `json:"fp,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Publish bool `json:"publish,omitempty"`
|
||||
Toolchain *StepAskBuildToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCheck is a type of the contract.
|
||||
type StepAskCheck struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Levels []string `json:"levels"`
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Run string `json:"run,omitempty"`
|
||||
Runner string `json:"runner,omitempty"`
|
||||
RunnerWhen string `json:"runner_when,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCompose is a type of the contract.
|
||||
type StepAskCompose struct {
|
||||
Dir string `json:"dir"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Package string `json:"package"`
|
||||
Reader string `json:"reader,omitempty"`
|
||||
// the compose-candidate request
|
||||
Request any `json:"request"`
|
||||
}
|
||||
|
||||
// StepAsk is one ask of a build module.
|
||||
type StepAsk struct {
|
||||
Asker string `json:"asker"`
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
Build *StepAskBuild `json:"build,omitempty"`
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
// package to the tagged version a build pins
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
// go or typescript
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// CurrentInput is what current takes.
|
||||
type CurrentInput struct {
|
||||
}
|
||||
|
||||
// CurrentAnswer is what current answers.
|
||||
type CurrentAnswer = map[string]any
|
||||
|
||||
// PauseInput is what pause takes.
|
||||
type PauseInput struct {
|
||||
}
|
||||
|
||||
// PauseAnswer is what pause answers.
|
||||
type PauseAnswer = map[string]any
|
||||
|
||||
// ResumeInput is what resume takes.
|
||||
type ResumeInput struct {
|
||||
}
|
||||
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
@@ -0,0 +1,68 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package nodebuildgo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/node-build-go/fixtures: each decodes into its type, a field the type does not
|
||||
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
|
||||
func TestFixtures(t *testing.T) {
|
||||
cases := []struct {
|
||||
name, subject, given, wire string
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a running step", subject: "", given: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}", wire: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a paused node", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's capacity", subject: "", given: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}", wire: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's toolchain", subject: "", given: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}", wire: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a build ask", subject: "mesh.seat.node-build-go.accept.delivery", given: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}", wire: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}",
|
||||
decode: func(b []byte) (any, error) { var v DeliveryAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.delivery$")},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not decode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
back, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not encode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
var got, want any
|
||||
if err := json.Unmarshal(back, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
|
||||
}
|
||||
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
|
||||
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildgo
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,447 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package nodebuildimage is the contract of the seat "node-build-image", defined whole (seats/node-build-image/seat.json): The image build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
package nodebuildimage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "node-build-image"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptRecheck = "recheck"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
const AcceptSubjectDelivery = "mesh.seat.node-build-image.accept.delivery"
|
||||
|
||||
// AcceptSubjectCheck is where check is sent.
|
||||
const AcceptSubjectCheck = "mesh.seat.node-build-image.accept.check"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-image.accept.recheck"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
func StepsByNodeIDKey(node, id string) string { return node + "." + id }
|
||||
|
||||
// ParseStepsByNodeIDKey reads the parts of a key of the form "<node>.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStepsByNodeIDKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeStepsByNodeIDValue reads one value of the state steps under the form "<node>.<id>", refusing a field StepsByNodeIDValue does not know and any text after the value.
|
||||
func DecodeStepsByNodeIDValue(raw []byte) (StepsByNodeIDValue, error) {
|
||||
var v StepsByNodeIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByPausedNodeKey is the key of one value of the state pauses under the form "paused.<node>".
|
||||
func PausesByPausedNodeKey(node string) string { return "paused." + node }
|
||||
|
||||
// ParsePausesByPausedNodeKey reads the parts of a key of the form "paused.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByPausedNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "paused.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByPausedNodeValue reads one value of the state pauses under the form "paused.<node>", refusing a field PausesByPausedNodeValue does not know and any text after the value.
|
||||
func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
// ParsePausesByCapacityNodeKey reads the parts of a key of the form "capacity.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByCapacityNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "capacity.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[9:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByCapacityNodeValue reads one value of the state pauses under the form "capacity.<node>", refusing a field PausesByCapacityNodeValue does not know and any text after the value.
|
||||
func DecodePausesByCapacityNodeValue(raw []byte) (PausesByCapacityNodeValue, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ToolchainsByNodeLanguageKey is the key of one value of the state toolchains under the form "<node>.<language>".
|
||||
func ToolchainsByNodeLanguageKey(node, language string) string { return node + "." + language }
|
||||
|
||||
// ParseToolchainsByNodeLanguageKey reads the parts of a key of the form "<node>.<language>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseToolchainsByNodeLanguageKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeToolchainsByNodeLanguageValue reads one value of the state toolchains under the form "<node>.<language>", refusing a field ToolchainsByNodeLanguageValue does not know and any text after the value.
|
||||
func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageValue, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BuildAnswerArtifactsItem is a type of the contract.
|
||||
type BuildAnswerArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Digest string `json:"digest"`
|
||||
Reference string `json:"reference,omitempty"`
|
||||
}
|
||||
|
||||
// BuildAnswerToolchain is a type of the contract.
|
||||
type BuildAnswerToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// BuildAnswer is a type of the contract.
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuildAnswerArtifactsItem `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *BuildAnswerToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// Capacity is how many steps the node runs at once.
|
||||
type Capacity struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
BuildHours string `json:"build-hours,omitempty"`
|
||||
BuildHoursFault string `json:"build-hours-fault,omitempty"`
|
||||
ByCpu int64 `json:"by-cpu,omitempty"`
|
||||
Configured int64 `json:"configured"`
|
||||
ConfiguredFrom string `json:"configured-from,omitempty"`
|
||||
CoresPerStep float64 `json:"cores-per-step,omitempty"`
|
||||
Effective int64 `json:"effective"`
|
||||
Ineligible string `json:"ineligible,omitempty"`
|
||||
OutsideHours bool `json:"outside-hours,omitempty"`
|
||||
QuotaCores float64 `json:"quota-cores,omitempty"`
|
||||
QuotaFrom string `json:"quota-from,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestNeedsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestPackagesItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestPackagesItem struct {
|
||||
Digest string `json:"digest"`
|
||||
Package string `json:"package"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigest is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigest struct {
|
||||
Beside []string `json:"beside,omitempty"`
|
||||
JudgedBy string `json:"judged_by,omitempty"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Needs []CheckAnswerLevelsItemDigestNeedsItem `json:"needs,omitempty"`
|
||||
Packages []CheckAnswerLevelsItemDigestPackagesItem `json:"packages,omitempty"`
|
||||
WithoutTests []string `json:"without_tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemKeptItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemKeptItem struct {
|
||||
Digest string `json:"digest,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
Tests int64 `json:"tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemUnmetItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemUnmetItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItem struct {
|
||||
Digest *CheckAnswerLevelsItemDigest `json:"digest,omitempty"`
|
||||
Judged string `json:"judged,omitempty"`
|
||||
Kept []CheckAnswerLevelsItemKeptItem `json:"kept,omitempty"`
|
||||
Level string `json:"level"`
|
||||
Tests []any `json:"tests,omitempty"`
|
||||
Unmet []CheckAnswerLevelsItemUnmetItem `json:"unmet,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswer is a type of the contract.
|
||||
type CheckAnswer struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Levels []CheckAnswerLevelsItem `json:"levels,omitempty"`
|
||||
}
|
||||
|
||||
// ComposeAnswer is a type of the contract.
|
||||
type ComposeAnswer struct {
|
||||
Built bool `json:"built"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the compose-candidate verdict
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Pause is whether the node takes no new ask.
|
||||
type Pause struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Paused bool `json:"paused"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when (RFC 3339 time)
|
||||
Ended string `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt string `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// what the step answered
|
||||
Result any `json:"result,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started string `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildArtifactsItem is a type of the contract.
|
||||
type StepAskBuildArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
From string `json:"from,omitempty"`
|
||||
Seat string `json:"seat,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildToolchain is a type of the contract.
|
||||
type StepAskBuildToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// StepAskBuild is a type of the contract.
|
||||
type StepAskBuild struct {
|
||||
Artifacts []StepAskBuildArtifactsItem `json:"artifacts"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch,omitempty"`
|
||||
Fp string `json:"fp,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Publish bool `json:"publish,omitempty"`
|
||||
Toolchain *StepAskBuildToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCheck is a type of the contract.
|
||||
type StepAskCheck struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Levels []string `json:"levels"`
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Run string `json:"run,omitempty"`
|
||||
Runner string `json:"runner,omitempty"`
|
||||
RunnerWhen string `json:"runner_when,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCompose is a type of the contract.
|
||||
type StepAskCompose struct {
|
||||
Dir string `json:"dir"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Package string `json:"package"`
|
||||
Reader string `json:"reader,omitempty"`
|
||||
// the compose-candidate request
|
||||
Request any `json:"request"`
|
||||
}
|
||||
|
||||
// StepAsk is one ask of a build module.
|
||||
type StepAsk struct {
|
||||
Asker string `json:"asker"`
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
Build *StepAskBuild `json:"build,omitempty"`
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
// package to the tagged version a build pins
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
// go or typescript
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// CurrentInput is what current takes.
|
||||
type CurrentInput struct {
|
||||
}
|
||||
|
||||
// CurrentAnswer is what current answers.
|
||||
type CurrentAnswer = map[string]any
|
||||
|
||||
// PauseInput is what pause takes.
|
||||
type PauseInput struct {
|
||||
}
|
||||
|
||||
// PauseAnswer is what pause answers.
|
||||
type PauseAnswer = map[string]any
|
||||
|
||||
// ResumeInput is what resume takes.
|
||||
type ResumeInput struct {
|
||||
}
|
||||
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
@@ -0,0 +1,68 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package nodebuildimage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/node-build-image/fixtures: each decodes into its type, a field the type does not
|
||||
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
|
||||
func TestFixtures(t *testing.T) {
|
||||
cases := []struct {
|
||||
name, subject, given, wire string
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a running step", subject: "", given: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}", wire: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a paused node", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's capacity", subject: "", given: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}", wire: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's toolchain", subject: "", given: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}", wire: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a build ask", subject: "mesh.seat.node-build-image.accept.delivery", given: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}", wire: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}",
|
||||
decode: func(b []byte) (any, error) { var v DeliveryAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.delivery$")},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not decode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
back, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not encode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
var got, want any
|
||||
if err := json.Unmarshal(back, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
|
||||
}
|
||||
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
|
||||
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildimage
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,447 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package nodebuildnode is the contract of the seat "node-build-node", defined whole (seats/node-build-node/seat.json): The Node build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
package nodebuildnode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "node-build-node"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptRecheck = "recheck"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbCurrent, VerbPause, VerbResume}
|
||||
}
|
||||
|
||||
// AcceptSubjectDelivery is where delivery is sent.
|
||||
const AcceptSubjectDelivery = "mesh.seat.node-build-node.accept.delivery"
|
||||
|
||||
// AcceptSubjectCheck is where check is sent.
|
||||
const AcceptSubjectCheck = "mesh.seat.node-build-node.accept.check"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-node.accept.recheck"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
func StepsByNodeIDKey(node, id string) string { return node + "." + id }
|
||||
|
||||
// ParseStepsByNodeIDKey reads the parts of a key of the form "<node>.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStepsByNodeIDKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeStepsByNodeIDValue reads one value of the state steps under the form "<node>.<id>", refusing a field StepsByNodeIDValue does not know and any text after the value.
|
||||
func DecodeStepsByNodeIDValue(raw []byte) (StepsByNodeIDValue, error) {
|
||||
var v StepsByNodeIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByPausedNodeKey is the key of one value of the state pauses under the form "paused.<node>".
|
||||
func PausesByPausedNodeKey(node string) string { return "paused." + node }
|
||||
|
||||
// ParsePausesByPausedNodeKey reads the parts of a key of the form "paused.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByPausedNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "paused.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[7:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByPausedNodeValue reads one value of the state pauses under the form "paused.<node>", refusing a field PausesByPausedNodeValue does not know and any text after the value.
|
||||
func DecodePausesByPausedNodeValue(raw []byte) (PausesByPausedNodeValue, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PausesByCapacityNodeKey is the key of one value of the state pauses under the form "capacity.<node>".
|
||||
func PausesByCapacityNodeKey(node string) string { return "capacity." + node }
|
||||
|
||||
// ParsePausesByCapacityNodeKey reads the parts of a key of the form "capacity.<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePausesByCapacityNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "capacity.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[9:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodePausesByCapacityNodeValue reads one value of the state pauses under the form "capacity.<node>", refusing a field PausesByCapacityNodeValue does not know and any text after the value.
|
||||
func DecodePausesByCapacityNodeValue(raw []byte) (PausesByCapacityNodeValue, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ToolchainsByNodeLanguageKey is the key of one value of the state toolchains under the form "<node>.<language>".
|
||||
func ToolchainsByNodeLanguageKey(node, language string) string { return node + "." + language }
|
||||
|
||||
// ParseToolchainsByNodeLanguageKey reads the parts of a key of the form "<node>.<language>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseToolchainsByNodeLanguageKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeToolchainsByNodeLanguageValue reads one value of the state toolchains under the form "<node>.<language>", refusing a field ToolchainsByNodeLanguageValue does not know and any text after the value.
|
||||
func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageValue, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// BuildAnswerArtifactsItem is a type of the contract.
|
||||
type BuildAnswerArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Digest string `json:"digest"`
|
||||
Reference string `json:"reference,omitempty"`
|
||||
}
|
||||
|
||||
// BuildAnswerToolchain is a type of the contract.
|
||||
type BuildAnswerToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// BuildAnswer is a type of the contract.
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuildAnswerArtifactsItem `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *BuildAnswerToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// Capacity is how many steps the node runs at once.
|
||||
type Capacity struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
BuildHours string `json:"build-hours,omitempty"`
|
||||
BuildHoursFault string `json:"build-hours-fault,omitempty"`
|
||||
ByCpu int64 `json:"by-cpu,omitempty"`
|
||||
Configured int64 `json:"configured"`
|
||||
ConfiguredFrom string `json:"configured-from,omitempty"`
|
||||
CoresPerStep float64 `json:"cores-per-step,omitempty"`
|
||||
Effective int64 `json:"effective"`
|
||||
Ineligible string `json:"ineligible,omitempty"`
|
||||
OutsideHours bool `json:"outside-hours,omitempty"`
|
||||
QuotaCores float64 `json:"quota-cores,omitempty"`
|
||||
QuotaFrom string `json:"quota-from,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestNeedsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigestPackagesItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigestPackagesItem struct {
|
||||
Digest string `json:"digest"`
|
||||
Package string `json:"package"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemDigest is a type of the contract.
|
||||
type CheckAnswerLevelsItemDigest struct {
|
||||
Beside []string `json:"beside,omitempty"`
|
||||
JudgedBy string `json:"judged_by,omitempty"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Needs []CheckAnswerLevelsItemDigestNeedsItem `json:"needs,omitempty"`
|
||||
Packages []CheckAnswerLevelsItemDigestPackagesItem `json:"packages,omitempty"`
|
||||
WithoutTests []string `json:"without_tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemKeptItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemKeptItem struct {
|
||||
Digest string `json:"digest,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
Tests int64 `json:"tests,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItemUnmetItem is a type of the contract.
|
||||
type CheckAnswerLevelsItemUnmetItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswerLevelsItem is a type of the contract.
|
||||
type CheckAnswerLevelsItem struct {
|
||||
Digest *CheckAnswerLevelsItemDigest `json:"digest,omitempty"`
|
||||
Judged string `json:"judged,omitempty"`
|
||||
Kept []CheckAnswerLevelsItemKeptItem `json:"kept,omitempty"`
|
||||
Level string `json:"level"`
|
||||
Tests []any `json:"tests,omitempty"`
|
||||
Unmet []CheckAnswerLevelsItemUnmetItem `json:"unmet,omitempty"`
|
||||
}
|
||||
|
||||
// CheckAnswer is a type of the contract.
|
||||
type CheckAnswer struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Levels []CheckAnswerLevelsItem `json:"levels,omitempty"`
|
||||
}
|
||||
|
||||
// ComposeAnswer is a type of the contract.
|
||||
type ComposeAnswer struct {
|
||||
Built bool `json:"built"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the compose-candidate verdict
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// Pause is whether the node takes no new ask.
|
||||
type Pause struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Paused bool `json:"paused"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Step is one step a build module runs on a node.
|
||||
type Step struct {
|
||||
// when (RFC 3339 time)
|
||||
Ended string `json:"ended,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Node string `json:"node"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
Phase string `json:"phase,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
PhaseAt string `json:"phase-at,omitempty"`
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// what the step answered
|
||||
Result any `json:"result,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
Started string `json:"started"`
|
||||
// running, passed, failed or refused
|
||||
State string `json:"state"`
|
||||
Tool string `json:"tool"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildArtifactsItem is a type of the contract.
|
||||
type StepAskBuildArtifactsItem struct {
|
||||
Artifact string `json:"artifact"`
|
||||
From string `json:"from,omitempty"`
|
||||
Seat string `json:"seat,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskBuildToolchain is a type of the contract.
|
||||
type StepAskBuildToolchain struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// StepAskBuild is a type of the contract.
|
||||
type StepAskBuild struct {
|
||||
Artifacts []StepAskBuildArtifactsItem `json:"artifacts"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch,omitempty"`
|
||||
Fp string `json:"fp,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Publish bool `json:"publish,omitempty"`
|
||||
Toolchain *StepAskBuildToolchain `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCheck is a type of the contract.
|
||||
type StepAskCheck struct {
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Levels []string `json:"levels"`
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Run string `json:"run,omitempty"`
|
||||
Runner string `json:"runner,omitempty"`
|
||||
RunnerWhen string `json:"runner_when,omitempty"`
|
||||
}
|
||||
|
||||
// StepAskCompose is a type of the contract.
|
||||
type StepAskCompose struct {
|
||||
Dir string `json:"dir"`
|
||||
// what the build module fetches: the repository, commit and directory, as the indexer states it
|
||||
Fetch any `json:"fetch"`
|
||||
Package string `json:"package"`
|
||||
Reader string `json:"reader,omitempty"`
|
||||
// the compose-candidate request
|
||||
Request any `json:"request"`
|
||||
}
|
||||
|
||||
// StepAsk is one ask of a build module.
|
||||
type StepAsk struct {
|
||||
Asker string `json:"asker"`
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
Build *StepAskBuild `json:"build,omitempty"`
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
// package to the tagged version a build pins
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
At string `json:"at,omitempty"`
|
||||
// go or typescript
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// CurrentInput is what current takes.
|
||||
type CurrentInput struct {
|
||||
}
|
||||
|
||||
// CurrentAnswer is what current answers.
|
||||
type CurrentAnswer = map[string]any
|
||||
|
||||
// PauseInput is what pause takes.
|
||||
type PauseInput struct {
|
||||
}
|
||||
|
||||
// PauseAnswer is what pause answers.
|
||||
type PauseAnswer = map[string]any
|
||||
|
||||
// ResumeInput is what resume takes.
|
||||
type ResumeInput struct {
|
||||
}
|
||||
|
||||
// ResumeAnswer is what resume answers.
|
||||
type ResumeAnswer = map[string]any
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
// PausesByPausedNodeValue is one value of the state pauses under the key paused.<node>.
|
||||
type PausesByPausedNodeValue = Pause
|
||||
|
||||
// PausesByCapacityNodeValue is one value of the state pauses under the key capacity.<node>.
|
||||
type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
@@ -0,0 +1,68 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package nodebuildnode
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/node-build-node/fixtures: each decodes into its type, a field the type does not
|
||||
// know is dropped (ADR 0608 §6), and it reads back as its wire says; each subject named is the contract's.
|
||||
func TestFixtures(t *testing.T) {
|
||||
cases := []struct {
|
||||
name, subject, given, wire string
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a running step", subject: "", given: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}", wire: "{\"id\":\"a1b2\",\"node\":\"ace\",\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"running\",\"tool\":\"build\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a paused node", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"operator@shanks\",\"paused\":true,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByPausedNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's capacity", subject: "", given: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}", wire: "{\"configured\":2,\"effective\":2,\"v\":1,\"why\":\"the configured steps fit the cores\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PausesByCapacityNodeValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a node's toolchain", subject: "", given: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}", wire: "{\"language\":\"go\",\"recipe\":\"1\",\"v\":1,\"version\":\"1.26.0\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v ToolchainsByNodeLanguageValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a build ask", subject: "mesh.seat.node-build-node.accept.delivery", given: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}", wire: "{\"asker\":\"mesh-delivery-builder\",\"build\":{\"artifacts\":[{\"artifact\":\"go\"}],\"module\":\"nats\"},\"id\":\"a1b2\",\"kind\":\"build\",\"language\":\"go\"}",
|
||||
decode: func(b []byte) (any, error) { var v DeliveryAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.delivery$")},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not decode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
back, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Errorf("%s: does not encode: %v", c.name, err)
|
||||
continue
|
||||
}
|
||||
var got, want any
|
||||
if err := json.Unmarshal(back, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal([]byte(c.wire), &want); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%s: reads back as %s, want %s", c.name, back, c.wire)
|
||||
}
|
||||
if c.subjectIs != nil && !c.subjectIs.MatchString(c.subject) {
|
||||
t.Errorf("%s: subject %q is not the contract's %s", c.name, c.subject, c.subjectIs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildnode
|
||||
|
||||
go 1.26.0
|
||||
@@ -53,6 +53,36 @@
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-nodebuildgo",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/nodebuildgo"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-nodebuildimage",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/nodebuildimage"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-nodebuildnode",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/nodebuildnode"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-npmpackageregistry",
|
||||
"kind": "package",
|
||||
@@ -159,6 +189,36 @@
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-nodebuildgo",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/nodebuildgo"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-nodebuildimage",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/nodebuildimage"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-nodebuildnode",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/nodebuildnode"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-npmpackageregistry",
|
||||
"kind": "package",
|
||||
|
||||
@@ -0,0 +1,588 @@
|
||||
{
|
||||
"format": 1,
|
||||
"part": "build-step",
|
||||
"description": "What the three build seats share: the verbs that read and steer a node's builds, and the layouts of the asks they accept and the steps they keep. A seat lists its states against these (a part carries no states).",
|
||||
"verbs": [
|
||||
{
|
||||
"name": "current",
|
||||
"description": "The asks this node runs now (each ask's id, kind, module and when it started), its build capacity, and whether it is paused, taking no new ask.",
|
||||
"input": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"description": "the steps running, the capacity and whether paused"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pause",
|
||||
"description": "Take no new ask on this node until resumed; an ask running here ends in its place. Kept across a restart of the build module. A capacity of 0 is the lasting way to keep a node from building.",
|
||||
"input": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"description": "whether the node is paused"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "resume",
|
||||
"description": "Take asks again on this node.",
|
||||
"input": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"description": "whether the node is paused"
|
||||
}
|
||||
}
|
||||
],
|
||||
"defs": {
|
||||
"StepAsk": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"description": "build, check or compose"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"description": "go, typescript or image"
|
||||
},
|
||||
"asker": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
},
|
||||
"build": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"module": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"fp": {
|
||||
"type": "string"
|
||||
},
|
||||
"fetch": {
|
||||
"description": "what the build module fetches: the repository, commit and directory, as the indexer states it"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"artifact": {
|
||||
"type": "string"
|
||||
},
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"seat": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"artifact"
|
||||
]
|
||||
}
|
||||
},
|
||||
"publish": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"toolchain": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"recipe": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"language",
|
||||
"version",
|
||||
"recipe"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"module",
|
||||
"artifacts"
|
||||
]
|
||||
},
|
||||
"check": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fetch": {
|
||||
"description": "what the build module fetches: the repository, commit and directory, as the indexer states it"
|
||||
},
|
||||
"levels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "unit or integration"
|
||||
}
|
||||
},
|
||||
"kept": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"runner": {
|
||||
"type": "string"
|
||||
},
|
||||
"runner_when": {
|
||||
"type": "string"
|
||||
},
|
||||
"run": {
|
||||
"type": "string"
|
||||
},
|
||||
"packages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fetch",
|
||||
"levels"
|
||||
]
|
||||
},
|
||||
"compose": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fetch": {
|
||||
"description": "what the build module fetches: the repository, commit and directory, as the indexer states it"
|
||||
},
|
||||
"dir": {
|
||||
"type": "string"
|
||||
},
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"request": {
|
||||
"description": "the compose-candidate request"
|
||||
},
|
||||
"reader": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fetch",
|
||||
"dir",
|
||||
"package",
|
||||
"request"
|
||||
]
|
||||
},
|
||||
"needs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"packages": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "package to the tagged version a build pins"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"kind",
|
||||
"language",
|
||||
"asker"
|
||||
],
|
||||
"description": "one ask of a build module"
|
||||
},
|
||||
"BuildAnswer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"artifacts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"artifact": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string"
|
||||
},
|
||||
"reference": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"artifact",
|
||||
"digest"
|
||||
]
|
||||
}
|
||||
},
|
||||
"toolchain": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"recipe": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"language",
|
||||
"version",
|
||||
"recipe"
|
||||
]
|
||||
},
|
||||
"imports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"out-of-step": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"artifacts"
|
||||
]
|
||||
},
|
||||
"CheckAnswer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fetch": {
|
||||
"description": "what the build module fetches: the repository, commit and directory, as the indexer states it"
|
||||
},
|
||||
"levels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string"
|
||||
},
|
||||
"judged": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string"
|
||||
},
|
||||
"packages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"package",
|
||||
"digest"
|
||||
]
|
||||
}
|
||||
},
|
||||
"beside": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"without_tests": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"judged_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"needs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"needs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kept": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"digest": {
|
||||
"type": "string"
|
||||
},
|
||||
"tests": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tests": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "one test's result"
|
||||
}
|
||||
},
|
||||
"unmet": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"type": "string"
|
||||
},
|
||||
"needs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"level"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fetch"
|
||||
]
|
||||
},
|
||||
"ComposeAnswer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"built": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"verdict": {
|
||||
"description": "the compose-candidate verdict"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"built"
|
||||
]
|
||||
},
|
||||
"Step": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"tool": {
|
||||
"type": "string"
|
||||
},
|
||||
"node": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "running, passed, failed or refused"
|
||||
},
|
||||
"started": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
},
|
||||
"ended": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
},
|
||||
"result": {
|
||||
"description": "what the step answered"
|
||||
},
|
||||
"what": {
|
||||
"type": "string"
|
||||
},
|
||||
"phase": {
|
||||
"type": "string"
|
||||
},
|
||||
"phase-at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"tool",
|
||||
"node",
|
||||
"state",
|
||||
"started"
|
||||
],
|
||||
"description": "one step a build module runs on a node"
|
||||
},
|
||||
"Toolchain": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"description": "go or typescript"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"recipe": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"language",
|
||||
"version",
|
||||
"recipe"
|
||||
],
|
||||
"description": "the toolchain a node reports"
|
||||
},
|
||||
"Pause": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"paused": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"by": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"paused"
|
||||
],
|
||||
"description": "whether the node takes no new ask"
|
||||
},
|
||||
"Capacity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "integer",
|
||||
"description": "the layout version"
|
||||
},
|
||||
"effective": {
|
||||
"type": "integer"
|
||||
},
|
||||
"configured": {
|
||||
"type": "integer"
|
||||
},
|
||||
"configured-from": {
|
||||
"type": "string"
|
||||
},
|
||||
"quota-cores": {
|
||||
"type": "number"
|
||||
},
|
||||
"quota-from": {
|
||||
"type": "string"
|
||||
},
|
||||
"cores-per-step": {
|
||||
"type": "number"
|
||||
},
|
||||
"by-cpu": {
|
||||
"type": "integer"
|
||||
},
|
||||
"build-hours": {
|
||||
"type": "string"
|
||||
},
|
||||
"outside-hours": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"build-hours-fault": {
|
||||
"type": "string"
|
||||
},
|
||||
"ineligible": {
|
||||
"type": "string"
|
||||
},
|
||||
"why": {
|
||||
"type": "string"
|
||||
},
|
||||
"at": {
|
||||
"type": "string",
|
||||
"description": "when (RFC 3339 time)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"effective",
|
||||
"configured",
|
||||
"why"
|
||||
],
|
||||
"description": "how many steps the node runs at once"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
[
|
||||
{
|
||||
"name": "a running step",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "running",
|
||||
"started": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a paused node",
|
||||
"of": "state:pauses/paused.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"paused": true,
|
||||
"by": "operator@shanks",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's capacity",
|
||||
"of": "state:pauses/capacity.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"effective": 2,
|
||||
"configured": 2,
|
||||
"why": "the configured steps fit the cores"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's toolchain",
|
||||
"of": "state:toolchains/<node>.<language>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"language": "go",
|
||||
"version": "1.26.0",
|
||||
"recipe": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a build ask",
|
||||
"of": "accept:delivery",
|
||||
"subject": "mesh.seat.node-build-go.accept.delivery",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"kind": "build",
|
||||
"language": "go",
|
||||
"asker": "mesh-delivery-builder",
|
||||
"build": {
|
||||
"module": "nats",
|
||||
"artifacts": [
|
||||
{
|
||||
"artifact": "go"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seat": "node-build-go",
|
||||
"scope": "node",
|
||||
"grain": "whole",
|
||||
"decision": "novox/hq ADR 0525, ADR 0536, ADR 0553",
|
||||
"pulled-by-kind": true,
|
||||
"yields": true,
|
||||
"accepts": [
|
||||
{
|
||||
"name": "delivery",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "check",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "recheck",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "The Go build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.",
|
||||
"includes": [
|
||||
"build-step"
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"name": "steps",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Step"
|
||||
},
|
||||
"description": "a step on a node"
|
||||
}
|
||||
],
|
||||
"description": "the steps this module runs",
|
||||
"history": 5
|
||||
},
|
||||
{
|
||||
"name": "pauses",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "paused.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Pause"
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Capacity"
|
||||
},
|
||||
"description": "a node's capacity"
|
||||
}
|
||||
],
|
||||
"description": "the pause and the capacity of each node",
|
||||
"history": 1
|
||||
},
|
||||
{
|
||||
"name": "toolchains",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<language>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Toolchain"
|
||||
},
|
||||
"description": "the toolchain a node reports"
|
||||
}
|
||||
],
|
||||
"description": "the toolchains the nodes report",
|
||||
"history": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
[
|
||||
{
|
||||
"name": "a running step",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "running",
|
||||
"started": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a paused node",
|
||||
"of": "state:pauses/paused.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"paused": true,
|
||||
"by": "operator@shanks",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's capacity",
|
||||
"of": "state:pauses/capacity.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"effective": 2,
|
||||
"configured": 2,
|
||||
"why": "the configured steps fit the cores"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's toolchain",
|
||||
"of": "state:toolchains/<node>.<language>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"language": "go",
|
||||
"version": "1.26.0",
|
||||
"recipe": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a build ask",
|
||||
"of": "accept:delivery",
|
||||
"subject": "mesh.seat.node-build-image.accept.delivery",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"kind": "build",
|
||||
"language": "go",
|
||||
"asker": "mesh-delivery-builder",
|
||||
"build": {
|
||||
"module": "nats",
|
||||
"artifacts": [
|
||||
{
|
||||
"artifact": "go"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seat": "node-build-image",
|
||||
"scope": "node",
|
||||
"grain": "whole",
|
||||
"decision": "novox/hq ADR 0525, ADR 0536, ADR 0553",
|
||||
"pulled-by-kind": true,
|
||||
"yields": true,
|
||||
"accepts": [
|
||||
{
|
||||
"name": "delivery",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "check",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "recheck",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "The image build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.",
|
||||
"includes": [
|
||||
"build-step"
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"name": "steps",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Step"
|
||||
},
|
||||
"description": "a step on a node"
|
||||
}
|
||||
],
|
||||
"description": "the steps this module runs",
|
||||
"history": 5
|
||||
},
|
||||
{
|
||||
"name": "pauses",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "paused.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Pause"
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Capacity"
|
||||
},
|
||||
"description": "a node's capacity"
|
||||
}
|
||||
],
|
||||
"description": "the pause and the capacity of each node",
|
||||
"history": 1
|
||||
},
|
||||
{
|
||||
"name": "toolchains",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<language>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Toolchain"
|
||||
},
|
||||
"description": "the toolchain a node reports"
|
||||
}
|
||||
],
|
||||
"description": "the toolchains the nodes report",
|
||||
"history": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
[
|
||||
{
|
||||
"name": "a running step",
|
||||
"of": "state:steps/<node>.<id>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"id": "a1b2",
|
||||
"tool": "build",
|
||||
"node": "ace",
|
||||
"state": "running",
|
||||
"started": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a paused node",
|
||||
"of": "state:pauses/paused.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"paused": true,
|
||||
"by": "operator@shanks",
|
||||
"at": "2026-11-05T10:00:00Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's capacity",
|
||||
"of": "state:pauses/capacity.<node>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"effective": 2,
|
||||
"configured": 2,
|
||||
"why": "the configured steps fit the cores"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a node's toolchain",
|
||||
"of": "state:toolchains/<node>.<language>",
|
||||
"given": {
|
||||
"v": 1,
|
||||
"language": "go",
|
||||
"version": "1.26.0",
|
||||
"recipe": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a build ask",
|
||||
"of": "accept:delivery",
|
||||
"subject": "mesh.seat.node-build-node.accept.delivery",
|
||||
"given": {
|
||||
"id": "a1b2",
|
||||
"kind": "build",
|
||||
"language": "go",
|
||||
"asker": "mesh-delivery-builder",
|
||||
"build": {
|
||||
"module": "nats",
|
||||
"artifacts": [
|
||||
{
|
||||
"artifact": "go"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seat": "node-build-node",
|
||||
"scope": "node",
|
||||
"grain": "whole",
|
||||
"decision": "novox/hq ADR 0525, ADR 0536, ADR 0553",
|
||||
"pulled-by-kind": true,
|
||||
"yields": true,
|
||||
"accepts": [
|
||||
{
|
||||
"name": "delivery",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "check",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "recheck",
|
||||
"body": {
|
||||
"$ref": "#/defs/StepAsk"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "The Node build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.",
|
||||
"includes": [
|
||||
"build-step"
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"name": "steps",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<id>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Step"
|
||||
},
|
||||
"description": "a step on a node"
|
||||
}
|
||||
],
|
||||
"description": "the steps this module runs",
|
||||
"history": 5
|
||||
},
|
||||
{
|
||||
"name": "pauses",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "paused.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Pause"
|
||||
},
|
||||
"description": "whether a node is paused"
|
||||
},
|
||||
{
|
||||
"key": "capacity.<node>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Capacity"
|
||||
},
|
||||
"description": "a node's capacity"
|
||||
}
|
||||
],
|
||||
"description": "the pause and the capacity of each node",
|
||||
"history": 1
|
||||
},
|
||||
{
|
||||
"name": "toolchains",
|
||||
"template": "state",
|
||||
"key-forms": [
|
||||
{
|
||||
"key": "<node>.<language>",
|
||||
"value": {
|
||||
"$ref": "#/defs/Toolchain"
|
||||
},
|
||||
"description": "the toolchain a node reports"
|
||||
}
|
||||
],
|
||||
"description": "the toolchains the nodes report",
|
||||
"history": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-go",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-go",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-go, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-go",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "node-build-go", defined whole (seats/node-build-go/seat.json): The Go build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-go";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-go.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-go.accept.check";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-go.accept.recheck";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node: string, id: string): string {
|
||||
return node + "." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<id>", or undefined for a key of another form. */
|
||||
export function parseStepsByNodeIDKey(key: string): { node: string; id: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const id = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "paused.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByPausedNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("paused.")) return undefined;
|
||||
rest = rest.slice(7);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "capacity.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByCapacityNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("capacity.")) return undefined;
|
||||
rest = rest.slice(9);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state toolchains under the form "<node>.<language>". */
|
||||
export function toolchainsByNodeLanguageKey(node: string, language: string): string {
|
||||
return node + "." + language;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<language>", or undefined for a key of another form. */
|
||||
export function parseToolchainsByNodeLanguageKey(key: string): { node: string; language: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const language = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, language };
|
||||
}
|
||||
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
export type BuildAnswerArtifactsItem = buildStep.BuildAnswerArtifactsItem;
|
||||
export type BuildAnswerToolchain = buildStep.BuildAnswerToolchain;
|
||||
export type Capacity = buildStep.Capacity;
|
||||
export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type CheckAnswerLevelsItem = buildStep.CheckAnswerLevelsItem;
|
||||
export type CheckAnswerLevelsItemDigest = buildStep.CheckAnswerLevelsItemDigest;
|
||||
export type CheckAnswerLevelsItemDigestNeedsItem = buildStep.CheckAnswerLevelsItemDigestNeedsItem;
|
||||
export type CheckAnswerLevelsItemDigestPackagesItem = buildStep.CheckAnswerLevelsItemDigestPackagesItem;
|
||||
export type CheckAnswerLevelsItemKeptItem = buildStep.CheckAnswerLevelsItemKeptItem;
|
||||
export type CheckAnswerLevelsItemUnmetItem = buildStep.CheckAnswerLevelsItemUnmetItem;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Pause = buildStep.Pause;
|
||||
export type PauseAnswer = buildStep.PauseAnswer;
|
||||
export type PauseInput = buildStep.PauseInput;
|
||||
export type ResumeAnswer = buildStep.ResumeAnswer;
|
||||
export type ResumeInput = buildStep.ResumeInput;
|
||||
export type Step = buildStep.Step;
|
||||
export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskBuildArtifactsItem = buildStep.StepAskBuildArtifactsItem;
|
||||
export type StepAskBuildToolchain = buildStep.StepAskBuildToolchain;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
|
||||
/** is the body of delivery. */
|
||||
export type DeliveryAccept = StepAsk;
|
||||
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
/** is one value of the state steps under the key <node>.<id>. */
|
||||
export type StepsByNodeIDValue = Step;
|
||||
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "build-step" several seats include whole: What the three build seats share: the verbs that read and steer a node's builds, and the layouts of the asks they accept and the steps they keep. A seat lists its states against these (a part carries no states).
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export interface BuildAnswerArtifactsItem {
|
||||
"artifact": string;
|
||||
"digest": string;
|
||||
"reference"?: string;
|
||||
}
|
||||
|
||||
export interface BuildAnswerToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuildAnswerArtifactsItem[];
|
||||
"imports"?: string[];
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: BuildAnswerToolchain;
|
||||
}
|
||||
|
||||
/** how many steps the node runs at once */
|
||||
export interface Capacity {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build-hours"?: string;
|
||||
"build-hours-fault"?: string;
|
||||
"by-cpu"?: number;
|
||||
"configured": number;
|
||||
"configured-from"?: string;
|
||||
"cores-per-step"?: number;
|
||||
"effective": number;
|
||||
"ineligible"?: string;
|
||||
"outside-hours"?: boolean;
|
||||
"quota-cores"?: number;
|
||||
"quota-from"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestPackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigest {
|
||||
"beside"?: string[];
|
||||
"judged_by"?: string;
|
||||
"level"?: string;
|
||||
"needs"?: CheckAnswerLevelsItemDigestNeedsItem[];
|
||||
"packages"?: CheckAnswerLevelsItemDigestPackagesItem[];
|
||||
"without_tests"?: string[];
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemKeptItem {
|
||||
"digest"?: string;
|
||||
"package"?: string;
|
||||
"tests"?: number;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemUnmetItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItem {
|
||||
"digest"?: CheckAnswerLevelsItemDigest;
|
||||
"judged"?: string;
|
||||
"kept"?: CheckAnswerLevelsItemKeptItem[];
|
||||
"level": string;
|
||||
"tests"?: unknown[];
|
||||
"unmet"?: CheckAnswerLevelsItemUnmetItem[];
|
||||
}
|
||||
|
||||
export interface CheckAnswer {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"levels"?: CheckAnswerLevelsItem[];
|
||||
}
|
||||
|
||||
export interface ComposeAnswer {
|
||||
"built": boolean;
|
||||
"key"?: string;
|
||||
/** the compose-candidate verdict */
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** whether the node takes no new ask */
|
||||
export interface Pause {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"paused": boolean;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
/** what the step answered */
|
||||
"result"?: unknown;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildArtifactsItem {
|
||||
"artifact": string;
|
||||
"from"?: string;
|
||||
"seat"?: string;
|
||||
"version"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface StepAskBuild {
|
||||
"artifacts": StepAskBuildArtifactsItem[];
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch"?: unknown;
|
||||
"fp"?: string;
|
||||
"module": string;
|
||||
"path"?: string;
|
||||
"publish"?: boolean;
|
||||
"toolchain"?: StepAskBuildToolchain;
|
||||
}
|
||||
|
||||
export interface StepAskCheck {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"kept"?: boolean;
|
||||
"levels": string[];
|
||||
"packages"?: string[];
|
||||
"run"?: string;
|
||||
"runner"?: string;
|
||||
"runner_when"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskCompose {
|
||||
"dir": string;
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"package": string;
|
||||
"reader"?: string;
|
||||
/** the compose-candidate request */
|
||||
"request": unknown;
|
||||
}
|
||||
|
||||
/** one ask of a build module */
|
||||
export interface StepAsk {
|
||||
"asker": string;
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build"?: StepAskBuild;
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
"needs"?: string[];
|
||||
/** package to the tagged version a build pins */
|
||||
"packages"?: Record<string, string>;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
/** go or typescript */
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what current takes. */
|
||||
export interface CurrentInput {
|
||||
}
|
||||
|
||||
/** is what current answers. */
|
||||
export type CurrentAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what pause takes. */
|
||||
export interface PauseInput {
|
||||
}
|
||||
|
||||
/** is what pause answers. */
|
||||
export type PauseAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what resume takes. */
|
||||
export interface ResumeInput {
|
||||
}
|
||||
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-image",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-image",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-image, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-image",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "node-build-image", defined whole (seats/node-build-image/seat.json): The image build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-image";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-image.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-image.accept.check";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-image.accept.recheck";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node: string, id: string): string {
|
||||
return node + "." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<id>", or undefined for a key of another form. */
|
||||
export function parseStepsByNodeIDKey(key: string): { node: string; id: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const id = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "paused.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByPausedNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("paused.")) return undefined;
|
||||
rest = rest.slice(7);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "capacity.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByCapacityNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("capacity.")) return undefined;
|
||||
rest = rest.slice(9);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state toolchains under the form "<node>.<language>". */
|
||||
export function toolchainsByNodeLanguageKey(node: string, language: string): string {
|
||||
return node + "." + language;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<language>", or undefined for a key of another form. */
|
||||
export function parseToolchainsByNodeLanguageKey(key: string): { node: string; language: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const language = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, language };
|
||||
}
|
||||
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
export type BuildAnswerArtifactsItem = buildStep.BuildAnswerArtifactsItem;
|
||||
export type BuildAnswerToolchain = buildStep.BuildAnswerToolchain;
|
||||
export type Capacity = buildStep.Capacity;
|
||||
export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type CheckAnswerLevelsItem = buildStep.CheckAnswerLevelsItem;
|
||||
export type CheckAnswerLevelsItemDigest = buildStep.CheckAnswerLevelsItemDigest;
|
||||
export type CheckAnswerLevelsItemDigestNeedsItem = buildStep.CheckAnswerLevelsItemDigestNeedsItem;
|
||||
export type CheckAnswerLevelsItemDigestPackagesItem = buildStep.CheckAnswerLevelsItemDigestPackagesItem;
|
||||
export type CheckAnswerLevelsItemKeptItem = buildStep.CheckAnswerLevelsItemKeptItem;
|
||||
export type CheckAnswerLevelsItemUnmetItem = buildStep.CheckAnswerLevelsItemUnmetItem;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Pause = buildStep.Pause;
|
||||
export type PauseAnswer = buildStep.PauseAnswer;
|
||||
export type PauseInput = buildStep.PauseInput;
|
||||
export type ResumeAnswer = buildStep.ResumeAnswer;
|
||||
export type ResumeInput = buildStep.ResumeInput;
|
||||
export type Step = buildStep.Step;
|
||||
export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskBuildArtifactsItem = buildStep.StepAskBuildArtifactsItem;
|
||||
export type StepAskBuildToolchain = buildStep.StepAskBuildToolchain;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
|
||||
/** is the body of delivery. */
|
||||
export type DeliveryAccept = StepAsk;
|
||||
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
/** is one value of the state steps under the key <node>.<id>. */
|
||||
export type StepsByNodeIDValue = Step;
|
||||
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "build-step" several seats include whole: What the three build seats share: the verbs that read and steer a node's builds, and the layouts of the asks they accept and the steps they keep. A seat lists its states against these (a part carries no states).
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export interface BuildAnswerArtifactsItem {
|
||||
"artifact": string;
|
||||
"digest": string;
|
||||
"reference"?: string;
|
||||
}
|
||||
|
||||
export interface BuildAnswerToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuildAnswerArtifactsItem[];
|
||||
"imports"?: string[];
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: BuildAnswerToolchain;
|
||||
}
|
||||
|
||||
/** how many steps the node runs at once */
|
||||
export interface Capacity {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build-hours"?: string;
|
||||
"build-hours-fault"?: string;
|
||||
"by-cpu"?: number;
|
||||
"configured": number;
|
||||
"configured-from"?: string;
|
||||
"cores-per-step"?: number;
|
||||
"effective": number;
|
||||
"ineligible"?: string;
|
||||
"outside-hours"?: boolean;
|
||||
"quota-cores"?: number;
|
||||
"quota-from"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestPackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigest {
|
||||
"beside"?: string[];
|
||||
"judged_by"?: string;
|
||||
"level"?: string;
|
||||
"needs"?: CheckAnswerLevelsItemDigestNeedsItem[];
|
||||
"packages"?: CheckAnswerLevelsItemDigestPackagesItem[];
|
||||
"without_tests"?: string[];
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemKeptItem {
|
||||
"digest"?: string;
|
||||
"package"?: string;
|
||||
"tests"?: number;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemUnmetItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItem {
|
||||
"digest"?: CheckAnswerLevelsItemDigest;
|
||||
"judged"?: string;
|
||||
"kept"?: CheckAnswerLevelsItemKeptItem[];
|
||||
"level": string;
|
||||
"tests"?: unknown[];
|
||||
"unmet"?: CheckAnswerLevelsItemUnmetItem[];
|
||||
}
|
||||
|
||||
export interface CheckAnswer {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"levels"?: CheckAnswerLevelsItem[];
|
||||
}
|
||||
|
||||
export interface ComposeAnswer {
|
||||
"built": boolean;
|
||||
"key"?: string;
|
||||
/** the compose-candidate verdict */
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** whether the node takes no new ask */
|
||||
export interface Pause {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"paused": boolean;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
/** what the step answered */
|
||||
"result"?: unknown;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildArtifactsItem {
|
||||
"artifact": string;
|
||||
"from"?: string;
|
||||
"seat"?: string;
|
||||
"version"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface StepAskBuild {
|
||||
"artifacts": StepAskBuildArtifactsItem[];
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch"?: unknown;
|
||||
"fp"?: string;
|
||||
"module": string;
|
||||
"path"?: string;
|
||||
"publish"?: boolean;
|
||||
"toolchain"?: StepAskBuildToolchain;
|
||||
}
|
||||
|
||||
export interface StepAskCheck {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"kept"?: boolean;
|
||||
"levels": string[];
|
||||
"packages"?: string[];
|
||||
"run"?: string;
|
||||
"runner"?: string;
|
||||
"runner_when"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskCompose {
|
||||
"dir": string;
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"package": string;
|
||||
"reader"?: string;
|
||||
/** the compose-candidate request */
|
||||
"request": unknown;
|
||||
}
|
||||
|
||||
/** one ask of a build module */
|
||||
export interface StepAsk {
|
||||
"asker": string;
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build"?: StepAskBuild;
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
"needs"?: string[];
|
||||
/** package to the tagged version a build pins */
|
||||
"packages"?: Record<string, string>;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
/** go or typescript */
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what current takes. */
|
||||
export interface CurrentInput {
|
||||
}
|
||||
|
||||
/** is what current answers. */
|
||||
export type CurrentAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what pause takes. */
|
||||
export interface PauseInput {
|
||||
}
|
||||
|
||||
/** is what pause answers. */
|
||||
export type PauseAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what resume takes. */
|
||||
export interface ResumeInput {
|
||||
}
|
||||
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-node",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-node",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-node, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-node",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "node-build-node", defined whole (seats/node-build-node/seat.json): The Node build module on a node: it takes the asks of the builder and the checker, runs them as steps and answers.
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-node";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-node.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-node.accept.check";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-node.accept.recheck";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node: string, id: string): string {
|
||||
return node + "." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<id>", or undefined for a key of another form. */
|
||||
export function parseStepsByNodeIDKey(key: string): { node: string; id: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const id = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "paused.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByPausedNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("paused.")) return undefined;
|
||||
rest = rest.slice(7);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "capacity.<node>", or undefined for a key of another form. */
|
||||
export function parsePausesByCapacityNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("capacity.")) return undefined;
|
||||
rest = rest.slice(9);
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state toolchains under the form "<node>.<language>". */
|
||||
export function toolchainsByNodeLanguageKey(node: string, language: string): string {
|
||||
return node + "." + language;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<language>", or undefined for a key of another form. */
|
||||
export function parseToolchainsByNodeLanguageKey(key: string): { node: string; language: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const language = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, language };
|
||||
}
|
||||
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
export type BuildAnswerArtifactsItem = buildStep.BuildAnswerArtifactsItem;
|
||||
export type BuildAnswerToolchain = buildStep.BuildAnswerToolchain;
|
||||
export type Capacity = buildStep.Capacity;
|
||||
export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type CheckAnswerLevelsItem = buildStep.CheckAnswerLevelsItem;
|
||||
export type CheckAnswerLevelsItemDigest = buildStep.CheckAnswerLevelsItemDigest;
|
||||
export type CheckAnswerLevelsItemDigestNeedsItem = buildStep.CheckAnswerLevelsItemDigestNeedsItem;
|
||||
export type CheckAnswerLevelsItemDigestPackagesItem = buildStep.CheckAnswerLevelsItemDigestPackagesItem;
|
||||
export type CheckAnswerLevelsItemKeptItem = buildStep.CheckAnswerLevelsItemKeptItem;
|
||||
export type CheckAnswerLevelsItemUnmetItem = buildStep.CheckAnswerLevelsItemUnmetItem;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type Pause = buildStep.Pause;
|
||||
export type PauseAnswer = buildStep.PauseAnswer;
|
||||
export type PauseInput = buildStep.PauseInput;
|
||||
export type ResumeAnswer = buildStep.ResumeAnswer;
|
||||
export type ResumeInput = buildStep.ResumeInput;
|
||||
export type Step = buildStep.Step;
|
||||
export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskBuildArtifactsItem = buildStep.StepAskBuildArtifactsItem;
|
||||
export type StepAskBuildToolchain = buildStep.StepAskBuildToolchain;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
|
||||
/** is the body of delivery. */
|
||||
export type DeliveryAccept = StepAsk;
|
||||
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
/** is one value of the state steps under the key <node>.<id>. */
|
||||
export type StepsByNodeIDValue = Step;
|
||||
|
||||
/** is one value of the state pauses under the key paused.<node>. */
|
||||
export type PausesByPausedNodeValue = Pause;
|
||||
|
||||
/** is one value of the state pauses under the key capacity.<node>. */
|
||||
export type PausesByCapacityNodeValue = Capacity;
|
||||
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "build-step" several seats include whole: What the three build seats share: the verbs that read and steer a node's builds, and the layouts of the asks they accept and the steps they keep. A seat lists its states against these (a part carries no states).
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
} as const;
|
||||
|
||||
export interface BuildAnswerArtifactsItem {
|
||||
"artifact": string;
|
||||
"digest": string;
|
||||
"reference"?: string;
|
||||
}
|
||||
|
||||
export interface BuildAnswerToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuildAnswerArtifactsItem[];
|
||||
"imports"?: string[];
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: BuildAnswerToolchain;
|
||||
}
|
||||
|
||||
/** how many steps the node runs at once */
|
||||
export interface Capacity {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build-hours"?: string;
|
||||
"build-hours-fault"?: string;
|
||||
"by-cpu"?: number;
|
||||
"configured": number;
|
||||
"configured-from"?: string;
|
||||
"cores-per-step"?: number;
|
||||
"effective": number;
|
||||
"ineligible"?: string;
|
||||
"outside-hours"?: boolean;
|
||||
"quota-cores"?: number;
|
||||
"quota-from"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigestPackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemDigest {
|
||||
"beside"?: string[];
|
||||
"judged_by"?: string;
|
||||
"level"?: string;
|
||||
"needs"?: CheckAnswerLevelsItemDigestNeedsItem[];
|
||||
"packages"?: CheckAnswerLevelsItemDigestPackagesItem[];
|
||||
"without_tests"?: string[];
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemKeptItem {
|
||||
"digest"?: string;
|
||||
"package"?: string;
|
||||
"tests"?: number;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItemUnmetItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
export interface CheckAnswerLevelsItem {
|
||||
"digest"?: CheckAnswerLevelsItemDigest;
|
||||
"judged"?: string;
|
||||
"kept"?: CheckAnswerLevelsItemKeptItem[];
|
||||
"level": string;
|
||||
"tests"?: unknown[];
|
||||
"unmet"?: CheckAnswerLevelsItemUnmetItem[];
|
||||
}
|
||||
|
||||
export interface CheckAnswer {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"levels"?: CheckAnswerLevelsItem[];
|
||||
}
|
||||
|
||||
export interface ComposeAnswer {
|
||||
"built": boolean;
|
||||
"key"?: string;
|
||||
/** the compose-candidate verdict */
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** whether the node takes no new ask */
|
||||
export interface Pause {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"paused": boolean;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** one step a build module runs on a node */
|
||||
export interface Step {
|
||||
/** when (RFC 3339 time) */
|
||||
"ended"?: string;
|
||||
"id": string;
|
||||
"node": string;
|
||||
"owner"?: string;
|
||||
"phase"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"phase-at"?: string;
|
||||
"reason"?: string;
|
||||
/** what the step answered */
|
||||
"result"?: unknown;
|
||||
/** when (RFC 3339 time) */
|
||||
"started": string;
|
||||
/** running, passed, failed or refused */
|
||||
"state": string;
|
||||
"tool": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildArtifactsItem {
|
||||
"artifact": string;
|
||||
"from"?: string;
|
||||
"seat"?: string;
|
||||
"version"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskBuildToolchain {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface StepAskBuild {
|
||||
"artifacts": StepAskBuildArtifactsItem[];
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch"?: unknown;
|
||||
"fp"?: string;
|
||||
"module": string;
|
||||
"path"?: string;
|
||||
"publish"?: boolean;
|
||||
"toolchain"?: StepAskBuildToolchain;
|
||||
}
|
||||
|
||||
export interface StepAskCheck {
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"kept"?: boolean;
|
||||
"levels": string[];
|
||||
"packages"?: string[];
|
||||
"run"?: string;
|
||||
"runner"?: string;
|
||||
"runner_when"?: string;
|
||||
}
|
||||
|
||||
export interface StepAskCompose {
|
||||
"dir": string;
|
||||
/** what the build module fetches: the repository, commit and directory, as the indexer states it */
|
||||
"fetch": unknown;
|
||||
"package": string;
|
||||
"reader"?: string;
|
||||
/** the compose-candidate request */
|
||||
"request": unknown;
|
||||
}
|
||||
|
||||
/** one ask of a build module */
|
||||
export interface StepAsk {
|
||||
"asker": string;
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"build"?: StepAskBuild;
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
"needs"?: string[];
|
||||
/** package to the tagged version a build pins */
|
||||
"packages"?: Record<string, string>;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
/** go or typescript */
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what current takes. */
|
||||
export interface CurrentInput {
|
||||
}
|
||||
|
||||
/** is what current answers. */
|
||||
export type CurrentAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what pause takes. */
|
||||
export interface PauseInput {
|
||||
}
|
||||
|
||||
/** is what pause answers. */
|
||||
export type PauseAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what resume takes. */
|
||||
export interface ResumeInput {
|
||||
}
|
||||
|
||||
/** is what resume answers. */
|
||||
export type ResumeAnswer = Record<string, unknown>;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user