CT11: regenerate the Go and TypeScript contracts from CT1 to CT9; each TypeScript contract as index.js with index.d.ts
Generated by seatgen (mesh-catalog, GEN1 and GEN2 on its worktree) from the definitions of CT1 to CT9; module.json names the artifacts of the new seats mesh-builds, mesh-pipeline-runner and git. seatgen -check is clean; every seat package's generated fixture test passes. Builds: design 47 G §341 (a TypeScript contract is emitted as index.js with index.d.ts), §196, §339 (the generator refuses an unknown callers entry), §260, §331. Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -0,0 +1,752 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package git is the contract of the seat "git", defined whole (seats/git/seat.json): The forge: every read and act a delivery part makes of the mesh's git repositories, and what the forge says happened (design 47 *The seat git*, ADR 0596 §1, §2). A failed read answers an error, never an empty answer. The act verbs are the forge bridge's alone.
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "git"
|
||||
|
||||
const (
|
||||
VerbPull = "pull"
|
||||
VerbBranch = "branch"
|
||||
VerbOpenPulls = "open-pulls"
|
||||
VerbTags = "tags"
|
||||
VerbTrees = "trees"
|
||||
VerbFile = "file"
|
||||
VerbContains = "contains"
|
||||
VerbStatuses = "statuses"
|
||||
VerbStatus = "status"
|
||||
VerbComment = "comment"
|
||||
VerbView = "view"
|
||||
VerbNote = "note"
|
||||
VerbMergePull = "merge-pull"
|
||||
VerbTag = "tag"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPullUpdated = "pull-updated"
|
||||
EventPullMerged = "pull-merged"
|
||||
EventPullClosed = "pull-closed"
|
||||
EventForgePull = "forge-pull"
|
||||
EventForgeStatus = "forge-status"
|
||||
EventForgeDelete = "forge-delete"
|
||||
EventRepoWritable = "repo-writable"
|
||||
EventBranchMoved = "branch-moved"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbPull, VerbBranch, VerbOpenPulls, VerbTags, VerbTrees, VerbFile, VerbContains, VerbStatuses, VerbStatus, VerbComment, VerbView, VerbNote, VerbMergePull, VerbTag}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventPullUpdated, EventPullMerged, EventPullClosed, EventForgePull, EventForgeStatus, EventForgeDelete, EventRepoWritable, EventBranchMoved}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "git.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectPullUpdated is where pull-updated is published.
|
||||
const SubjectPullUpdated = "mesh.seat.git.event.pull-updated"
|
||||
|
||||
// SubjectPullMerged is where pull-merged is published.
|
||||
const SubjectPullMerged = "mesh.seat.git.event.pull-merged"
|
||||
|
||||
// SubjectPullClosed is where pull-closed is published.
|
||||
const SubjectPullClosed = "mesh.seat.git.event.pull-closed"
|
||||
|
||||
// SubjectForgePull is where forge-pull is published.
|
||||
const SubjectForgePull = "mesh.seat.git.event.forge-pull"
|
||||
|
||||
// SubjectForgeStatus is where forge-status is published.
|
||||
const SubjectForgeStatus = "mesh.seat.git.event.forge-status"
|
||||
|
||||
// SubjectForgeDelete is where forge-delete is published.
|
||||
const SubjectForgeDelete = "mesh.seat.git.event.forge-delete"
|
||||
|
||||
// SubjectRepoWritable is where repo-writable is published.
|
||||
const SubjectRepoWritable = "mesh.seat.git.event.repo-writable"
|
||||
|
||||
// StreamBranchMoved is the stream branch-moved is kept in.
|
||||
const StreamBranchMoved = "SEAT_git_branch-moved"
|
||||
|
||||
// SubjectBranchMoved is where branch-moved is published.
|
||||
const SubjectBranchMoved = "mesh.seat.git.event.branch-moved"
|
||||
|
||||
const (
|
||||
StateFailedSteps = "failed-steps"
|
||||
)
|
||||
|
||||
// FailedStepsByModuleFingerprintStepKey is the key of one value of the state failed-steps under the form "<module>.<fingerprint>.<step>".
|
||||
func FailedStepsByModuleFingerprintStepKey(module, fingerprint, step string) string {
|
||||
return module + "." + fingerprint + "." + step
|
||||
}
|
||||
|
||||
// ParseFailedStepsByModuleFingerprintStepKey reads the parts of a key of the form "<module>.<fingerprint>.<step>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseFailedStepsByModuleFingerprintStepKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodeFailedStepsByModuleFingerprintStepValue reads one value of the state failed-steps under the form "<module>.<fingerprint>.<step>", refusing a field FailedStepsByModuleFingerprintStepValue does not know and any text after the value.
|
||||
func DecodeFailedStepsByModuleFingerprintStepValue(raw []byte) (FailedStepsByModuleFingerprintStepValue, error) {
|
||||
var v FailedStepsByModuleFingerprintStepValue
|
||||
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
|
||||
}
|
||||
|
||||
// Change is what a pull request changed.
|
||||
type Change struct {
|
||||
// the changed directories that hold a module at its head; absent when they could not be read
|
||||
ModuleDirs []string `json:"module-dirs,omitempty"`
|
||||
// the paths it changed
|
||||
Paths []string `json:"paths"`
|
||||
// the forge cut the list
|
||||
PathsTruncated bool `json:"paths-truncated,omitempty"`
|
||||
// which of them it deleted
|
||||
Removed []string `json:"removed,omitempty"`
|
||||
}
|
||||
|
||||
// ErrorKind is which kind of error, set with error alone: refused, the forge or the holder refused and error says why in the forge's own words; not-found, the forge said that what was asked about (a repository, a commit, a pull request, a branch or a tag) does not exist, so a caller never reads it out of error's words; failed, the forge failed or could not be reached, so the act or read could not be performed.
|
||||
type ErrorKind = string
|
||||
|
||||
// The values of ErrorKind.
|
||||
const (
|
||||
ErrorKindRefused = "refused"
|
||||
ErrorKindNotFound = "not-found"
|
||||
ErrorKindFailed = "failed"
|
||||
)
|
||||
|
||||
// FailedStep is a failed required step at a build-input fingerprint, with the commits it was seen at and the run that failed it (design 47 *Judged from its own state, never by a call*); cleared by a later passing rerun of that step whose proved caller is the operator or a healer.
|
||||
type FailedStep struct {
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// every commit it was seen at
|
||||
Commits []string `json:"commits"`
|
||||
// the build-input fingerprint the step failed at
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Module string `json:"module"`
|
||||
// the run that failed it: the runner's pipeline key
|
||||
Run string `json:"run"`
|
||||
// why it failed, as the runner's step-ended said
|
||||
Said string `json:"said,omitempty"`
|
||||
Step string `json:"step"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// Merging is what the forge would merge now, for an open pull request (issues 1275, 1945; ADR 0441 §1): answered whole or not at all, and a read the forge could not make answers the verb's error, never a guess; absent for a merged or closed one.
|
||||
type Merging struct {
|
||||
// the forge's own word on whether it merges into its base now: false while it is in conflict with its base, or while the forge works that out after the base moved
|
||||
Mergeable bool `json:"mergeable"`
|
||||
// whether a protection rule guards its base branch
|
||||
Protected bool `json:"protected"`
|
||||
// the status contexts the base branch's protection requires; none when it requires none
|
||||
Required []string `json:"required"`
|
||||
// whether the forge's merging account may write the repository: false, its statuses and its merge are refused
|
||||
Writes bool `json:"writes"`
|
||||
}
|
||||
|
||||
// OpenPull is an open pull request, with the statuses its base requires and those its head has.
|
||||
type OpenPull struct {
|
||||
// the head's statuses by context, the newest of each
|
||||
Checks map[string]Status `json:"checks"`
|
||||
Pull Pull `json:"pull"`
|
||||
// the contexts the base branch's protection requires; none when it requires none
|
||||
Required []string `json:"required"`
|
||||
}
|
||||
|
||||
// Pull is one pull request as the forge holds it; never its description (ADR 0659 §1).
|
||||
type Pull struct {
|
||||
// who opened it, the forge's login
|
||||
Author string `json:"author,omitempty"`
|
||||
// the branch it merges into
|
||||
Base string `json:"base"`
|
||||
// its head branch: what a delivery group is named by
|
||||
Branch string `json:"branch"`
|
||||
// a commit, its full 40-hex sha
|
||||
Head string `json:"head"`
|
||||
// the merge commit, once merged
|
||||
MergeCommit string `json:"merge-commit,omitempty"`
|
||||
// when it merged
|
||||
MergedAt *time.Time `json:"merged-at,omitempty"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// open, merged or closed
|
||||
State string `json:"state"`
|
||||
// its title
|
||||
Title string `json:"title,omitempty"`
|
||||
// its page on the forge
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// The values of Pull's state.
|
||||
const (
|
||||
PullStateOpen = "open"
|
||||
PullStateMerged = "merged"
|
||||
PullStateClosed = "closed"
|
||||
)
|
||||
|
||||
// Status is the newest status of one context on a commit.
|
||||
type Status struct {
|
||||
// when it was set
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// who set it
|
||||
By string `json:"by,omitempty"`
|
||||
// the status's context, such as mesh/check
|
||||
Context string `json:"context"`
|
||||
// what it says
|
||||
Description string `json:"description,omitempty"`
|
||||
// pending, success, failure, error or warning
|
||||
State string `json:"state"`
|
||||
// the page it links to
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
// PullInput is what pull takes.
|
||||
type PullInput struct {
|
||||
// instead of the number: the merge commit it made
|
||||
MergeCommit string `json:"merge-commit,omitempty"`
|
||||
// its number
|
||||
Number int64 `json:"number,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// PullAnswer is what pull answers.
|
||||
type PullAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
Merging *Merging `json:"merging,omitempty"`
|
||||
Pull *Pull `json:"pull,omitempty"`
|
||||
}
|
||||
|
||||
// BranchInput is what branch takes.
|
||||
type BranchInput struct {
|
||||
Branch string `json:"branch"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// BranchAnswer is what branch answers.
|
||||
type BranchAnswer struct {
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// a commit, its full 40-hex sha
|
||||
Head string `json:"head,omitempty"`
|
||||
// a protection rule refuses a direct push and admits only merges
|
||||
Protected bool `json:"protected,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
}
|
||||
|
||||
// OpenPullsInput is what open-pulls takes.
|
||||
type OpenPullsInput struct {
|
||||
}
|
||||
|
||||
// OpenPullsAnswer is what open-pulls answers.
|
||||
type OpenPullsAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// every open pull request; said empty when none is open, so an answer that lacks it is never read as none
|
||||
Pulls []OpenPull `json:"pulls"`
|
||||
}
|
||||
|
||||
// TagsInput is what tags takes.
|
||||
type TagsInput struct {
|
||||
// the page, from 1
|
||||
Page int64 `json:"page,omitempty"`
|
||||
// only tags starting with it
|
||||
Prefix string `json:"prefix,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// TagsAnswer is what tags answers.
|
||||
type TagsAnswer struct {
|
||||
// how many tags a page holds
|
||||
Bound int64 `json:"bound,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// another page exists
|
||||
More bool `json:"more,omitempty"`
|
||||
// the page
|
||||
Page int64 `json:"page,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository,omitempty"`
|
||||
// the tags of this page
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
// TreesInput is what trees takes.
|
||||
type TreesInput struct {
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit"`
|
||||
// directories whose every blob is answered; the root is the empty name
|
||||
Files []string `json:"files,omitempty"`
|
||||
// {directory: [path relative to it]}; the root is the empty name
|
||||
Paths map[string][]string `json:"paths,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// TreesAnswer is what trees answers.
|
||||
type TreesAnswer struct {
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// directory to {path: blob id}
|
||||
Files map[string]map[string]string `json:"files,omitempty"`
|
||||
// directory to {path: object id}
|
||||
Paths map[string]map[string]string `json:"paths,omitempty"`
|
||||
// the root tree's hash
|
||||
Root string `json:"root,omitempty"`
|
||||
// directory to its tree's hash, the root as the empty name
|
||||
Trees map[string]string `json:"trees,omitempty"`
|
||||
}
|
||||
|
||||
// FileInput is what file takes.
|
||||
type FileInput struct {
|
||||
// the file's path from the repository's root
|
||||
Path string `json:"path"`
|
||||
// a commit, branch or tag; the default branch when absent
|
||||
Ref string `json:"ref,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// FileAnswer is what file answers.
|
||||
type FileAnswer struct {
|
||||
// the forge holds no such file there
|
||||
Absent bool `json:"absent,omitempty"`
|
||||
// the file's git blob id
|
||||
Blob string `json:"blob,omitempty"`
|
||||
// its content
|
||||
Content string `json:"content,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the path
|
||||
Path string `json:"path,omitempty"`
|
||||
// what was read
|
||||
Ref string `json:"ref,omitempty"`
|
||||
// its size in bytes
|
||||
Size int64 `json:"size,omitempty"`
|
||||
}
|
||||
|
||||
// ContainsInput is what contains takes.
|
||||
type ContainsInput struct {
|
||||
// the commit asked about
|
||||
Commit string `json:"commit"`
|
||||
// the commit it may be contained in
|
||||
In string `json:"in"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// ContainsAnswer is what contains answers.
|
||||
type ContainsAnswer struct {
|
||||
// how many commits commit is ahead of in
|
||||
Ahead int64 `json:"ahead,omitempty"`
|
||||
// the commit
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// in contains commit
|
||||
Contains bool `json:"contains,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the other
|
||||
In string `json:"in,omitempty"`
|
||||
}
|
||||
|
||||
// StatusesInput is what statuses takes.
|
||||
type StatusesInput struct {
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// StatusesAnswer is what statuses answers.
|
||||
type StatusesAnswer struct {
|
||||
// the forge's combined state
|
||||
Combined string `json:"combined,omitempty"`
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the newest of each context
|
||||
Statuses []Status `json:"statuses,omitempty"`
|
||||
}
|
||||
|
||||
// StatusInput is what status takes.
|
||||
type StatusInput struct {
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit"`
|
||||
// the context, such as mesh/check
|
||||
Context string `json:"context"`
|
||||
// what it says
|
||||
Description string `json:"description,omitempty"`
|
||||
// the act's id
|
||||
ID string `json:"id"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// the state
|
||||
State string `json:"state"`
|
||||
// the page it links to
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StatusInput's state.
|
||||
const (
|
||||
StatusInputStatePending = "pending"
|
||||
StatusInputStateSuccess = "success"
|
||||
StatusInputStateFailure = "failure"
|
||||
StatusInputStateError = "error"
|
||||
StatusInputStateWarning = "warning"
|
||||
)
|
||||
|
||||
// StatusAnswer is what status answers.
|
||||
type StatusAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the id was already held on the pull request or the note, so nothing was done again
|
||||
Held bool `json:"held,omitempty"`
|
||||
// the act's id, as the caller gave it
|
||||
ID string `json:"id,omitempty"`
|
||||
// the forge holds the act now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
}
|
||||
|
||||
// CommentInput is what comment takes.
|
||||
type CommentInput struct {
|
||||
// the act's id
|
||||
ID string `json:"id"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// the comment, markdown
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
// CommentAnswer is what comment answers.
|
||||
type CommentAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the id was already held on the pull request or the note, so nothing was done again
|
||||
Held bool `json:"held,omitempty"`
|
||||
// the act's id, as the caller gave it
|
||||
ID string `json:"id,omitempty"`
|
||||
// the forge holds the act now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
}
|
||||
|
||||
// ViewInput is what view takes.
|
||||
type ViewInput struct {
|
||||
// the act's id
|
||||
ID string `json:"id"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// the view, markdown
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
// ViewAnswer is what view answers.
|
||||
type ViewAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the id was already held on the pull request or the note, so nothing was done again
|
||||
Held bool `json:"held,omitempty"`
|
||||
// the act's id, as the caller gave it
|
||||
ID string `json:"id,omitempty"`
|
||||
// the forge holds the act now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
}
|
||||
|
||||
// NoteInput is what note takes.
|
||||
type NoteInput struct {
|
||||
// a commit, its full 40-hex sha
|
||||
Commit string `json:"commit"`
|
||||
// the act's id
|
||||
ID string `json:"id"`
|
||||
// the line, one line
|
||||
Line string `json:"line"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// NoteAnswer is what note answers.
|
||||
type NoteAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the id was already held on the pull request or the note, so nothing was done again
|
||||
Held bool `json:"held,omitempty"`
|
||||
// the act's id, as the caller gave it
|
||||
ID string `json:"id,omitempty"`
|
||||
// the forge holds the act now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
}
|
||||
|
||||
// MergePullInput is what merge-pull takes.
|
||||
type MergePullInput struct {
|
||||
// the head the caller names
|
||||
Head string `json:"head"`
|
||||
// the act's id
|
||||
ID string `json:"id"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// MergePullAnswer is what merge-pull answers.
|
||||
type MergePullAnswer struct {
|
||||
// why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the id was already held on the pull request or the note, so nothing was done again
|
||||
Held bool `json:"held,omitempty"`
|
||||
// the act's id, as the caller gave it
|
||||
ID string `json:"id,omitempty"`
|
||||
// the merge commit
|
||||
MergeCommit string `json:"merge-commit,omitempty"`
|
||||
// for policy-failed, the module
|
||||
Module string `json:"module,omitempty"`
|
||||
// the forge holds the act now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
// why the forge or the holder refused the merge; the act is not performed
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// which refusal, set with refused: head-moved, the pull request's head is not the one named; unprotected, the base branch's protection does not refuse a direct push; policy-failed, a run at the head's fingerprint failed a required step (run, module and step name it); no-registrations, no registration-changed heard yet (ADR 0667 section 10); git-refused, git refused the merge
|
||||
RefusedKind string `json:"refused-kind,omitempty"`
|
||||
// for policy-failed, the run that failed the step: the runner's pipeline key
|
||||
Run string `json:"run,omitempty"`
|
||||
// for policy-failed, the step
|
||||
Step string `json:"step,omitempty"`
|
||||
}
|
||||
|
||||
// The values of MergePullAnswer's refused-kind.
|
||||
const (
|
||||
MergePullAnswerRefusedKindHeadMoved = "head-moved"
|
||||
MergePullAnswerRefusedKindUnprotected = "unprotected"
|
||||
MergePullAnswerRefusedKindPolicyFailed = "policy-failed"
|
||||
MergePullAnswerRefusedKindNoRegistrations = "no-registrations"
|
||||
MergePullAnswerRefusedKindGitRefused = "git-refused"
|
||||
)
|
||||
|
||||
// TagInput is what tag takes.
|
||||
type TagInput struct {
|
||||
// the commit it is written at
|
||||
Commit string `json:"commit"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// the tag
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
|
||||
// TagAnswer is what tag answers.
|
||||
type TagAnswer struct {
|
||||
// why the forge could not write it: set alone with error-kind
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorKind ErrorKind `json:"error-kind,omitempty"`
|
||||
// the forge holds the tag at that commit now
|
||||
Performed bool `json:"performed,omitempty"`
|
||||
// the tag, as asked
|
||||
Tag string `json:"tag,omitempty"`
|
||||
}
|
||||
|
||||
// PullUpdatedEvent is the body of the event pull-updated.
|
||||
type PullUpdatedEvent struct {
|
||||
// who opened it
|
||||
Author string `json:"author,omitempty"`
|
||||
// the branch it merges into
|
||||
Base string `json:"base"`
|
||||
// the base branch's head as the head was announced; absent when it could not be read
|
||||
BaseHead string `json:"base-head,omitempty"`
|
||||
// its head branch
|
||||
Branch string `json:"branch"`
|
||||
Change *Change `json:"change,omitempty"`
|
||||
// a commit, its full 40-hex sha
|
||||
Head string `json:"head"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// its title
|
||||
Title string `json:"title,omitempty"`
|
||||
// its page
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// PullMergedEvent is the body of the event pull-merged.
|
||||
type PullMergedEvent struct {
|
||||
// who opened it
|
||||
Author string `json:"author,omitempty"`
|
||||
// the branch it merges into
|
||||
Base string `json:"base"`
|
||||
// its head branch
|
||||
Branch string `json:"branch"`
|
||||
Change *Change `json:"change,omitempty"`
|
||||
// a commit, its full 40-hex sha
|
||||
Head string `json:"head"`
|
||||
// the head's statuses by context, their states; absent when they could not be read
|
||||
HeadChecks map[string]string `json:"head-checks,omitempty"`
|
||||
// a commit, its full 40-hex sha
|
||||
MergeCommit string `json:"merge-commit"`
|
||||
// when
|
||||
MergedAt *time.Time `json:"merged-at,omitempty"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// its title
|
||||
Title string `json:"title,omitempty"`
|
||||
// its page
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// PullClosedEvent is the body of the event pull-closed.
|
||||
type PullClosedEvent struct {
|
||||
// who opened it
|
||||
Author string `json:"author,omitempty"`
|
||||
// the branch it merges into
|
||||
Base string `json:"base"`
|
||||
// its head branch
|
||||
Branch string `json:"branch"`
|
||||
// a commit, its full 40-hex sha
|
||||
Head string `json:"head"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// its title
|
||||
Title string `json:"title,omitempty"`
|
||||
// its page
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// ForgePullEvent is the body of the event forge-pull.
|
||||
type ForgePullEvent struct {
|
||||
// what the forge said: opened, reopened, synchronized, edited, closed, merged
|
||||
Action string `json:"action"`
|
||||
// who opened it
|
||||
Author string `json:"author,omitempty"`
|
||||
// its base branch
|
||||
Base string `json:"base,omitempty"`
|
||||
// its head branch
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// its head commit
|
||||
Head string `json:"head,omitempty"`
|
||||
// the merge commit
|
||||
MergeCommit string `json:"merge-commit,omitempty"`
|
||||
// merged
|
||||
Merged bool `json:"merged,omitempty"`
|
||||
// its number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// who acted
|
||||
Sender string `json:"sender,omitempty"`
|
||||
}
|
||||
|
||||
// ForgeStatusEvent is the body of the event forge-status.
|
||||
type ForgeStatusEvent struct {
|
||||
// the commit
|
||||
Commit string `json:"commit"`
|
||||
// the context
|
||||
Context string `json:"context"`
|
||||
// what it says
|
||||
Description string `json:"description,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// who set it
|
||||
Sender string `json:"sender,omitempty"`
|
||||
// the state
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
// ForgeDeleteEvent is the body of the event forge-delete.
|
||||
type ForgeDeleteEvent struct {
|
||||
// the deleted branch or tag
|
||||
Ref string `json:"ref"`
|
||||
// branch or tag
|
||||
RefType string `json:"ref-type,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// who deleted it
|
||||
Sender string `json:"sender,omitempty"`
|
||||
}
|
||||
|
||||
// RepoWritableEvent is the body of the event repo-writable.
|
||||
type RepoWritableEvent struct {
|
||||
// the account that writes it now
|
||||
Account string `json:"account"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// BranchMovedEvent is the body of the event branch-moved.
|
||||
type BranchMovedEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Branch string `json:"branch"`
|
||||
// the head the webhook said, a commit's full 40-hex sha; read again by branch
|
||||
Head string `json:"head,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// FailedStepsByModuleFingerprintStepValue is one value of the state failed-steps under the key <module>.<fingerprint>.<step>.
|
||||
type FailedStepsByModuleFingerprintStepValue = FailedStep
|
||||
@@ -0,0 +1,164 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/git/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: "pull.updated is said", subject: "mesh.seat.git.event.pull-updated", given: "{\"author\":\"jochen\",\"base\":\"main\",\"base-head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"branch\":\"feat/47-G\",\"change\":{\"module-dirs\":[\"go\"],\"paths\":[\"go/seatlist/seatlist.go\"]},\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"title\":\"One wiring\",\"url\":\"https://forge.test/p/178\"}", wire: "{\"author\":\"jochen\",\"base\":\"main\",\"base-head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"branch\":\"feat/47-G\",\"change\":{\"module-dirs\":[\"go\"],\"paths\":[\"go/seatlist/seatlist.go\"]},\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"title\":\"One wiring\",\"url\":\"https://forge.test/p/178\"}",
|
||||
decode: func(b []byte) (any, error) { var v PullUpdatedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.pull-updated$")},
|
||||
{name: "pull.merged is said", subject: "mesh.seat.git.event.pull-merged", given: "{\"base\":\"main\",\"branch\":\"feat/47-G\",\"change\":{\"module-dirs\":[\"go\"],\"paths\":[\"go/seatlist/seatlist.go\"]},\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"head-checks\":{\"mesh/check\":\"success\"},\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"merged-at\":\"2026-11-09T19:40:00Z\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"base\":\"main\",\"branch\":\"feat/47-G\",\"change\":{\"module-dirs\":[\"go\"],\"paths\":[\"go/seatlist/seatlist.go\"]},\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"head-checks\":{\"mesh/check\":\"success\"},\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"merged-at\":\"2026-11-09T19:40:00Z\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v PullMergedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.pull-merged$")},
|
||||
{name: "pull.closed is said", subject: "mesh.seat.git.event.pull-closed", given: "{\"base\":\"main\",\"branch\":\"fix/x\",\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":179,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"base\":\"main\",\"branch\":\"fix/x\",\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":179,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v PullClosedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.pull-closed$")},
|
||||
{name: "forge.pull is said", subject: "mesh.seat.git.event.forge-pull", given: "{\"action\":\"synchronized\",\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"sender\":\"jochen\"}", wire: "{\"action\":\"synchronized\",\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"sender\":\"jochen\"}",
|
||||
decode: func(b []byte) (any, error) { var v ForgePullEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.forge-pull$")},
|
||||
{name: "forge.status is said", subject: "mesh.seat.git.event.forge-status", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"context\":\"mesh/check\",\"description\":\"failed\",\"repository\":\"novox/mesh-sdk\",\"sender\":\"mesh-delivery-checker\",\"state\":\"failure\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"context\":\"mesh/check\",\"description\":\"failed\",\"repository\":\"novox/mesh-sdk\",\"sender\":\"mesh-delivery-checker\",\"state\":\"failure\"}",
|
||||
decode: func(b []byte) (any, error) { var v ForgeStatusEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.forge-status$")},
|
||||
{name: "forge.delete is said", subject: "mesh.seat.git.event.forge-delete", given: "{\"ref\":\"feat/47-G\",\"ref-type\":\"branch\",\"repository\":\"novox/mesh-sdk\",\"sender\":\"jochen\"}", wire: "{\"ref\":\"feat/47-G\",\"ref-type\":\"branch\",\"repository\":\"novox/mesh-sdk\",\"sender\":\"jochen\"}",
|
||||
decode: func(b []byte) (any, error) { var v ForgeDeleteEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.forge-delete$")},
|
||||
{name: "repo.writable is said", subject: "mesh.seat.git.event.repo-writable", given: "{\"account\":\"mesh-delivery\",\"repository\":\"jochen/notes\"}", wire: "{\"account\":\"mesh-delivery\",\"repository\":\"jochen/notes\"}",
|
||||
decode: func(b []byte) (any, error) { var v RepoWritableEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.repo-writable$")},
|
||||
{name: "a branch moved by a merge", subject: "mesh.seat.git.event.branch-moved", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-catalog\"}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-catalog\"}",
|
||||
decode: func(b []byte) (any, error) { var v BranchMovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.git\\.event\\.branch-moved$")},
|
||||
{name: "a failed required step kept", subject: "", given: "{\"artifact\":\"nats:program\",\"at\":\"2026-11-10T10:00:00Z\",\"commits\":[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"],\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"run\":\"main.12.nats\",\"said\":\"TestTheBusWhole failed\",\"step\":\"unit\",\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"at\":\"2026-11-10T10:00:00Z\",\"commits\":[\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"],\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"run\":\"main.12.nats\",\"said\":\"TestTheBusWhole failed\",\"step\":\"unit\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v FailedStepsByModuleFingerprintStepValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "pull asks", subject: "", given: "{\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\"}", wire: "{\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v PullInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "pull answers", subject: "", given: "{\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"merged-at\":\"2026-11-09T19:40:00Z\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"merged\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/178\"}}", wire: "{\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"merged-at\":\"2026-11-09T19:40:00Z\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"merged\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/178\"}}",
|
||||
decode: func(b []byte) (any, error) { var v PullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "pull answers an open one with what the forge would merge now", subject: "", given: "{\"merging\":{\"mergeable\":false,\"protected\":true,\"required\":[\"mesh/check\"],\"writes\":true},\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":179,\"repository\":\"novox/mesh-sdk\",\"state\":\"open\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/179\"}}", wire: "{\"merging\":{\"mergeable\":false,\"protected\":true,\"required\":[\"mesh/check\"],\"writes\":true},\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":179,\"repository\":\"novox/mesh-sdk\",\"state\":\"open\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/179\"}}",
|
||||
decode: func(b []byte) (any, error) { var v PullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "pull answers an error, never none", subject: "", given: "{\"error\":\"the forge holds no pull request novox/mesh-sdk#999\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge holds no pull request novox/mesh-sdk#999\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v PullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "open-pulls asks", subject: "", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v OpenPullsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "open-pulls answers", subject: "", given: "{\"pulls\":[{\"checks\":{\"mesh/check\":{\"at\":\"2026-11-09T19:00:00Z\",\"by\":\"mesh-delivery-checker\",\"context\":\"mesh/check\",\"description\":\"passed\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}},\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"open\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/178\"},\"required\":[\"mesh/check\"]}]}", wire: "{\"pulls\":[{\"checks\":{\"mesh/check\":{\"at\":\"2026-11-09T19:00:00Z\",\"by\":\"mesh-delivery-checker\",\"context\":\"mesh/check\",\"description\":\"passed\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}},\"pull\":{\"author\":\"jochen\",\"base\":\"main\",\"branch\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"open\",\"title\":\"One wiring of the seat list\",\"url\":\"https://forge.test/novox/mesh-sdk/pulls/178\"},\"required\":[\"mesh/check\"]}]}",
|
||||
decode: func(b []byte) (any, error) { var v OpenPullsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "open-pulls answers none open as an empty list", subject: "", given: "{\"pulls\":[]}", wire: "{\"pulls\":[]}",
|
||||
decode: func(b []byte) (any, error) { var v OpenPullsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "open-pulls answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\",\"pulls\":[]}", wire: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\",\"pulls\":[]}",
|
||||
decode: func(b []byte) (any, error) { var v OpenPullsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tags asks", subject: "", given: "{\"page\":1,\"prefix\":\"go/v\",\"repository\":\"novox/mesh-sdk\"}", wire: "{\"page\":1,\"prefix\":\"go/v\",\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v TagsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tags answers", subject: "", given: "{\"bound\":50,\"more\":true,\"page\":1,\"repository\":\"novox/mesh-sdk\",\"tags\":[\"go/v0.1.15\",\"go/v0.1.14\"]}", wire: "{\"bound\":50,\"more\":true,\"page\":1,\"repository\":\"novox/mesh-sdk\",\"tags\":[\"go/v0.1.15\",\"go/v0.1.14\"]}",
|
||||
decode: func(b []byte) (any, error) { var v TagsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tags answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 404 for novox/nothing\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge answered 404 for novox/nothing\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v TagsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "trees asks", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"files\":[\"contracts\"],\"paths\":{\"\":[\"go.work\"]},\"repository\":\"novox/mesh-delivery\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"files\":[\"contracts\"],\"paths\":{\"\":[\"go.work\"]},\"repository\":\"novox/mesh-delivery\"}",
|
||||
decode: func(b []byte) (any, error) { var v TreesInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "trees answers", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"files\":{\"contracts\":{\"module.json\":\"ffffffffffffffffffffffffffffffffffffffff\"}},\"paths\":{\"\":{\"go.work\":\"1111111111111111111111111111111111111111\"}},\"root\":\"dddddddddddddddddddddddddddddddddddddddd\",\"trees\":{\"\":\"dddddddddddddddddddddddddddddddddddddddd\",\"contracts\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"files\":{\"contracts\":{\"module.json\":\"ffffffffffffffffffffffffffffffffffffffff\"}},\"paths\":{\"\":{\"go.work\":\"1111111111111111111111111111111111111111\"}},\"root\":\"dddddddddddddddddddddddddddddddddddddddd\",\"trees\":{\"\":\"dddddddddddddddddddddddddddddddddddddddd\",\"contracts\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}}",
|
||||
decode: func(b []byte) (any, error) { var v TreesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "trees answers an error, never none", subject: "", given: "{\"error\":\"the forge's tree listing of novox/mesh-delivery at aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa was cut; no trees are answered from a part\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge's tree listing of novox/mesh-delivery at aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa was cut; no trees are answered from a part\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v TreesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "file asks", subject: "", given: "{\"path\":\"seats/index.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"repository\":\"novox/mesh-contracts\"}", wire: "{\"path\":\"seats/index.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"repository\":\"novox/mesh-contracts\"}",
|
||||
decode: func(b []byte) (any, error) { var v FileInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "file answers", subject: "", given: "{\"blob\":\"2222222222222222222222222222222222222222\",\"content\":\"{\\\"format\\\":1,\\\"seats\\\":[\\\"mesh-broker\\\"]}\",\"path\":\"seats/index.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"size\":31}", wire: "{\"blob\":\"2222222222222222222222222222222222222222\",\"content\":\"{\\\"format\\\":1,\\\"seats\\\":[\\\"mesh-broker\\\"]}\",\"path\":\"seats/index.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"size\":31}",
|
||||
decode: func(b []byte) (any, error) { var v FileAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "file answers", subject: "", given: "{\"absent\":true,\"path\":\"seats/gone.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}", wire: "{\"absent\":true,\"path\":\"seats/gone.json\",\"ref\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}",
|
||||
decode: func(b []byte) (any, error) { var v FileAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "file answers an error, never none", subject: "", given: "{\"error\":\"seats/big.json is over 512 KiB\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"seats/big.json is over 512 KiB\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v FileAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "contains asks", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"in\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"in\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v ContainsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "contains answers", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"contains\":true,\"in\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"contains\":true,\"in\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"}",
|
||||
decode: func(b []byte) (any, error) { var v ContainsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "contains answers an error, never none", subject: "", given: "{\"error\":\"the forge cannot compare bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge cannot compare bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v ContainsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "contains answers a commit the forge does not have as not-found", subject: "", given: "{\"error\":\"the forge has no commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"error-kind\":\"not-found\"}", wire: "{\"error\":\"the forge has no commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"error-kind\":\"not-found\"}",
|
||||
decode: func(b []byte) (any, error) { var v ContainsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "statuses asks", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"repository\":\"novox/mesh-sdk\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v StatusesInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "statuses answers", subject: "", given: "{\"combined\":\"success\",\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"statuses\":[{\"at\":\"2026-11-09T19:00:00Z\",\"by\":\"mesh-delivery-checker\",\"context\":\"mesh/check\",\"description\":\"passed\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}]}", wire: "{\"combined\":\"success\",\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"statuses\":[{\"at\":\"2026-11-09T19:00:00Z\",\"by\":\"mesh-delivery-checker\",\"context\":\"mesh/check\",\"description\":\"passed\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v StatusesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "statuses answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 500\",\"error-kind\":\"failed\"}", wire: "{\"error\":\"the forge answered 500\",\"error-kind\":\"failed\"}",
|
||||
decode: func(b []byte) (any, error) { var v StatusesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "status asks", subject: "", given: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"context\":\"mesh/check\",\"description\":\"checking\",\"id\":\"owed-1\",\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\"}", wire: "{\"commit\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"context\":\"mesh/check\",\"description\":\"checking\",\"id\":\"owed-1\",\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\"}",
|
||||
decode: func(b []byte) (any, error) { var v StatusInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "status answers", subject: "", given: "{\"id\":\"owed-1\",\"performed\":true}", wire: "{\"id\":\"owed-1\",\"performed\":true}",
|
||||
decode: func(b []byte) (any, error) { var v StatusAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "status answers an error, never none", subject: "", given: "{\"error\":\"the forge account cannot write novox/mesh-sdk\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge account cannot write novox/mesh-sdk\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v StatusAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "comment asks", subject: "", given: "{\"id\":\"owed-2\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"text\":\"the delivery reached every node\"}", wire: "{\"id\":\"owed-2\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"text\":\"the delivery reached every node\"}",
|
||||
decode: func(b []byte) (any, error) { var v CommentInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "comment answers", subject: "", given: "{\"held\":true,\"id\":\"owed-2\"}", wire: "{\"held\":true,\"id\":\"owed-2\"}",
|
||||
decode: func(b []byte) (any, error) { var v CommentAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "comment answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 403\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge answered 403\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v CommentAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "view asks", subject: "", given: "{\"id\":\"owed-3\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"text\":\"## Delivery\"}", wire: "{\"id\":\"owed-3\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"text\":\"## Delivery\"}",
|
||||
decode: func(b []byte) (any, error) { var v ViewInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "view answers", subject: "", given: "{\"id\":\"owed-3\",\"performed\":true}", wire: "{\"id\":\"owed-3\",\"performed\":true}",
|
||||
decode: func(b []byte) (any, error) { var v ViewAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "view answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\"}", wire: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\"}",
|
||||
decode: func(b []byte) (any, error) { var v ViewAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "note asks", subject: "", given: "{\"commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"id\":\"owed-4\",\"line\":\"owed-4 delivered to ace\",\"repository\":\"novox/mesh-sdk\"}", wire: "{\"commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"id\":\"owed-4\",\"line\":\"owed-4 delivered to ace\",\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v NoteInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "note answers", subject: "", given: "{\"id\":\"owed-4\",\"performed\":true}", wire: "{\"id\":\"owed-4\",\"performed\":true}",
|
||||
decode: func(b []byte) (any, error) { var v NoteAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "note answers an error, never none", subject: "", given: "{\"error\":\"the note ref could not be pushed\",\"error-kind\":\"failed\"}", wire: "{\"error\":\"the note ref could not be pushed\",\"error-kind\":\"failed\"}",
|
||||
decode: func(b []byte) (any, error) { var v NoteAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "merge-pull asks", subject: "", given: "{\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"owed-5\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"owed-5\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v MergePullInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "merge-pull answers", subject: "", given: "{\"id\":\"owed-5\",\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"performed\":true}", wire: "{\"id\":\"owed-5\",\"merge-commit\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"performed\":true}",
|
||||
decode: func(b []byte) (any, error) { var v MergePullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "merge-pull answers", subject: "", given: "{\"id\":\"owed-5\",\"refused\":\"the head moved: cccccccccccccccccccccccccccccccccccccccc, not the named aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"refused-kind\":\"head-moved\"}", wire: "{\"id\":\"owed-5\",\"refused\":\"the head moved: cccccccccccccccccccccccccccccccccccccccc, not the named aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"refused-kind\":\"head-moved\"}",
|
||||
decode: func(b []byte) (any, error) { var v MergePullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "merge-pull answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\"}", wire: "{\"error\":\"the forge answered 502\",\"error-kind\":\"failed\"}",
|
||||
decode: func(b []byte) (any, error) { var v MergePullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "merge-pull refuses a failed required step, naming the run, the module and the step", subject: "", given: "{\"id\":\"merge-7\",\"module\":\"nats\",\"refused\":\"unit of nats:program failed at fp-0123 in main.12.nats\",\"refused-kind\":\"policy-failed\",\"run\":\"main.12.nats\",\"step\":\"unit\"}", wire: "{\"id\":\"merge-7\",\"module\":\"nats\",\"refused\":\"unit of nats:program failed at fp-0123 in main.12.nats\",\"refused-kind\":\"policy-failed\",\"run\":\"main.12.nats\",\"step\":\"unit\"}",
|
||||
decode: func(b []byte) (any, error) { var v MergePullAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "branch asks a branch", subject: "", given: "{\"branch\":\"main\",\"repository\":\"novox/mesh-catalog\"}", wire: "{\"branch\":\"main\",\"repository\":\"novox/mesh-catalog\"}",
|
||||
decode: func(b []byte) (any, error) { var v BranchInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "branch answers its head and protection", subject: "", given: "{\"branch\":\"main\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"protected\":true,\"repository\":\"novox/mesh-catalog\"}", wire: "{\"branch\":\"main\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"protected\":true,\"repository\":\"novox/mesh-catalog\"}",
|
||||
decode: func(b []byte) (any, error) { var v BranchAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "branch answers a branch the forge does not hold", subject: "", given: "{\"error\":\"no branch beta in novox/mesh-catalog\",\"error-kind\":\"not-found\"}", wire: "{\"error\":\"no branch beta in novox/mesh-catalog\",\"error-kind\":\"not-found\"}",
|
||||
decode: func(b []byte) (any, error) { var v BranchAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tag asks", subject: "", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"tag\":\"go/v0.1.15\"}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"tag\":\"go/v0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v TagInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tag answers performed", subject: "", given: "{\"performed\":true,\"tag\":\"go/v0.1.15\"}", wire: "{\"performed\":true,\"tag\":\"go/v0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v TagAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "tag answers an error, never none", subject: "", given: "{\"error\":\"the forge answered 403\",\"error-kind\":\"refused\"}", wire: "{\"error\":\"the forge answered 403\",\"error-kind\":\"refused\"}",
|
||||
decode: func(b []byte) (any, error) { var v TagAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
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/git
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,121 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshbuilds is the contract of the seat "mesh-builds", defined whole (seats/mesh-builds/seat.json): The builder's seat: it says each artifact it published and each agreed toolchain, and answers a module's reserved version. Held once for the mesh (design 47 G section 52, section 307).
|
||||
package meshbuilds
|
||||
|
||||
import "time"
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-builds"
|
||||
|
||||
const (
|
||||
VerbReserved = "reserved"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPackagePublished = "package-published"
|
||||
EventToolchainAgreed = "toolchain-agreed"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbReserved}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventPackagePublished, EventToolchainAgreed}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-builds.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamPackagePublished is the stream package-published is kept in.
|
||||
const StreamPackagePublished = "SEAT_mesh-builds_package-published"
|
||||
|
||||
// SubjectPackagePublished is where package-published is published.
|
||||
const SubjectPackagePublished = "mesh.seat.mesh-builds.event.package-published"
|
||||
|
||||
// StreamToolchainAgreed is the stream toolchain-agreed is kept in.
|
||||
const StreamToolchainAgreed = "SEAT_mesh-builds_toolchain-agreed"
|
||||
|
||||
// SubjectToolchainAgreed is where toolchain-agreed is published.
|
||||
const SubjectToolchainAgreed = "mesh.seat.mesh-builds.event.toolchain-agreed"
|
||||
|
||||
// Dependency is a dependency the build resolved, named by the build module in its step key and carried by the builder (design 47 G section 374).
|
||||
type Dependency struct {
|
||||
// the dependency's artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
// the digest of the part, as the build used it
|
||||
Digest string `json:"digest"`
|
||||
// 1 an imported package, 3 the build toolchain (design 47 G section 374)
|
||||
Kind int64 `json:"kind"`
|
||||
// the version of the dependency the build resolved
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// PackagePublished is one artifact published at the module's reserved version (design 47 G section 52, section 334).
|
||||
type PackagePublished struct {
|
||||
// the package's artifact reference, <module>:<artifact>, from the catalog entry
|
||||
Artifact string `json:"artifact"`
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the watched branch the build was made from
|
||||
Branch string `json:"branch"`
|
||||
// each dependency the build resolved, with its version and digest
|
||||
Dependencies []Dependency `json:"dependencies,omitempty"`
|
||||
// the published artifact's digest
|
||||
Digest string `json:"digest"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// the source revision of that branch the build was made from
|
||||
Source int64 `json:"source"`
|
||||
V int64 `json:"v"`
|
||||
// the version the build reserved, MAJOR.MINOR.PATCH
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// ToolchainAgreed is the agreed toolchain of a language changed (design 47 G section 376, ADR 0584 section 1).
|
||||
type ToolchainAgreed struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the toolchain part's digest
|
||||
Digest string `json:"digest"`
|
||||
// the language whose agreed toolchain changed
|
||||
Language string `json:"language"`
|
||||
V int64 `json:"v"`
|
||||
// the agreed toolchain's version
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// ReservedInput is what reserved takes.
|
||||
type ReservedInput struct {
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// the version, when asked for a particular one
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// ReservedAnswerArtifactsItem is a type of the contract.
|
||||
type ReservedAnswerArtifactsItem struct {
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
// its digest once built; empty before
|
||||
Digest string `json:"digest,omitempty"`
|
||||
}
|
||||
|
||||
// ReservedAnswer is what reserved answers.
|
||||
type ReservedAnswer struct {
|
||||
Artifacts []ReservedAnswerArtifactsItem `json:"artifacts"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// the reserved version, MAJOR.MINOR.PATCH
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// PackagePublishedEvent is the body of the event package-published.
|
||||
type PackagePublishedEvent = PackagePublished
|
||||
|
||||
// ToolchainAgreedEvent is the body of the event toolchain-agreed.
|
||||
type ToolchainAgreedEvent = ToolchainAgreed
|
||||
@@ -0,0 +1,54 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package meshbuilds
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/mesh-builds/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 package published with the dependencies the build resolved", subject: "mesh.seat.mesh-builds.event.package-published", given: "{\"artifact\":\"mesh-sdk:go\",\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"dependencies\":[{\"artifact\":\"mesh-contracts:go-nodeengine\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"version\":\"0.1.4\"},{\"artifact\":\"mesh-build-go:toolchain\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":3,\"version\":\"1.26.0\"}],\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}", wire: "{\"artifact\":\"mesh-sdk:go\",\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"dependencies\":[{\"artifact\":\"mesh-contracts:go-nodeengine\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"version\":\"0.1.4\"},{\"artifact\":\"mesh-build-go:toolchain\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":3,\"version\":\"1.26.0\"}],\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v PackagePublishedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-builds\\.event\\.package-published$")},
|
||||
{name: "a toolchain agreed", subject: "mesh.seat.mesh-builds.event.toolchain-agreed", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"language\":\"go\",\"v\":1,\"version\":\"1.26.0\"}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"language\":\"go\",\"v\":1,\"version\":\"1.26.0\"}",
|
||||
decode: func(b []byte) (any, error) { var v ToolchainAgreedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-builds\\.event\\.toolchain-agreed$")},
|
||||
{name: "reserved asks a module", subject: "", given: "{\"module\":\"mesh-sdk\"}", wire: "{\"module\":\"mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v ReservedInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "reserved answers the version and each artifact's digest", subject: "", given: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},{\"artifact\":\"mesh-sdk:ts\"}],\"module\":\"mesh-sdk\",\"version\":\"0.1.15\"}", wire: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},{\"artifact\":\"mesh-sdk:ts\"}],\"module\":\"mesh-sdk\",\"version\":\"0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v ReservedAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
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/meshbuilds
|
||||
|
||||
go 1.26.0
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,26 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a trunk revision kept, on the seat's subject", subject: "mesh.seat.mesh-catalog.event.catalog-revision.main", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"branch\":\"main\",\"changed\":[\"xclip\"],\"entries\":2,\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"branch\":\"main\",\"changed\":[\"xclip\"],\"entries\":2,\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v CatalogRevisionEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.catalog-revision\\.[^.*> ]+$")},
|
||||
{name: "a candidate's revision kept", subject: "mesh.seat.mesh-catalog.event.catalog-revision.main", given: "{\"branch\":\"main\",\"entries\":2,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"revision\":13,\"source\":3589,\"v\":1}", wire: "{\"branch\":\"main\",\"entries\":2,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"revision\":13,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v CatalogRevisionEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.catalog-revision\\.[^.*> ]+$")},
|
||||
{name: "the store past 80 % of its cap", subject: "mesh.seat.mesh-catalog.event.filling", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":450000000,\"cap\":536870912,\"store\":\"catalog-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":450000000,\"cap\":536870912,\"store\":\"catalog-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v FillingEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.filling$")},
|
||||
{name: "the store full, naming what it refuses", subject: "mesh.seat.mesh-catalog.event.full", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":536870912,\"cap\":536870912,\"refused\":\"the next revision; source revision 3590 held pending with the reason objects full\",\"store\":\"catalog-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":536870912,\"cap\":536870912,\"refused\":\"the next revision; source revision 3590 held pending with the reason objects full\",\"store\":\"catalog-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v FullEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.full$")},
|
||||
{name: "the store back below its cap", subject: "mesh.seat.mesh-catalog.event.room", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":300000000,\"cap\":536870912,\"store\":\"catalog-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":300000000,\"cap\":536870912,\"store\":\"catalog-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v RoomEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.room$")},
|
||||
{name: "a registration changed on its warrant", subject: "mesh.seat.mesh-catalog.event.registration-changed", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"by\":\"operator@shanks\",\"module\":\"nats\",\"moved\":[\"nats:program unit: required -\\u003e bypass\"],\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"by\":\"operator@shanks\",\"module\":\"nats\",\"moved\":[\"nats:program unit: required -\\u003e bypass\"],\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v RegistrationChangedEvent
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.registration-changed$")},
|
||||
{name: "a version released", subject: "mesh.seat.mesh-catalog.event.version-released", given: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}", wire: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v VersionReleasedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.version-released$")},
|
||||
{name: "the versions filled", subject: "mesh.seat.mesh-catalog.event.versions-filled", given: "{\"at\":\"2026-11-11T10:00:00Z\",\"modules\":120,\"v\":1}", wire: "{\"at\":\"2026-11-11T10:00:00Z\",\"modules\":120,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v VersionsFilledEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-catalog\\.event\\.versions-filled$")},
|
||||
{name: "a manifest (xclip, read through mesh-catalog.module)", subject: "", given: "{\"manifest\":\"{\\\"build\\\":{\\\"artifacts\\\":[{\\\"binary\\\":\\\"xclip-tools\\\",\\\"from\\\":\\\"cmd/xclip-tools\\\",\\\"kind\\\":\\\"bundle\\\",\\\"language\\\":\\\"go\\\",\\\"loads\\\":[\\\"xclip-tools\\\"],\\\"name\\\":\\\"tools\\\",\\\"system\\\":\\\"arch\\\"}]},\\\"capabilities\\\":[\\\"package-manager\\\"],\\\"module\\\":\\\"xclip\\\",\\\"resources\\\":[{\\\"id\\\":\\\"package\\\",\\\"package\\\":\\\"xclip\\\",\\\"type\\\":\\\"package\\\"}],\\\"tools\\\":[\\\"xclip_copy\\\",\\\"xclip_paste\\\",\\\"xclip_targets\\\",\\\"xclip_session\\\"],\\\"version\\\":\\\"1\\\"}\",\"module\":\"xclip\",\"v\":1}", wire: "{\"manifest\":\"{\\\"build\\\":{\\\"artifacts\\\":[{\\\"binary\\\":\\\"xclip-tools\\\",\\\"from\\\":\\\"cmd/xclip-tools\\\",\\\"kind\\\":\\\"bundle\\\",\\\"language\\\":\\\"go\\\",\\\"loads\\\":[\\\"xclip-tools\\\"],\\\"name\\\":\\\"tools\\\",\\\"system\\\":\\\"arch\\\"}]},\\\"capabilities\\\":[\\\"package-manager\\\"],\\\"module\\\":\\\"xclip\\\",\\\"resources\\\":[{\\\"id\\\":\\\"package\\\",\\\"package\\\":\\\"xclip\\\",\\\"type\\\":\\\"package\\\"}],\\\"tools\\\":[\\\"xclip_copy\\\",\\\"xclip_paste\\\",\\\"xclip_targets\\\",\\\"xclip_session\\\"],\\\"version\\\":\\\"1\\\"}\",\"module\":\"xclip\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v ManifestsByDigestValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a module (xclip, read through mesh-catalog.modules; the inputs and toolchains no tool reads are not here)", subject: "", given: "{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp2\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"v\":1}", wire: "{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp2\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"v\":1}",
|
||||
@@ -53,6 +73,104 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v ModulesAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "the module verb (captured: xclip)", subject: "", given: "{\"module\":{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"manifest\":{\"build\":{\"artifacts\":[{\"binary\":\"xclip-tools\",\"from\":\"cmd/xclip-tools\",\"kind\":\"bundle\",\"language\":\"go\",\"loads\":[\"xclip-tools\"],\"name\":\"tools\",\"system\":\"arch\"}]},\"capabilities\":[\"package-manager\"],\"module\":\"xclip\",\"resources\":[{\"id\":\"package\",\"package\":\"xclip\",\"type\":\"package\"}],\"tools\":[\"xclip_copy\",\"xclip_paste\",\"xclip_targets\",\"xclip_session\"],\"version\":\"1\"},\"module\":\"xclip\",\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\"}}", wire: "{\"module\":{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"manifest\":{\"build\":{\"artifacts\":[{\"binary\":\"xclip-tools\",\"from\":\"cmd/xclip-tools\",\"kind\":\"bundle\",\"language\":\"go\",\"loads\":[\"xclip-tools\"],\"name\":\"tools\",\"system\":\"arch\"}]},\"capabilities\":[\"package-manager\"],\"module\":\"xclip\",\"resources\":[{\"id\":\"package\",\"package\":\"xclip\",\"type\":\"package\"}],\"tools\":[\"xclip_copy\",\"xclip_paste\",\"xclip_targets\",\"xclip_session\"],\"version\":\"1\"},\"module\":\"xclip\",\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\"}}",
|
||||
decode: func(b []byte) (any, error) { var v ModuleAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a watched branch's catalog graph revision", subject: "", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"branch\":\"main\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"branch\":\"main\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v CatalogRevisionsByBranchRevisionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a candidate's catalog graph revision", subject: "", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"revision\":13,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"revision\":13,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v CatalogRevisionsByCandidateGroupHeadsValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a catalog graph entry (xclip)", subject: "", given: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", wire: "{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v CatalogRevisionsByEntryDigestValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an acting part's entry carries the rule of the seat it claims", subject: "", given: "{\"acts\":[{\"bound\":\"60m\",\"on\":\"go\",\"seat\":\"node-build-go\",\"step\":\"build\"}],\"awaits\":[\"database\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"left-out\":[\"mesh-catalog.revision\"],\"main\":\"cmd/mesh-build-go\",\"manifest\":{\"module\":\"mesh-build-go\",\"version\":\"1\"},\"module\":\"mesh-build-go\",\"needs\":[\"form:setting\",\"word:claims\"],\"path\":\"modules/mesh-build-go\",\"repository\":\"novox/mesh-catalog\",\"serves\":[\"node-build-go.run\"],\"v\":1,\"verdict\":\"accepted\"}", wire: "{\"acts\":[{\"bound\":\"60m\",\"on\":\"go\",\"seat\":\"node-build-go\",\"step\":\"build\"}],\"awaits\":[\"database\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"left-out\":[\"mesh-catalog.revision\"],\"main\":\"cmd/mesh-build-go\",\"manifest\":{\"module\":\"mesh-build-go\",\"version\":\"1\"},\"module\":\"mesh-build-go\",\"needs\":[\"form:setting\",\"word:claims\"],\"path\":\"modules/mesh-build-go\",\"repository\":\"novox/mesh-catalog\",\"serves\":[\"node-build-go.run\"],\"v\":1,\"verdict\":\"accepted\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v CatalogRevisionsByEntryDigestValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a module's registration", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v RegistrationsByModuleValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "one version kept in the history", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v RegistrationHistoryByModuleVersionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an entry with its artifacts and the edges into them, per artifact", subject: "", given: "{\"artifacts\":[{\"language\":\"go\",\"ref\":\"mesh-grants:program\"},{\"language\":\"go\",\"ref\":\"mesh-grants:tools\"}],\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"edges\":[{\"from\":\"mesh-grants:program\",\"kind\":6,\"to\":\"node-tools:runtime\",\"why\":\"seat mesh-grants verb grants\"},{\"from\":\"node-tools:runtime\",\"kind\":4,\"to\":\"mesh-grants:tools\",\"why\":\"the tool runner runs the tools\"},{\"from\":\"mesh-sdk:go\",\"kind\":1,\"to\":\"mesh-grants:program\",\"why\":\"git.novox.be/novox/mesh-sdk/go\"},{\"declared\":true,\"from\":\"nats:program\",\"kind\":4,\"to\":\"mesh-grants:program\",\"why\":\"declared in needs\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"mesh-grants\",\"version\":\"1\"},\"module\":\"mesh-grants\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}", wire: "{\"artifacts\":[{\"language\":\"go\",\"ref\":\"mesh-grants:program\"},{\"language\":\"go\",\"ref\":\"mesh-grants:tools\"}],\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"edges\":[{\"from\":\"mesh-grants:program\",\"kind\":6,\"to\":\"node-tools:runtime\",\"why\":\"seat mesh-grants verb grants\"},{\"from\":\"node-tools:runtime\",\"kind\":4,\"to\":\"mesh-grants:tools\",\"why\":\"the tool runner runs the tools\"},{\"from\":\"mesh-sdk:go\",\"kind\":1,\"to\":\"mesh-grants:program\",\"why\":\"git.novox.be/novox/mesh-sdk/go\"},{\"declared\":true,\"from\":\"nats:program\",\"kind\":4,\"to\":\"mesh-grants:program\",\"why\":\"declared in needs\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"inputs\":{\"fp-src\":41,\"from\":{\"bases\":[\"arch\"],\"locks\":{\"go.sum\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"packages\":[\"git.novox.be/novox/mesh-sdk/go@v0.0.0-20261101000000-f469eb387a30\"],\"tree\":\"4b825dc642cb6eb9a060e54bf8d69288fbee4904\"},\"src\":41,\"toolchains\":{\"go\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}}},\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"mesh-grants\",\"version\":\"1\"},\"module\":\"mesh-grants\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v CatalogRevisionsByEntryDigestValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a released version", subject: "", given: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}", wire: "{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v VersionsByModuleVersionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a build of another branch", subject: "", given: "{\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"fp\":\"src2:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"source\":3589,\"v\":1}", wire: "{\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"fp\":\"src2:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v BuildEdgesByModuleBranchValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an input", subject: "", given: "\"eyJ2IjoxfQ==\"", wire: "\"eyJ2IjoxfQ==\"",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v InputsByTimeDigestValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "revision asks the trunk's newest", subject: "", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision asks a candidate's, from a page on", subject: "", given: "{\"after\":\"mesh-build-go\",\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}", wire: "{\"after\":\"mesh-build-go\",\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision answers a page and the next", subject: "", given: "{\"entries\":[{\"acts\":[{\"bound\":\"60m\",\"on\":\"go\",\"seat\":\"node-build-go\",\"step\":\"build\"}],\"awaits\":[\"database\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"left-out\":[\"mesh-catalog.revision\"],\"main\":\"cmd/mesh-build-go\",\"manifest\":{\"module\":\"mesh-build-go\",\"version\":\"1\"},\"module\":\"mesh-build-go\",\"needs\":[\"form:setting\",\"word:claims\"],\"path\":\"modules/mesh-build-go\",\"repository\":\"novox/mesh-catalog\",\"serves\":[\"node-build-go.run\"],\"v\":1,\"verdict\":\"accepted\"}],\"next\":\"mesh-build-go\",\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}}", wire: "{\"entries\":[{\"acts\":[{\"bound\":\"60m\",\"on\":\"go\",\"seat\":\"node-build-go\",\"step\":\"build\"}],\"awaits\":[\"database\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"left-out\":[\"mesh-catalog.revision\"],\"main\":\"cmd/mesh-build-go\",\"manifest\":{\"module\":\"mesh-build-go\",\"version\":\"1\"},\"module\":\"mesh-build-go\",\"needs\":[\"form:setting\",\"word:claims\"],\"path\":\"modules/mesh-build-go\",\"repository\":\"novox/mesh-catalog\",\"serves\":[\"node-build-go.run\"],\"v\":1,\"verdict\":\"accepted\"}],\"next\":\"mesh-build-go\",\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision answers its last page", subject: "", given: "{\"entries\":[{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}],\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}}", wire: "{\"entries\":[{\"bases\":[\"arch\"],\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"invokes\":[\"node-files.read\"],\"manifest\":{\"module\":\"xclip\",\"version\":\"1\"},\"module\":\"xclip\",\"packages\":{\"git.novox.be/novox/mesh-sdk/go\":\"v0.0.0-20261101000000-f469eb387a30\"},\"path\":\"modules/xclip\",\"repository\":\"novox/mesh-catalog\",\"toolchains\":{\"go\":{\"module\":\"mesh-build-go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"v\":1,\"verdict\":\"accepted\"}],\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"definitions\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"seat\":\"node-build-go\"}],\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"mesh-build-go\"},{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\"}],\"kind\":\"trunk\",\"revision\":12,\"source\":3589,\"trunk\":[{\"commit\":\"f469eb387a3015569d9b16c66ed418e9dd098f64\",\"repository\":\"novox/mesh-catalog\"}],\"v\":1}}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "registrations of one module with its history", subject: "", given: "{\"history\":true,\"module\":\"nats\"}", wire: "{\"history\":true,\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v RegistrationsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "registrations answers one with its versions", subject: "", given: "{\"history\":[{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":1,\"warrant\":\"ask-m2kx9a1b3c4d5e\"},{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}],\"registrations\":[{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}]}", wire: "{\"history\":[{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":1,\"warrant\":\"ask-m2kx9a1b3c4d5e\"},{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}],\"registrations\":[{\"at\":\"2026-11-10T10:00:00Z\",\"branches\":[\"main\"],\"by\":\"operator@shanks\",\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1,\"version\":2,\"warrant\":\"ask-m2kx9a1b3c4d5e\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v RegistrationsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "register a module whole", subject: "", given: "{\"registration\":{\"branches\":[\"main\"],\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1},\"why\":\"the first registration\"}", wire: "{\"registration\":{\"branches\":[\"main\"],\"module\":\"nats\",\"origin\":\"novox/mesh-catalog\",\"path\":\"modules/nats/module.json\",\"policy\":{\"artifacts\":{\"program\":{\"unit\":\"bypass\"}},\"steps\":{\"approval\":\"bypass\",\"composition\":\"required\",\"integration\":\"required\",\"lint\":\"required\",\"review\":\"optional\",\"unit\":\"required\"}},\"v\":1},\"why\":\"the first registration\"}",
|
||||
decode: func(b []byte) (any, error) { var v RegisterInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "register refused for an unprotected branch", subject: "", given: "{\"module\":\"nats\",\"refused\":\"unprotected branch\",\"words\":\"the branch beta of novox/mesh-catalog admits a direct push\"}", wire: "{\"module\":\"nats\",\"refused\":\"unprotected branch\",\"words\":\"the branch beta of novox/mesh-catalog admits a direct push\"}",
|
||||
decode: func(b []byte) (any, error) { var v RegisterAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "policy moves one artifact's unit step", subject: "", given: "{\"artifact\":\"program\",\"module\":\"nats\",\"steps\":{\"unit\":\"bypass\"},\"why\":\"its tests need hardware\"}", wire: "{\"artifact\":\"program\",\"module\":\"nats\",\"steps\":{\"unit\":\"bypass\"},\"why\":\"its tests need hardware\"}",
|
||||
decode: func(b []byte) (any, error) { var v PolicyInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "policy asked, naming the moved status", subject: "", given: "{\"ask\":\"ask-m2kx9a1b3c4d5e\",\"lines\":[\"nats:program unit: required -\\u003e bypass\"],\"module\":\"nats\"}", wire: "{\"ask\":\"ask-m2kx9a1b3c4d5e\",\"lines\":[\"nats:program unit: required -\\u003e bypass\"],\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v PolicyAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "watch a second branch", subject: "", given: "{\"branch\":\"beta\",\"module\":\"nats\"}", wire: "{\"branch\":\"beta\",\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v WatchInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "unwatch it", subject: "", given: "{\"branch\":\"beta\",\"module\":\"nats\"}", wire: "{\"branch\":\"beta\",\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v UnwatchInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "versions asks a module", subject: "", given: "{\"module\":\"mesh-sdk\"}", wire: "{\"module\":\"mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v VersionsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "versions answers the released versions with their edges", subject: "", given: "{\"module\":\"mesh-sdk\",\"versions\":[{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}]}", wire: "{\"module\":\"mesh-sdk\",\"versions\":[{\"artifacts\":[{\"artifact\":\"mesh-sdk:go\",\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}],\"edges\":[{\"digest\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"kind\":1,\"part\":\"mesh-contracts:go-nodeengine\",\"stale\":true,\"version\":\"0.1.4\",\"word\":\"imports\"}],\"module\":\"mesh-sdk\",\"source\":3589,\"v\":1,\"version\":\"0.1.15\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v VersionsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "outdated asks for one dependency", subject: "", given: "{\"branch\":\"main\",\"dependency\":\"mesh-sdk:go\"}", wire: "{\"branch\":\"main\",\"dependency\":\"mesh-sdk:go\"}",
|
||||
decode: func(b []byte) (any, error) { var v OutdatedInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "outdated answers an entry behind", subject: "", given: "{\"behind\":[{\"act\":\"rebuild\",\"dependency\":{\"artifact\":\"mesh-sdk:go\",\"branch\":\"main\",\"source\":3589},\"kind\":1,\"module\":\"nats\",\"newest\":\"0.1.15 sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"recorded\":\"0.1.14 sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"version\":\"1.2.3\"}]}", wire: "{\"behind\":[{\"act\":\"rebuild\",\"dependency\":{\"artifact\":\"mesh-sdk:go\",\"branch\":\"main\",\"source\":3589},\"kind\":1,\"module\":\"nats\",\"newest\":\"0.1.15 sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"recorded\":\"0.1.14 sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"version\":\"1.2.3\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v OutdatedAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "input asks a step's input by digest", subject: "", given: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}", wire: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}",
|
||||
decode: func(b []byte) (any, error) { var v InputInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "input answers the exact bytes", subject: "", given: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"input\":\"eyJ2IjoxfQ==\"}", wire: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"input\":\"eyJ2IjoxfQ==\"}",
|
||||
decode: func(b []byte) (any, error) { var v InputAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "entry asks by fingerprint", subject: "", given: "{\"fingerprint\":\"src2:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}", wire: "{\"fingerprint\":\"src2:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}",
|
||||
decode: func(b []byte) (any, error) { var v EntryInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -15,54 +15,116 @@ import (
|
||||
const Seat = "mesh-delivery"
|
||||
|
||||
const (
|
||||
VerbDeliveries = "deliveries"
|
||||
VerbTimes = "times"
|
||||
VerbShow = "show"
|
||||
VerbGroups = "groups"
|
||||
VerbWhatIf = "what-if"
|
||||
VerbChecks = "checks"
|
||||
VerbTable = "table"
|
||||
VerbStalled = "stalled"
|
||||
VerbRecheck = "recheck"
|
||||
VerbRelease = "release"
|
||||
VerbStop = "stop"
|
||||
VerbClose = "close"
|
||||
VerbRetireHistory = "retire-history"
|
||||
VerbSettle = "settle"
|
||||
VerbDeliveries = "deliveries"
|
||||
VerbShow = "show"
|
||||
VerbGroups = "groups"
|
||||
VerbSource = "source"
|
||||
VerbStalled = "stalled"
|
||||
VerbRecovery = "recovery"
|
||||
)
|
||||
|
||||
const (
|
||||
EventOwed = "owed"
|
||||
EventPinned = "pinned"
|
||||
EventFreed = "freed"
|
||||
EventHeadsReplaced = "heads-replaced"
|
||||
EventRecordOpened = "record-opened"
|
||||
EventRecordEnded = "record-ended"
|
||||
EventFilling = "filling"
|
||||
EventFull = "full"
|
||||
EventRoom = "room"
|
||||
EventSourceMoved = "source-moved"
|
||||
EventRecoveryMerged = "recovery-merged"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbDeliveries, VerbTimes, VerbShow, VerbGroups, VerbWhatIf, VerbChecks, VerbTable, VerbStalled, VerbRecheck, VerbRelease, VerbStop, VerbClose, VerbRetireHistory, VerbSettle}
|
||||
return []string{VerbDeliveries, VerbShow, VerbGroups, VerbSource, VerbStalled, VerbRecovery}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventOwed, EventPinned, EventFreed, EventHeadsReplaced, EventRecordOpened, EventRecordEnded, EventFilling, EventFull, EventRoom, EventSourceMoved, EventRecoveryMerged}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-delivery.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamOwed is the stream owed is kept in.
|
||||
const StreamOwed = "SEAT_mesh-delivery_owed"
|
||||
|
||||
// SubjectOwed is where owed is published, on mesh.seat.mesh-delivery.event.owed.<repository>.<number>.
|
||||
func SubjectOwed(repository, number string) string {
|
||||
return "mesh.seat.mesh-delivery.event.owed." + repository + "." + number
|
||||
}
|
||||
|
||||
// SubjectOwedAll hears every owed.
|
||||
const SubjectOwedAll = "mesh.seat.mesh-delivery.event.owed.*.*"
|
||||
|
||||
// SubjectPinned is where pinned is published.
|
||||
const SubjectPinned = "mesh.seat.mesh-delivery.event.pinned"
|
||||
|
||||
// SubjectFreed is where freed is published.
|
||||
const SubjectFreed = "mesh.seat.mesh-delivery.event.freed"
|
||||
|
||||
// SubjectHeadsReplaced is where heads-replaced is published.
|
||||
const SubjectHeadsReplaced = "mesh.seat.mesh-delivery.event.heads-replaced"
|
||||
|
||||
// SubjectRecordOpened is where record-opened is published.
|
||||
const SubjectRecordOpened = "mesh.seat.mesh-delivery.event.record-opened"
|
||||
|
||||
// SubjectRecordEnded is where record-ended is published.
|
||||
const SubjectRecordEnded = "mesh.seat.mesh-delivery.event.record-ended"
|
||||
|
||||
// SubjectFilling is where filling is published.
|
||||
const SubjectFilling = "mesh.seat.mesh-delivery.event.filling"
|
||||
|
||||
// SubjectFull is where full is published.
|
||||
const SubjectFull = "mesh.seat.mesh-delivery.event.full"
|
||||
|
||||
// SubjectRoom is where room is published.
|
||||
const SubjectRoom = "mesh.seat.mesh-delivery.event.room"
|
||||
|
||||
// SubjectSourceMoved is where source-moved is published, on mesh.seat.mesh-delivery.event.source-moved.<branch>.
|
||||
func SubjectSourceMoved(branch string) string {
|
||||
return "mesh.seat.mesh-delivery.event.source-moved." + branch
|
||||
}
|
||||
|
||||
// SubjectSourceMovedAll hears every source-moved.
|
||||
const SubjectSourceMovedAll = "mesh.seat.mesh-delivery.event.source-moved.*"
|
||||
|
||||
// SubjectRecoveryMerged is where recovery-merged is published.
|
||||
const SubjectRecoveryMerged = "mesh.seat.mesh-delivery.event.recovery-merged"
|
||||
|
||||
const (
|
||||
StateSource = "source"
|
||||
StateMerges = "merges"
|
||||
StateAsks = "asks"
|
||||
StateOwed = "owed"
|
||||
StateTurns = "turns"
|
||||
)
|
||||
|
||||
// SourceByMainKey is the key of one value of the state source under the form "main".
|
||||
func SourceByMainKey() string { return "main" }
|
||||
// SourceByBranchKey is the key of one value of the state source under the form "<branch>".
|
||||
func SourceByBranchKey(branch string) string { return branch }
|
||||
|
||||
// ParseSourceByMainKey reads the parts of a key of the form "main", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseSourceByMainKey(key string) bool {
|
||||
// ParseSourceByBranchKey reads the parts of a key of the form "<branch>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseSourceByBranchKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "main") {
|
||||
return false
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[4:]
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return false
|
||||
return "", false
|
||||
}
|
||||
return true
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeSourceByMainValue reads one value of the state source under the form "main", refusing a field SourceByMainValue does not know and any text after the value.
|
||||
func DecodeSourceByMainValue(raw []byte) (SourceByMainValue, error) {
|
||||
var v SourceByMainValue
|
||||
// DecodeSourceByBranchValue reads one value of the state source under the form "<branch>", refusing a field SourceByBranchValue does not know and any text after the value.
|
||||
func DecodeSourceByBranchValue(raw []byte) (SourceByBranchValue, error) {
|
||||
var v SourceByBranchValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
@@ -105,46 +167,6 @@ func DecodeMergesByGroupValue(raw []byte) (MergesByGroupValue, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AsksByMergeGroupHeadsKey is the key of one value of the state asks under the form "merge.<group>.<heads>".
|
||||
func AsksByMergeGroupHeadsKey(group, heads string) string { return "merge." + group + "." + heads }
|
||||
|
||||
// ParseAsksByMergeGroupHeadsKey reads the parts of a key of the form "merge.<group>.<heads>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByMergeGroupHeadsKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "merge.") {
|
||||
return "", "", false
|
||||
}
|
||||
rest = rest[6:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after1
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v3 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v1, v3, true
|
||||
}
|
||||
|
||||
// DecodeAsksByMergeGroupHeadsValue reads one value of the state asks under the form "merge.<group>.<heads>", refusing a field AsksByMergeGroupHeadsValue does not know and any text after the value.
|
||||
func DecodeAsksByMergeGroupHeadsValue(raw []byte) (AsksByMergeGroupHeadsValue, error) {
|
||||
var v AsksByMergeGroupHeadsValue
|
||||
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
|
||||
}
|
||||
|
||||
// OwedByRepositoryNumberHeadActKey is the key of one value of the state owed under the form "<repository>.<number>.<head>.<act>".
|
||||
func OwedByRepositoryNumberHeadActKey(repository, number, head, act string) string {
|
||||
return repository + "." + number + "." + head + "." + act
|
||||
@@ -193,35 +215,158 @@ func DecodeOwedByRepositoryNumberHeadActValue(raw []byte) (OwedByRepositoryNumbe
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// TurnsByRepositoryKey is the key of one value of the state turns under the form "<repository>".
|
||||
func TurnsByRepositoryKey(repository string) string { return repository }
|
||||
|
||||
// ParseTurnsByRepositoryKey reads the parts of a key of the form "<repository>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseTurnsByRepositoryKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
// Act is an act the gate said for a group, with its recorded outcome once the forge bridge said one.
|
||||
type Act struct {
|
||||
// when the outcome was recorded
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the outcome the forge bridge said as owed.ended and the gate recorded; absent while unanswered
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
Owed Owed `json:"owed"`
|
||||
// the forge's own words for a refusal, the error for an act that could not be performed, why one is undecodable or dropped
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// DecodeTurnsByRepositoryValue reads one value of the state turns under the form "<repository>", refusing a field TurnsByRepositoryValue does not know and any text after the value.
|
||||
func DecodeTurnsByRepositoryValue(raw []byte) (TurnsByRepositoryValue, error) {
|
||||
var v TurnsByRepositoryValue
|
||||
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
|
||||
// The values of Act's outcome.
|
||||
const (
|
||||
ActOutcomePerformed = "performed"
|
||||
ActOutcomeRefused = "refused"
|
||||
ActOutcomeCouldNotBePerformed = "could not be performed"
|
||||
ActOutcomeUndecodable = "undecodable"
|
||||
ActOutcomeDropped = "dropped"
|
||||
)
|
||||
|
||||
// Ask is the one Approve ask of a milestone (ADR 0493 §9), said apart from each delivery's transition.
|
||||
type Ask struct {
|
||||
// on answered: approve or decline
|
||||
Answer string `json:"answer,omitempty"`
|
||||
// the ask's id
|
||||
Ask string `json:"ask"`
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// on answered: who answered
|
||||
By string `json:"by,omitempty"`
|
||||
// its delivery group
|
||||
Group string `json:"group"`
|
||||
// repository to the head asked
|
||||
Heads map[string]string `json:"heads,omitempty"`
|
||||
// the milestone
|
||||
Milestone string `json:"milestone"`
|
||||
// on withdrawn: why, such as a new head of a member
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// Fill is the delivery records' ledger's fill against its cap.
|
||||
type Fill struct {
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Bytes int64 `json:"bytes"`
|
||||
// bytes
|
||||
Cap int64 `json:"cap"`
|
||||
// what full refuses, such as the next record
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// the kept data, by its name in the holder's manifest
|
||||
Store string `json:"store"`
|
||||
}
|
||||
|
||||
// Group is one delivery group: its members, its derived state and the acts the gate said for it.
|
||||
type Group struct {
|
||||
// the acts the gate said for it, each with its id and its recorded outcome; an id said and not answered is the forge bridge's to perform
|
||||
Acts []Act `json:"acts"`
|
||||
// the group's check: its verdict, or asked as <id>
|
||||
Check string `json:"check,omitempty"`
|
||||
// the group's id, its branch
|
||||
ID string `json:"id"`
|
||||
// its members in merge order
|
||||
Members []Member `json:"members"`
|
||||
// its state, derived from its members
|
||||
State string `json:"state"`
|
||||
// why it is in that state
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// Member is one member of a group: a pull request.
|
||||
type Member struct {
|
||||
// the branch it merges into
|
||||
Base string `json:"base,omitempty"`
|
||||
// its head
|
||||
Head string `json:"head"`
|
||||
// the member's delivery id
|
||||
ID string `json:"id"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the pull request is open: not merged, closed or final
|
||||
Open bool `json:"open,omitempty"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// the member's delivery state
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
// Owed is one act the gate owes the forge, said once under its id and safe to repeat at the forge (design 47 *What the gate owes the forge*); the forge bridge performs it through the seat git's verb of the same act.
|
||||
type Owed struct {
|
||||
// the act: merge (the seat git's merge-pull), status, view, comment or note
|
||||
Act string `json:"act"`
|
||||
// the operator's ask that approved the heads, for a merge
|
||||
Ask string `json:"ask,omitempty"`
|
||||
// the commit a status or a note line is on; the head when absent
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// a status: its context, such as mesh/merge-gate
|
||||
Context string `json:"context,omitempty"`
|
||||
// a status: what it says
|
||||
Description string `json:"description,omitempty"`
|
||||
// the delivery group the pull request is a member of, for a merge
|
||||
Group string `json:"group,omitempty"`
|
||||
// the pull request's head the act is for
|
||||
Head string `json:"head"`
|
||||
// the act's id, the same each time it is said again; a comment and a note line carry it, so the forge holds it once
|
||||
ID string `json:"id"`
|
||||
// a note line: the one line
|
||||
Line string `json:"line,omitempty"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// when the gate first said it
|
||||
Said *time.Time `json:"said,omitempty"`
|
||||
// a status: its state, pending, success, failure or error
|
||||
State string `json:"state,omitempty"`
|
||||
// a status: the page it links to
|
||||
Target string `json:"target,omitempty"`
|
||||
// a comment or the view: the text, markdown
|
||||
Text string `json:"text,omitempty"`
|
||||
}
|
||||
|
||||
// The values of Owed's act.
|
||||
const (
|
||||
OwedActMerge = "merge"
|
||||
OwedActStatus = "status"
|
||||
OwedActView = "view"
|
||||
OwedActComment = "comment"
|
||||
OwedActNote = "note"
|
||||
)
|
||||
|
||||
// Pins is the graph revisions a delivery record starts or stops pointing at.
|
||||
type Pins struct {
|
||||
// assignment graph revisions, by their number on the seat mesh-wants
|
||||
Assignment []int64 `json:"assignment,omitempty"`
|
||||
// catalog graph revisions, by their number on the seat mesh-catalog
|
||||
Catalog []int64 `json:"catalog,omitempty"`
|
||||
// the record's milestone
|
||||
Milestone string `json:"milestone"`
|
||||
// the record's id
|
||||
Record string `json:"record"`
|
||||
// on freed: the record ended past its retention, or was removed by hand
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// SourceHead is one repository of the source revision: its trunk branch and that trunk's head.
|
||||
type SourceHead struct {
|
||||
// the trunk's head the source revision names
|
||||
Head string `json:"head"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// its trunk branch, such as main
|
||||
Trunk string `json:"trunk"`
|
||||
}
|
||||
|
||||
// DeliveriesInput is what deliveries takes.
|
||||
@@ -245,13 +390,6 @@ const (
|
||||
// DeliveriesAnswer is what deliveries answers.
|
||||
type DeliveriesAnswer = map[string]any
|
||||
|
||||
// TimesInput is what times takes.
|
||||
type TimesInput struct {
|
||||
}
|
||||
|
||||
// TimesAnswer is what times answers.
|
||||
type TimesAnswer = map[string]any
|
||||
|
||||
// ShowInput is what show takes.
|
||||
type ShowInput struct {
|
||||
// a delivery's id, or a group's
|
||||
@@ -265,6 +403,8 @@ type ShowAnswer = map[string]any
|
||||
type GroupsInput struct {
|
||||
// "true": the groups that ended too
|
||||
All string `json:"all,omitempty"`
|
||||
// one group's id: that group alone, ended or not
|
||||
Group string `json:"group,omitempty"`
|
||||
}
|
||||
|
||||
// The values of GroupsInput's all.
|
||||
@@ -274,35 +414,32 @@ const (
|
||||
)
|
||||
|
||||
// GroupsAnswer is what groups answers.
|
||||
type GroupsAnswer = map[string]any
|
||||
|
||||
// WhatIfInput is what what-if takes.
|
||||
type WhatIfInput struct {
|
||||
type GroupsAnswer struct {
|
||||
// why it could not answer at all; a group it does not know is answered with no groups, never an error
|
||||
Error string `json:"error,omitempty"`
|
||||
Groups []Group `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
// WhatIfAnswer is what what-if answers.
|
||||
type WhatIfAnswer = map[string]any
|
||||
|
||||
// ChecksInput is what checks takes.
|
||||
type ChecksInput struct {
|
||||
// a commit's sha, or the start of one, instead of a pull request
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// a pull request's number: its head is read
|
||||
Number string `json:"number,omitempty"`
|
||||
// owner/repository
|
||||
Repository string `json:"repository"`
|
||||
// SourceInput is what source takes.
|
||||
type SourceInput struct {
|
||||
// the watched branch, escaped as a key name is
|
||||
Branch string `json:"branch"`
|
||||
}
|
||||
|
||||
// ChecksAnswer is what checks answers.
|
||||
type ChecksAnswer = map[string]any
|
||||
|
||||
// TableInput is what table takes.
|
||||
type TableInput struct {
|
||||
// SourceAnswer is what source answers.
|
||||
type SourceAnswer struct {
|
||||
// the watched branch the source revision is of
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// why it could not be read
|
||||
Error string `json:"error,omitempty"`
|
||||
// the group that moved the source revision last; absent before the first
|
||||
Group string `json:"group,omitempty"`
|
||||
// every repository the source revision names, by name
|
||||
Repositories []SourceHead `json:"repositories,omitempty"`
|
||||
// the source revision's number on the bus; 0 before the first
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
}
|
||||
|
||||
// TableAnswer is what table answers.
|
||||
type TableAnswer = map[string]any
|
||||
|
||||
// StalledInput is what stalled takes.
|
||||
type StalledInput struct {
|
||||
}
|
||||
@@ -310,62 +447,123 @@ type StalledInput struct {
|
||||
// StalledAnswer is what stalled answers.
|
||||
type StalledAnswer = map[string]any
|
||||
|
||||
// RecheckInput is what recheck takes.
|
||||
type RecheckInput struct {
|
||||
// the delivery's id
|
||||
ID string `json:"id"`
|
||||
// why, kept with the transition
|
||||
// RecoveryInput is what recovery takes.
|
||||
type RecoveryInput struct {
|
||||
// the merge commit
|
||||
Commit string `json:"commit"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// why the merge is a recovery
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// RecheckAnswer is what recheck answers.
|
||||
type RecheckAnswer = map[string]any
|
||||
|
||||
// ReleaseInput is what release takes.
|
||||
type ReleaseInput struct {
|
||||
// RecoveryAnswer is what recovery answers.
|
||||
type RecoveryAnswer struct {
|
||||
// the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the merge commit
|
||||
Commit string `json:"commit"`
|
||||
Recovery bool `json:"recovery"`
|
||||
// the repository
|
||||
Repository string `json:"repository,omitempty"`
|
||||
}
|
||||
|
||||
// ReleaseAnswer is what release answers.
|
||||
type ReleaseAnswer = map[string]any
|
||||
// OwedEvent is the body of the event owed.
|
||||
type OwedEvent = Owed
|
||||
|
||||
// StopInput is what stop takes.
|
||||
type StopInput struct {
|
||||
// PinnedEvent is the body of the event pinned.
|
||||
type PinnedEvent = Pins
|
||||
|
||||
// FreedEvent is the body of the event freed.
|
||||
type FreedEvent = Pins
|
||||
|
||||
// HeadsReplacedEvent is the body of the event heads-replaced.
|
||||
type HeadsReplacedEvent struct {
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the pull request closed
|
||||
Closed bool `json:"closed,omitempty"`
|
||||
// the group
|
||||
Group string `json:"group"`
|
||||
// its new head; absent when it closed
|
||||
Head string `json:"head,omitempty"`
|
||||
// the candidate's heads, 12 hex digits, as its revisions are keyed
|
||||
Heads string `json:"heads"`
|
||||
// its pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the member whose head moved or which closed
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// StopAnswer is what stop answers.
|
||||
type StopAnswer = map[string]any
|
||||
// RecordOpenedEvent is the body of the event record-opened.
|
||||
type RecordOpenedEvent struct {
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// a merge made at the forge, with no Approve
|
||||
ForgeMade bool `json:"forge-made,omitempty"`
|
||||
// its milestone
|
||||
Milestone string `json:"milestone"`
|
||||
// the record's id
|
||||
Record string `json:"record"`
|
||||
}
|
||||
|
||||
// CloseInput is what close takes.
|
||||
type CloseInput struct {
|
||||
// the delivery's id
|
||||
ID string `json:"id"`
|
||||
// the condition it answers
|
||||
// RecordEndedEventAwayItem is a type of the contract.
|
||||
type RecordEndedEventAwayItem struct {
|
||||
// a node away
|
||||
Node string `json:"node"`
|
||||
// since when
|
||||
Since *time.Time `json:"since,omitempty"`
|
||||
}
|
||||
|
||||
// RecordEndedEvent is the body of the event record-ended.
|
||||
type RecordEndedEvent struct {
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the nodes away, each with since when; it ends without them
|
||||
Away []RecordEndedEventAwayItem `json:"away,omitempty"`
|
||||
// a merge made at the forge, with no Approve
|
||||
ForgeMade bool `json:"forge-made,omitempty"`
|
||||
// its milestone
|
||||
Milestone string `json:"milestone"`
|
||||
// the record's id
|
||||
Record string `json:"record"`
|
||||
}
|
||||
|
||||
// FillingEvent is the body of the event filling.
|
||||
type FillingEvent = Fill
|
||||
|
||||
// FullEvent is the body of the event full.
|
||||
type FullEvent = Fill
|
||||
|
||||
// RoomEvent is the body of the event room.
|
||||
type RoomEvent = Fill
|
||||
|
||||
// SourceMovedEvent is the body of the event source-moved.
|
||||
type SourceMovedEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Branch string `json:"branch"`
|
||||
// the group that moved it, when one did
|
||||
Group string `json:"group,omitempty"`
|
||||
Revision int64 `json:"revision"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// RecoveryMergedEvent is the body of the event recovery-merged.
|
||||
type RecoveryMergedEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the merge commit
|
||||
Commit string `json:"commit"`
|
||||
// the repository
|
||||
Repository string `json:"repository"`
|
||||
V int64 `json:"v"`
|
||||
// why
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CloseAnswer is what close answers.
|
||||
type CloseAnswer = map[string]any
|
||||
|
||||
// RetireHistoryInput is what retire-history takes.
|
||||
type RetireHistoryInput struct {
|
||||
}
|
||||
|
||||
// RetireHistoryAnswer is what retire-history answers.
|
||||
type RetireHistoryAnswer = map[string]any
|
||||
|
||||
// SettleInput is what settle takes.
|
||||
type SettleInput struct {
|
||||
// the held deliveries' ids (owner/repository@commit)
|
||||
Ids []string `json:"ids"`
|
||||
// why they may be settled, shown to the operator
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// SettleAnswer is what settle answers.
|
||||
type SettleAnswer = map[string]any
|
||||
|
||||
// SourceByMainValue is one value of the state source under the key main.
|
||||
type SourceByMainValue struct {
|
||||
// SourceByBranchValue is one value of the state source under the key <branch>.
|
||||
type SourceByBranchValue struct {
|
||||
// the group that moved it
|
||||
Group string `json:"group"`
|
||||
// repository to the merged head, a full commit
|
||||
@@ -397,27 +595,6 @@ type MergesByGroupValue struct {
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// AsksByMergeGroupHeadsValueHeadsItem is a type of the contract.
|
||||
type AsksByMergeGroupHeadsValueHeadsItem struct {
|
||||
// the full commit
|
||||
Head string `json:"head"`
|
||||
Number int64 `json:"number"`
|
||||
// <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
}
|
||||
|
||||
// AsksByMergeGroupHeadsValue is one value of the state asks under the key merge.<group>.<heads>.
|
||||
type AsksByMergeGroupHeadsValue struct {
|
||||
// the operator-channel ask as raised
|
||||
Ask any `json:"ask"`
|
||||
// the number of times it was asked
|
||||
Asking int64 `json:"asking,omitempty"`
|
||||
Group string `json:"group"`
|
||||
Heads []AsksByMergeGroupHeadsValueHeadsItem `json:"heads"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// OwedByRepositoryNumberHeadActValue is one value of the state owed under the key <repository>.<number>.<head>.<act>.
|
||||
type OwedByRepositoryNumberHeadActValue struct {
|
||||
// status=<context>, view, note or comment.<seq>
|
||||
@@ -430,26 +607,3 @@ type OwedByRepositoryNumberHeadActValue struct {
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// TurnsByRepositoryValueWaitingItem is a type of the contract.
|
||||
type TurnsByRepositoryValueWaitingItem struct {
|
||||
// when (RFC 3339 time)
|
||||
Approved time.Time `json:"approved"`
|
||||
Ask string `json:"ask,omitempty"`
|
||||
Group string `json:"group"`
|
||||
Heads string `json:"heads"`
|
||||
// when (RFC 3339 time)
|
||||
Since time.Time `json:"since"`
|
||||
Step string `json:"step,omitempty"`
|
||||
WaitsFor string `json:"waits-for,omitempty"`
|
||||
// when (RFC 3339 time)
|
||||
WaitsSince *time.Time `json:"waits-since,omitempty"`
|
||||
}
|
||||
|
||||
// TurnsByRepositoryValue is one value of the state turns under the key <repository>.
|
||||
type TurnsByRepositoryValue struct {
|
||||
Repository string `json:"repository"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
Waiting []TurnsByRepositoryValueWaitingItem `json:"waiting"`
|
||||
}
|
||||
|
||||
@@ -17,24 +17,58 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "owed is said, a merge", subject: "mesh.seat.mesh-delivery.event.owed.novox/mesh-sdk.178", given: "{\"act\":\"merge\",\"ask\":\"merge.feat=47-G.0123456789ab\",\"group\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"merge.feat=47-G.0123456789ab.novox/mesh-sdk#178\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:00:00Z\"}", wire: "{\"act\":\"merge\",\"ask\":\"merge.feat=47-G.0123456789ab\",\"group\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"merge.feat=47-G.0123456789ab.novox/mesh-sdk#178\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:00:00Z\"}",
|
||||
decode: func(b []byte) (any, error) { var v OwedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.owed\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "owed is said, a status", subject: "mesh.seat.mesh-delivery.event.owed.novox/mesh-sdk.178", given: "{\"act\":\"status\",\"context\":\"mesh/merge-gate\",\"description\":\"waits for the operator's Approve\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/merge-gate\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\",\"target\":\"https://forge.test/x\"}", wire: "{\"act\":\"status\",\"context\":\"mesh/merge-gate\",\"description\":\"waits for the operator's Approve\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/merge-gate\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\",\"target\":\"https://forge.test/x\"}",
|
||||
decode: func(b []byte) (any, error) { var v OwedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.owed\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "pinned is said", subject: "mesh.seat.mesh-delivery.event.pinned", given: "{\"assignment\":[1204],\"catalog\":[3610],\"milestone\":\"47/G\",\"record\":\"47-G\"}", wire: "{\"assignment\":[1204],\"catalog\":[3610],\"milestone\":\"47/G\",\"record\":\"47-G\"}",
|
||||
decode: func(b []byte) (any, error) { var v PinnedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.pinned$")},
|
||||
{name: "freed is said", subject: "mesh.seat.mesh-delivery.event.freed", given: "{\"assignment\":[1204],\"catalog\":[3610],\"milestone\":\"47/G\",\"record\":\"47-G\",\"why\":\"past its retention of 90 days\"}", wire: "{\"assignment\":[1204],\"catalog\":[3610],\"milestone\":\"47/G\",\"record\":\"47-G\",\"why\":\"past its retention of 90 days\"}",
|
||||
decode: func(b []byte) (any, error) { var v FreedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.freed$")},
|
||||
{name: "heads-replaced is said", subject: "mesh.seat.mesh-delivery.event.heads-replaced", given: "{\"at\":\"2026-11-09T20:05:00Z\",\"group\":\"feat/47-G\",\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"heads\":\"0123456789ab\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"at\":\"2026-11-09T20:05:00Z\",\"group\":\"feat/47-G\",\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"heads\":\"0123456789ab\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v HeadsReplacedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.heads-replaced$")},
|
||||
{name: "heads-replaced is said for a closed pull request", subject: "mesh.seat.mesh-delivery.event.heads-replaced", given: "{\"closed\":true,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"closed\":true,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"number\":178,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v HeadsReplacedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.heads-replaced$")},
|
||||
{name: "record-opened is said", subject: "mesh.seat.mesh-delivery.event.record-opened", given: "{\"at\":\"2026-11-09T18:00:00Z\",\"milestone\":\"47/G\",\"record\":\"47-G\"}", wire: "{\"at\":\"2026-11-09T18:00:00Z\",\"milestone\":\"47/G\",\"record\":\"47-G\"}",
|
||||
decode: func(b []byte) (any, error) { var v RecordOpenedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.record-opened$")},
|
||||
{name: "record-ended is said", subject: "mesh.seat.mesh-delivery.event.record-ended", given: "{\"at\":\"2026-11-09T21:00:00Z\",\"away\":[{\"node\":\"laptop\",\"since\":\"2026-11-09T18:00:00Z\"}],\"milestone\":\"47/G\",\"record\":\"47-G\"}", wire: "{\"at\":\"2026-11-09T21:00:00Z\",\"away\":[{\"node\":\"laptop\",\"since\":\"2026-11-09T18:00:00Z\"}],\"milestone\":\"47/G\",\"record\":\"47-G\"}",
|
||||
decode: func(b []byte) (any, error) { var v RecordEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.record-ended$")},
|
||||
{name: "filling is said", subject: "mesh.seat.mesh-delivery.event.filling", given: "{\"bytes\":650000000,\"cap\":805306368,\"store\":\"records\"}", wire: "{\"bytes\":650000000,\"cap\":805306368,\"store\":\"records\"}",
|
||||
decode: func(b []byte) (any, error) { var v FillingEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.filling$")},
|
||||
{name: "full is said", subject: "mesh.seat.mesh-delivery.event.full", given: "{\"bytes\":805306368,\"cap\":805306368,\"refused\":\"the next record\",\"store\":\"records\"}", wire: "{\"bytes\":805306368,\"cap\":805306368,\"refused\":\"the next record\",\"store\":\"records\"}",
|
||||
decode: func(b []byte) (any, error) { var v FullEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.full$")},
|
||||
{name: "room is said", subject: "mesh.seat.mesh-delivery.event.room", given: "{\"bytes\":400000000,\"cap\":805306368,\"store\":\"records\"}", wire: "{\"bytes\":400000000,\"cap\":805306368,\"store\":\"records\"}",
|
||||
decode: func(b []byte) (any, error) { var v RoomEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.room$")},
|
||||
{name: "main moved to its next source revision", subject: "mesh.seat.mesh-delivery.event.source-moved.main", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"revision\":3590,\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"revision\":3590,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v SourceMovedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.source-moved\\.[^.*> ]+$")},
|
||||
{name: "a recovery merged", subject: "mesh.seat.mesh-delivery.event.recovery-merged", given: "{\"at\":\"2026-11-11T10:00:00Z\",\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"v\":1,\"why\":\"the live delivery was broken\"}", wire: "{\"at\":\"2026-11-11T10:00:00Z\",\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"v\":1,\"why\":\"the live delivery was broken\"}",
|
||||
decode: func(b []byte) (any, error) { var v RecoveryMergedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery\\.event\\.recovery-merged$")},
|
||||
{name: "the source revision", subject: "", given: "{\"group\":\"feat/registry\",\"heads\":{\"novox/mesh-sdk\":\"cccccccccccccccccccccccccccccccccccccccc\"},\"v\":1}", wire: "{\"group\":\"feat/registry\",\"heads\":{\"novox/mesh-sdk\":\"cccccccccccccccccccccccccccccccccccccccc\"},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v SourceByMainValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
decode: func(b []byte) (any, error) { var v SourceByBranchValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a merge", subject: "", given: "{\"ask\":\"merge.feat=registry.0123456789ab\",\"group\":\"feat/registry\",\"pulls\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"v\":1}", wire: "{\"ask\":\"merge.feat=registry.0123456789ab\",\"group\":\"feat/registry\",\"pulls\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v MergesByGroupValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask", subject: "", given: "{\"ask\":{\"headline\":\"merge\"},\"group\":\"feat/registry\",\"heads\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\"}],\"v\":1}", wire: "{\"ask\":{\"headline\":\"merge\"},\"group\":\"feat/registry\",\"heads\":[{\"head\":\"cccccccccccccccccccccccccccccccccccccccc\",\"number\":1,\"repository\":\"novox/mesh-sdk\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AsksByMergeGroupHeadsValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an act owed", subject: "", given: "{\"act\":\"view\",\"v\":1}", wire: "{\"act\":\"view\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v OwedByRepositoryNumberHeadActValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a turn", subject: "", given: "{\"repository\":\"novox/mesh-sdk\",\"v\":1,\"waiting\":[{\"approved\":\"2026-11-05T10:00:00Z\",\"group\":\"feat/registry\",\"heads\":\"0123456789ab\",\"since\":\"2026-11-05T10:01:00Z\"}]}", wire: "{\"repository\":\"novox/mesh-sdk\",\"v\":1,\"waiting\":[{\"approved\":\"2026-11-05T10:00:00Z\",\"group\":\"feat/registry\",\"heads\":\"0123456789ab\",\"since\":\"2026-11-05T10:01:00Z\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v TurnsByRepositoryValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "groups asks for one group", subject: "", given: "{\"group\":\"feat/47-G\"}", wire: "{\"group\":\"feat/47-G\"}",
|
||||
decode: func(b []byte) (any, error) { var v GroupsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "groups answers a group with its members and acts", subject: "", given: "{\"groups\":[{\"acts\":[{\"at\":\"2026-11-09T20:01:00Z\",\"outcome\":\"performed\",\"owed\":{\"act\":\"merge\",\"ask\":\"merge.feat=47-G.0123456789ab\",\"group\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"merge.feat=47-G.0123456789ab.novox/mesh-sdk#178\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:00:00Z\"}},{\"owed\":{\"act\":\"status\",\"context\":\"mesh/merge-gate\",\"description\":\"waits for the operator's Approve\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/merge-gate\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\",\"target\":\"https://forge.test/x\"}}],\"check\":\"pass\",\"id\":\"feat/47-G\",\"members\":[{\"base\":\"main\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"novox/mesh-sdk#178\",\"number\":178,\"open\":true,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"state\":\"merging\",\"why\":\"novox/mesh-sdk#178 merges first\"}]}", wire: "{\"groups\":[{\"acts\":[{\"at\":\"2026-11-09T20:01:00Z\",\"outcome\":\"performed\",\"owed\":{\"act\":\"merge\",\"ask\":\"merge.feat=47-G.0123456789ab\",\"group\":\"feat/47-G\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"merge.feat=47-G.0123456789ab.novox/mesh-sdk#178\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:00:00Z\"}},{\"owed\":{\"act\":\"status\",\"context\":\"mesh/merge-gate\",\"description\":\"waits for the operator's Approve\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/merge-gate\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"state\":\"pending\",\"target\":\"https://forge.test/x\"}}],\"check\":\"pass\",\"id\":\"feat/47-G\",\"members\":[{\"base\":\"main\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"novox/mesh-sdk#178\",\"number\":178,\"open\":true,\"repository\":\"novox/mesh-sdk\",\"state\":\"merging\"}],\"state\":\"merging\",\"why\":\"novox/mesh-sdk#178 merges first\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v GroupsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "groups answers a group it does not know with no groups", subject: "", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v GroupsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "source is asked with nothing", subject: "", given: "{\"branch\":\"main\"}", wire: "{\"branch\":\"main\"}",
|
||||
decode: func(b []byte) (any, error) { var v SourceInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "source answers each repository's trunk and head", subject: "", given: "{\"branch\":\"main\",\"group\":\"feat/47-G\",\"repositories\":[{\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\",\"trunk\":\"main\"}],\"revision\":42}", wire: "{\"branch\":\"main\",\"group\":\"feat/47-G\",\"repositories\":[{\"head\":\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"repository\":\"novox/mesh-sdk\",\"trunk\":\"main\"}],\"revision\":42}",
|
||||
decode: func(b []byte) (any, error) { var v SourceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "source answers an error when it cannot be read", subject: "", given: "{\"error\":\"source.main is not readable\"}", wire: "{\"error\":\"source.main is not readable\"}",
|
||||
decode: func(b []byte) (any, error) { var v SourceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "recovery names a merge and why", subject: "", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"why\":\"the live delivery was broken\"}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\",\"why\":\"the live delivery was broken\"}",
|
||||
decode: func(b []byte) (any, error) { var v RecoveryInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "recovery answers the caller the runtime proved", subject: "", given: "{\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"recovery\":true,\"repository\":\"novox/mesh-sdk\"}", wire: "{\"by\":\"jochen\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"recovery\":true,\"repository\":\"novox/mesh-sdk\"}",
|
||||
decode: func(b []byte) (any, error) { var v RecoveryAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshdeliverychecker is the contract of the seat "mesh-delivery-checker", defined whole (seats/mesh-delivery-checker/seat.json): The merge check's tries: start one, read one, end one. The checker's own events stay under its own subjects (ADR 0620 §2).
|
||||
// Package meshdeliverychecker is the contract of the seat "mesh-delivery-checker", defined whole (seats/mesh-delivery-checker/seat.json): The merge check's tries: start one, read one, end one. The seat says each check's end as checked and what the checker owes the forge as owed; the checker's other events stay under its own subjects (ADR 0620 §2).
|
||||
package meshdeliverychecker
|
||||
|
||||
import (
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
@@ -20,11 +21,41 @@ const (
|
||||
VerbInput = "input"
|
||||
)
|
||||
|
||||
const (
|
||||
EventChecked = "checked"
|
||||
EventOwed = "owed"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbTry, VerbTryRead, VerbTryEnd, VerbInput}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventChecked, EventOwed}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-delivery-checker.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectChecked is where checked is published.
|
||||
const SubjectChecked = "mesh.seat.mesh-delivery-checker.event.checked"
|
||||
|
||||
// StreamOwed is the stream owed is kept in.
|
||||
const StreamOwed = "SEAT_mesh-delivery-checker_owed"
|
||||
|
||||
// SubjectOwed is where owed is published, on mesh.seat.mesh-delivery-checker.event.owed.<repository>.<number>.
|
||||
func SubjectOwed(repository, number string) string {
|
||||
return "mesh.seat.mesh-delivery-checker.event.owed." + repository + "." + number
|
||||
}
|
||||
|
||||
// SubjectOwedAll hears every owed.
|
||||
const SubjectOwedAll = "mesh.seat.mesh-delivery-checker.event.owed.*.*"
|
||||
|
||||
// The holder's own events, listed beside the seat and published under the holder's subjects (ADR 0620 §2).
|
||||
const (
|
||||
HolderEventVerdict = "verdict"
|
||||
@@ -215,6 +246,45 @@ func DecodePreviewsByRepositoryHeadTrunkValue(raw []byte) (PreviewsByRepositoryH
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// CheckedEntry is one entry of the candidate checked: a module at its fingerprint.
|
||||
type CheckedEntry struct {
|
||||
// the entry's fingerprint
|
||||
Fp string `json:"fp"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// the node it was composed for, when the check composed it on one
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// Owed is the status the checker owes the forge for a head, said under its id and safe to repeat (a status replaces what stands); the forge bridge performs it through the seat git's verb status (design 47 *What the gate owes the forge*).
|
||||
type Owed struct {
|
||||
// the act: always status
|
||||
Act string `json:"act"`
|
||||
// its context, mesh/check
|
||||
Context string `json:"context"`
|
||||
// what it says
|
||||
Description string `json:"description,omitempty"`
|
||||
// the pull request's head the status is on
|
||||
Head string `json:"head"`
|
||||
// the act's id, the same each time it is said again
|
||||
ID string `json:"id"`
|
||||
// the pull request's number
|
||||
Number int64 `json:"number"`
|
||||
// the repository, <owner>/<name>
|
||||
Repository string `json:"repository"`
|
||||
// when the checker first said it
|
||||
Said *time.Time `json:"said,omitempty"`
|
||||
// pending, success, failure or error
|
||||
State string `json:"state"`
|
||||
// the page it links to
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
// The values of Owed's act.
|
||||
const (
|
||||
OwedActStatus = "status"
|
||||
)
|
||||
|
||||
// TryInputMembersItem is a type of the contract.
|
||||
type TryInputMembersItem struct {
|
||||
// the full commit to try, 40 or 64 hex digits
|
||||
@@ -288,6 +358,36 @@ type InputAnswer struct {
|
||||
Input string `json:"input"`
|
||||
}
|
||||
|
||||
// CheckedEvent is the body of the event checked.
|
||||
type CheckedEvent struct {
|
||||
// when
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the candidate's catalog graph revision judged, by its number on the seat mesh-catalog
|
||||
Catalog int64 `json:"catalog,omitempty"`
|
||||
// the entries checked
|
||||
Entries []CheckedEntry `json:"entries,omitempty"`
|
||||
// the group, its branch
|
||||
Group string `json:"group"`
|
||||
// the heads checked, 12 hex digits, as the candidate's revisions are keyed
|
||||
Heads string `json:"heads"`
|
||||
// the source revision the heads are merged onto
|
||||
Source int64 `json:"source,omitempty"`
|
||||
// pass, fail, or could not run when a part the check needs did not answer
|
||||
Verdict string `json:"verdict"`
|
||||
// what failed first, or the part not heard
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// The values of CheckedEvent's verdict.
|
||||
const (
|
||||
CheckedEventVerdictPass = "pass"
|
||||
CheckedEventVerdictFail = "fail"
|
||||
CheckedEventVerdictCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// OwedEvent is the body of the event owed.
|
||||
type OwedEvent = Owed
|
||||
|
||||
// VerdictHolderEventSeriesItem is a type of the contract.
|
||||
type VerdictHolderEventSeriesItem struct {
|
||||
// its artifact, or the package's ecosystem name as the module's packages name it
|
||||
|
||||
@@ -23,6 +23,12 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v TagWantedHolderEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.stream\\.[a-z0-9-]+\\.event\\.tag-wanted$")},
|
||||
{name: "preview.written on the checker's stream", subject: "mesh.stream.mesh-delivery-checker.event.preview.written", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v map[string]any; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.stream\\.[a-z0-9-]+\\.event\\.preview\\.written$")},
|
||||
{name: "checked is said", subject: "mesh.seat.mesh-delivery-checker.event.checked", given: "{\"at\":\"2026-11-09T20:30:00Z\",\"catalog\":3612,\"entries\":[{\"fp\":\"src2:1480985e\",\"module\":\"mesh-delivery-gate\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"source\":3611,\"verdict\":\"pass\"}", wire: "{\"at\":\"2026-11-09T20:30:00Z\",\"catalog\":3612,\"entries\":[{\"fp\":\"src2:1480985e\",\"module\":\"mesh-delivery-gate\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"source\":3611,\"verdict\":\"pass\"}",
|
||||
decode: func(b []byte) (any, error) { var v CheckedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery-checker\\.event\\.checked$")},
|
||||
{name: "checked is said when it could not run", subject: "mesh.seat.mesh-delivery-checker.event.checked", given: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"verdict\":\"could not run\",\"words\":\"the seat git's holder did not answer\"}", wire: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"verdict\":\"could not run\",\"words\":\"the seat git's holder did not answer\"}",
|
||||
decode: func(b []byte) (any, error) { var v CheckedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery-checker\\.event\\.checked$")},
|
||||
{name: "owed is said", subject: "mesh.seat.mesh-delivery-checker.event.owed.novox/mesh-sdk.178", given: "{\"act\":\"status\",\"context\":\"mesh/check\",\"description\":\"passed\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/check\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:30:00Z\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}", wire: "{\"act\":\"status\",\"context\":\"mesh/check\",\"description\":\"passed\",\"head\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"id\":\"status.novox/mesh-sdk#178.aaaaaaaaaaaa.mesh/check\",\"number\":178,\"repository\":\"novox/mesh-sdk\",\"said\":\"2026-11-09T20:30:00Z\",\"state\":\"success\",\"target\":\"https://forge.test/x\"}",
|
||||
decode: func(b []byte) (any, error) { var v OwedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-delivery-checker\\.event\\.owed\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a running verdict", subject: "", given: "{\"group\":\"feat/registry\",\"heads\":\"0123456789ab\",\"state\":\"running\",\"v\":1}", wire: "{\"group\":\"feat/registry\",\"heads\":\"0123456789ab\",\"state\":\"running\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v VerdictsByGroupHeadsValue
|
||||
|
||||
@@ -0,0 +1,969 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshpipelinerunner is the contract of the seat "mesh-pipeline-runner", defined whole (seats/mesh-pipeline-runner/seat.json): The pipeline runner: it runs each module's pipeline on each of its watched branches, asking each step of the seat that serves it and hearing its end, and says each pipeline's and each step's start and end (design 47 *Pipelines per module*). Held once for the mesh; a foundation part.
|
||||
package meshpipelinerunner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-pipeline-runner"
|
||||
|
||||
const (
|
||||
VerbRun = "run"
|
||||
VerbStart = "start"
|
||||
VerbShow = "show"
|
||||
VerbList = "list"
|
||||
VerbStands = "stands"
|
||||
VerbWhyCarried = "why-carried"
|
||||
VerbKept = "kept"
|
||||
VerbReview = "review"
|
||||
VerbRerun = "rerun"
|
||||
VerbAccept = "accept"
|
||||
VerbCancel = "cancel"
|
||||
VerbAskAgain = "ask-again"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPipelineStarted = "pipeline-started"
|
||||
EventPipelineEnded = "pipeline-ended"
|
||||
EventGroupEnded = "group-ended"
|
||||
EventRunStarted = "run-started"
|
||||
EventStepStarted = "step-started"
|
||||
EventStepEnded = "step-ended"
|
||||
EventWaitHeld = "wait-held"
|
||||
EventWaitEnded = "wait-ended"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbRun, VerbStart, VerbShow, VerbList, VerbStands, VerbWhyCarried, VerbKept, VerbReview, VerbRerun, VerbAccept, VerbCancel, VerbAskAgain}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventPipelineStarted, EventPipelineEnded, EventGroupEnded, EventRunStarted, EventStepStarted, EventStepEnded, EventWaitHeld, EventWaitEnded}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-pipeline-runner.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamPipelineStarted is the stream pipeline-started is kept in.
|
||||
const StreamPipelineStarted = "SEAT_mesh-pipeline-runner_pipeline-started"
|
||||
|
||||
// SubjectPipelineStarted is where pipeline-started is published, on mesh.seat.mesh-pipeline-runner.event.pipeline-started.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectPipelineStarted(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.pipeline-started." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectPipelineStartedAll hears every pipeline-started.
|
||||
const SubjectPipelineStartedAll = "mesh.seat.mesh-pipeline-runner.event.pipeline-started.*.*.*"
|
||||
|
||||
// StreamPipelineEnded is the stream pipeline-ended is kept in.
|
||||
const StreamPipelineEnded = "SEAT_mesh-pipeline-runner_pipeline-ended"
|
||||
|
||||
// SubjectPipelineEnded is where pipeline-ended is published, on mesh.seat.mesh-pipeline-runner.event.pipeline-ended.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectPipelineEnded(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.pipeline-ended." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectPipelineEndedAll hears every pipeline-ended.
|
||||
const SubjectPipelineEndedAll = "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.*.*.*"
|
||||
|
||||
// StreamGroupEnded is the stream group-ended is kept in.
|
||||
const StreamGroupEnded = "SEAT_mesh-pipeline-runner_group-ended"
|
||||
|
||||
// SubjectGroupEnded is where group-ended is published, on mesh.seat.mesh-pipeline-runner.event.group-ended.<branch>.<group>.
|
||||
func SubjectGroupEnded(branch, group string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.group-ended." + branch + "." + group
|
||||
}
|
||||
|
||||
// SubjectGroupEndedAll hears every group-ended.
|
||||
const SubjectGroupEndedAll = "mesh.seat.mesh-pipeline-runner.event.group-ended.*.*"
|
||||
|
||||
// StreamRunStarted is the stream run-started is kept in.
|
||||
const StreamRunStarted = "SEAT_mesh-pipeline-runner_run-started"
|
||||
|
||||
// SubjectRunStarted is where run-started is published, on mesh.seat.mesh-pipeline-runner.event.run-started.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectRunStarted(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.run-started." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectRunStartedAll hears every run-started.
|
||||
const SubjectRunStartedAll = "mesh.seat.mesh-pipeline-runner.event.run-started.*.*.*"
|
||||
|
||||
// StreamStepStarted is the stream step-started is kept in.
|
||||
const StreamStepStarted = "SEAT_mesh-pipeline-runner_step-started"
|
||||
|
||||
// SubjectStepStarted is where step-started is published, on mesh.seat.mesh-pipeline-runner.event.step-started.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectStepStarted(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.step-started." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectStepStartedAll hears every step-started.
|
||||
const SubjectStepStartedAll = "mesh.seat.mesh-pipeline-runner.event.step-started.*.*.*"
|
||||
|
||||
// StreamStepEnded is the stream step-ended is kept in.
|
||||
const StreamStepEnded = "SEAT_mesh-pipeline-runner_step-ended"
|
||||
|
||||
// SubjectStepEnded is where step-ended is published, on mesh.seat.mesh-pipeline-runner.event.step-ended.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectStepEnded(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.step-ended." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectStepEndedAll hears every step-ended.
|
||||
const SubjectStepEndedAll = "mesh.seat.mesh-pipeline-runner.event.step-ended.*.*.*"
|
||||
|
||||
// StreamWaitHeld is the stream wait-held is kept in.
|
||||
const StreamWaitHeld = "SEAT_mesh-pipeline-runner_wait-held"
|
||||
|
||||
// SubjectWaitHeld is where wait-held is published, on mesh.seat.mesh-pipeline-runner.event.wait-held.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectWaitHeld(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.wait-held." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectWaitHeldAll hears every wait-held.
|
||||
const SubjectWaitHeldAll = "mesh.seat.mesh-pipeline-runner.event.wait-held.*.*.*"
|
||||
|
||||
// StreamWaitEnded is the stream wait-ended is kept in.
|
||||
const StreamWaitEnded = "SEAT_mesh-pipeline-runner_wait-ended"
|
||||
|
||||
// SubjectWaitEnded is where wait-ended is published, on mesh.seat.mesh-pipeline-runner.event.wait-ended.<module>.<branch>.<commit-or-group>.
|
||||
func SubjectWaitEnded(module, branch, commitOrGroup string) string {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.wait-ended." + module + "." + branch + "." + commitOrGroup
|
||||
}
|
||||
|
||||
// SubjectWaitEndedAll hears every wait-ended.
|
||||
const SubjectWaitEndedAll = "mesh.seat.mesh-pipeline-runner.event.wait-ended.*.*.*"
|
||||
|
||||
const (
|
||||
StatePipelines = "pipelines"
|
||||
StateKept = "kept"
|
||||
StateStepLog = "step-log"
|
||||
StateStepOutputs = "step-outputs"
|
||||
)
|
||||
|
||||
// PipelinesByBranchRevisionModuleKey is the key of one value of the state pipelines under the form "<branch>.<revision>.<module>".
|
||||
func PipelinesByBranchRevisionModuleKey(branch, revision, module string) string {
|
||||
return branch + "." + revision + "." + module
|
||||
}
|
||||
|
||||
// ParsePipelinesByBranchRevisionModuleKey reads the parts of a key of the form "<branch>.<revision>.<module>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePipelinesByBranchRevisionModuleKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodePipelinesByBranchRevisionModuleValue reads one value of the state pipelines under the form "<branch>.<revision>.<module>", refusing a field PipelinesByBranchRevisionModuleValue does not know and any text after the value.
|
||||
func DecodePipelinesByBranchRevisionModuleValue(raw []byte) (PipelinesByBranchRevisionModuleValue, error) {
|
||||
var v PipelinesByBranchRevisionModuleValue
|
||||
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
|
||||
}
|
||||
|
||||
// KeptByLevelDigestKey is the key of one value of the state kept under the form "<level>.<digest>".
|
||||
func KeptByLevelDigestKey(level, digest string) string { return level + "." + digest }
|
||||
|
||||
// ParseKeptByLevelDigestKey reads the parts of a key of the form "<level>.<digest>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseKeptByLevelDigestKey(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
|
||||
}
|
||||
|
||||
// DecodeKeptByLevelDigestValue reads one value of the state kept under the form "<level>.<digest>", refusing a field KeptByLevelDigestValue does not know and any text after the value.
|
||||
func DecodeKeptByLevelDigestValue(raw []byte) (KeptByLevelDigestValue, error) {
|
||||
var v KeptByLevelDigestValue
|
||||
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
|
||||
}
|
||||
|
||||
// StepLogByPipelineKey is the key of one value of the state step-log under the form "<pipeline>".
|
||||
func StepLogByPipelineKey(pipeline string) string { return pipeline }
|
||||
|
||||
// ParseStepLogByPipelineKey reads the parts of a key of the form "<pipeline>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStepLogByPipelineKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeStepLogByPipelineValue reads one value of the state step-log under the form "<pipeline>", refusing a field StepLogByPipelineValue does not know and any text after the value.
|
||||
func DecodeStepLogByPipelineValue(raw []byte) (StepLogByPipelineValue, error) {
|
||||
var v StepLogByPipelineValue
|
||||
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
|
||||
}
|
||||
|
||||
// StepOutputsByPipelineStepArtifactKey is the key of one value of the state step-outputs under the form "<pipeline>.<step>.<artifact>".
|
||||
func StepOutputsByPipelineStepArtifactKey(pipeline, step, artifact string) string {
|
||||
return pipeline + "." + step + "." + artifact
|
||||
}
|
||||
|
||||
// ParseStepOutputsByPipelineStepArtifactKey reads the parts of a key of the form "<pipeline>.<step>.<artifact>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStepOutputsByPipelineStepArtifactKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodeStepOutputsByPipelineStepArtifactValue reads one value of the state step-outputs under the form "<pipeline>.<step>.<artifact>", refusing a field StepOutputsByPipelineStepArtifactValue does not know and any text after the value.
|
||||
func DecodeStepOutputsByPipelineStepArtifactValue(raw []byte) (StepOutputsByPipelineStepArtifactValue, error) {
|
||||
var v StepOutputsByPipelineStepArtifactValue
|
||||
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
|
||||
}
|
||||
|
||||
// Accepted is a failed optional step a person accepted, recorded in the hand-act log.
|
||||
type Accepted struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// who accepted it, as the runtime proved the caller
|
||||
By string `json:"by"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// Fill is a store's fill against its cap.
|
||||
type Fill struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Bytes int64 `json:"bytes"`
|
||||
// bytes
|
||||
Cap int64 `json:"cap"`
|
||||
// the kept data, by its name in the holder's manifest
|
||||
Store string `json:"store"`
|
||||
}
|
||||
|
||||
// GroupEnded is a group's one pipeline's end on a watched branch, said once every member's modules have ended; a group's wants are written on it alone (ADR 0666 section 9).
|
||||
type GroupEnded struct {
|
||||
Branch string `json:"branch"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
Group string `json:"group"`
|
||||
Outcome string `json:"outcome"`
|
||||
// every member module's pipeline, each ended
|
||||
Pipelines []PipelineEnded `json:"pipelines"`
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the group's one source revision of the watched branch
|
||||
Source int64 `json:"source,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// The values of GroupEnded's outcome.
|
||||
const (
|
||||
GroupEndedOutcomeRunning = "running"
|
||||
GroupEndedOutcomePassed = "passed"
|
||||
GroupEndedOutcomeFailed = "failed"
|
||||
GroupEndedOutcomeRefused = "refused"
|
||||
GroupEndedOutcomeSuperseded = "superseded"
|
||||
GroupEndedOutcomeCancelled = "cancelled"
|
||||
)
|
||||
|
||||
// KeptResult is a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8).
|
||||
type KeptResult struct {
|
||||
// sha256:<hex> of what the package's tests read
|
||||
Digest string `json:"digest"`
|
||||
// unit or integration
|
||||
Level string `json:"level"`
|
||||
Package string `json:"package"`
|
||||
// the pipeline whose step kept it
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// LogEntry is one entry of the step log.
|
||||
type LogEntry struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
At time.Time `json:"at"`
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
// the output's name in step-outputs
|
||||
Output string `json:"output,omitempty"`
|
||||
Pipeline string `json:"pipeline"`
|
||||
Step string `json:"step"`
|
||||
What string `json:"what"`
|
||||
}
|
||||
|
||||
// The values of LogEntry's outcome.
|
||||
const (
|
||||
LogEntryOutcomeRunning = "running"
|
||||
LogEntryOutcomeWaiting = "waiting"
|
||||
LogEntryOutcomePassed = "passed"
|
||||
LogEntryOutcomeFailed = "failed"
|
||||
LogEntryOutcomeNothingToRun = "nothing to run"
|
||||
LogEntryOutcomeBypassed = "bypassed"
|
||||
LogEntryOutcomeCarried = "carried"
|
||||
LogEntryOutcomeCouldNotRun = "could not run"
|
||||
LogEntryOutcomeWaitingForABuildNode = "waiting for a build node"
|
||||
LogEntryOutcomeDidNotBuild = "did not build"
|
||||
LogEntryOutcomeAccepted = "accepted"
|
||||
LogEntryOutcomeDeclined = "declined"
|
||||
LogEntryOutcomeSuperseded = "superseded"
|
||||
LogEntryOutcomeCancelled = "cancelled"
|
||||
)
|
||||
|
||||
// The values of LogEntry's step.
|
||||
const (
|
||||
LogEntryStepLint = "lint"
|
||||
LogEntryStepUnit = "unit"
|
||||
LogEntryStepIntegration = "integration"
|
||||
LogEntryStepComposition = "composition"
|
||||
LogEntryStepReview = "review"
|
||||
LogEntryStepApproval = "approval"
|
||||
)
|
||||
|
||||
// The values of LogEntry's what.
|
||||
const (
|
||||
LogEntryWhatStarted = "started"
|
||||
LogEntryWhatEnded = "ended"
|
||||
)
|
||||
|
||||
// Member is a module at a named commit.
|
||||
type Member struct {
|
||||
// the branch the commit is on
|
||||
Branch string `json:"branch,omitempty"`
|
||||
Commit string `json:"commit"`
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// Pipeline is one pipeline as the runner keeps it in its state pipelines, by compare-and-set (design 47 *The runner's kept data*).
|
||||
type Pipeline struct {
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// the commit the module's entry was last changed at
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the gathered group, when the pipeline is its
|
||||
Group string `json:"group,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Outcome string `json:"outcome"`
|
||||
// yes when the module is over its test budget (design 47 G section 419)
|
||||
OverBudget bool `json:"over-budget,omitempty"`
|
||||
// the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id, for a pipeline of a run; such a pipeline delivers nothing
|
||||
Run string `json:"run,omitempty"`
|
||||
// the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)
|
||||
Source int64 `json:"source,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
// every step, approval last
|
||||
Steps []StepResult `json:"steps"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
// for a pipeline that did not pass, the steps that held it
|
||||
Why string `json:"why,omitempty"`
|
||||
Widens []Widening `json:"widens,omitempty"`
|
||||
}
|
||||
|
||||
// The values of Pipeline's outcome.
|
||||
const (
|
||||
PipelineOutcomeRunning = "running"
|
||||
PipelineOutcomePassed = "passed"
|
||||
PipelineOutcomeFailed = "failed"
|
||||
PipelineOutcomeRefused = "refused"
|
||||
PipelineOutcomeSuperseded = "superseded"
|
||||
PipelineOutcomeCancelled = "cancelled"
|
||||
)
|
||||
|
||||
// PipelineEnded is a pipeline's end with every step's result, its test counts, the source revision and widens (design 47 *Health and going back*); the assigner writes a want only from one whose every required step passed.
|
||||
type PipelineEnded struct {
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// the commit the module's entry was last changed at
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the gathered group, when the pipeline is its
|
||||
Group string `json:"group,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Outcome string `json:"outcome"`
|
||||
// yes when the module is over its test budget (500 unit or 50 integration tests; design 47 G section 419)
|
||||
OverBudget bool `json:"over-budget,omitempty"`
|
||||
// the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id, for a pipeline of a run; such a pipeline delivers nothing
|
||||
Run string `json:"run,omitempty"`
|
||||
// the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)
|
||||
Source int64 `json:"source,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
Steps []StepResult `json:"steps"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
Why string `json:"why,omitempty"`
|
||||
Widens []Widening `json:"widens,omitempty"`
|
||||
}
|
||||
|
||||
// The values of PipelineEnded's outcome.
|
||||
const (
|
||||
PipelineEndedOutcomeRunning = "running"
|
||||
PipelineEndedOutcomePassed = "passed"
|
||||
PipelineEndedOutcomeFailed = "failed"
|
||||
PipelineEndedOutcomeRefused = "refused"
|
||||
PipelineEndedOutcomeSuperseded = "superseded"
|
||||
PipelineEndedOutcomeCancelled = "cancelled"
|
||||
)
|
||||
|
||||
// PipelineStartedStepsItem is a type of the contract.
|
||||
type PipelineStartedStepsItem struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
Status string `json:"status"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of PipelineStartedStepsItem's status.
|
||||
const (
|
||||
PipelineStartedStepsItemStatusRequired = "required"
|
||||
PipelineStartedStepsItemStatusOptional = "optional"
|
||||
PipelineStartedStepsItemStatusBypass = "bypass"
|
||||
)
|
||||
|
||||
// The values of PipelineStartedStepsItem's step.
|
||||
const (
|
||||
PipelineStartedStepsItemStepLint = "lint"
|
||||
PipelineStartedStepsItemStepUnit = "unit"
|
||||
PipelineStartedStepsItemStepIntegration = "integration"
|
||||
PipelineStartedStepsItemStepComposition = "composition"
|
||||
PipelineStartedStepsItemStepReview = "review"
|
||||
PipelineStartedStepsItemStepApproval = "approval"
|
||||
)
|
||||
|
||||
// PipelineStarted is a pipeline's start.
|
||||
type PipelineStarted struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// the commit the module's entry was last changed at
|
||||
Commit string `json:"commit"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the gathered group, when the pipeline is its
|
||||
Group string `json:"group,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id, for a pipeline of a run; such a pipeline delivers nothing
|
||||
Run string `json:"run,omitempty"`
|
||||
// the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)
|
||||
Source int64 `json:"source,omitempty"`
|
||||
// the steps the policy gives it
|
||||
Steps []PipelineStartedStepsItem `json:"steps,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// RunStarted is a run on request's start, with its members at their commits (ADR 0666 section 18).
|
||||
type RunStarted struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the caller the runtime proved
|
||||
By string `json:"by"`
|
||||
Members []Member `json:"members"`
|
||||
Run string `json:"run"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// StepEvent is a step's start or end: the step, its status, its outcome, its fingerprint, its test counts, what a carried result was carried from, and for a rerun that it is one and its proved caller; a bypassed step too.
|
||||
type StepEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// the commit the module's entry was last changed at
|
||||
Commit string `json:"commit"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the gathered group, when the pipeline is its
|
||||
Group string `json:"group,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
Result StepResult `json:"result"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id, for a pipeline of a run; such a pipeline delivers nothing
|
||||
Run string `json:"run,omitempty"`
|
||||
// the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)
|
||||
Source int64 `json:"source,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// StepResult is one step of a pipeline: its status in the policy and its outcome (design 47 *Pipeline steps and the policy*).
|
||||
type StepResult struct {
|
||||
Accepted *Accepted `json:"accepted,omitempty"`
|
||||
// the artifact reference, <module>:<artifact>; absent for a step of the whole module (review, approval)
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
// the step's ask on the serving seat's work queue
|
||||
Ask string `json:"ask,omitempty"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// for a carried result, the pipeline it was carried from
|
||||
CarriedFrom string `json:"carried-from,omitempty"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
// the artifact's build-input fingerprint the step ran at
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
// the node whose holder ended it
|
||||
Node string `json:"node,omitempty"`
|
||||
// for a waiting step, who or what it waits on: a person, a build node, the revision view
|
||||
On string `json:"on,omitempty"`
|
||||
// never passed for a step that ran nothing (design 47 *Pipeline steps and the policy*)
|
||||
Outcome string `json:"outcome"`
|
||||
// the step's output, by its name in the runner's objects step-outputs
|
||||
Output string `json:"output,omitempty"`
|
||||
// the step was asked again by the runner's rerun
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// the seat that serves the step, whose holder alone may end it (ADR 0666 section 21)
|
||||
Seat string `json:"seat,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
// the step's status in the module's policy
|
||||
Status string `json:"status"`
|
||||
Step string `json:"step"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
// what the outcome rests on: the part not heard, the seat with no holder, what a waiting step waits on
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepResult's outcome.
|
||||
const (
|
||||
StepResultOutcomeRunning = "running"
|
||||
StepResultOutcomeWaiting = "waiting"
|
||||
StepResultOutcomePassed = "passed"
|
||||
StepResultOutcomeFailed = "failed"
|
||||
StepResultOutcomeNothingToRun = "nothing to run"
|
||||
StepResultOutcomeBypassed = "bypassed"
|
||||
StepResultOutcomeCarried = "carried"
|
||||
StepResultOutcomeCouldNotRun = "could not run"
|
||||
StepResultOutcomeWaitingForABuildNode = "waiting for a build node"
|
||||
StepResultOutcomeDidNotBuild = "did not build"
|
||||
StepResultOutcomeAccepted = "accepted"
|
||||
StepResultOutcomeDeclined = "declined"
|
||||
StepResultOutcomeSuperseded = "superseded"
|
||||
StepResultOutcomeCancelled = "cancelled"
|
||||
)
|
||||
|
||||
// The values of StepResult's status.
|
||||
const (
|
||||
StepResultStatusRequired = "required"
|
||||
StepResultStatusOptional = "optional"
|
||||
StepResultStatusBypass = "bypass"
|
||||
)
|
||||
|
||||
// The values of StepResult's step.
|
||||
const (
|
||||
StepResultStepLint = "lint"
|
||||
StepResultStepUnit = "unit"
|
||||
StepResultStepIntegration = "integration"
|
||||
StepResultStepComposition = "composition"
|
||||
StepResultStepReview = "review"
|
||||
StepResultStepApproval = "approval"
|
||||
)
|
||||
|
||||
// TestCounts is how many tests a step ran and carried, per level (ADR 0666 section 8).
|
||||
type TestCounts struct {
|
||||
Integration int64 `json:"integration,omitempty"`
|
||||
Unit int64 `json:"unit,omitempty"`
|
||||
}
|
||||
|
||||
// ToolchainUsed is the toolchain a build was made with: the language, the installed version and the build module's recipe.
|
||||
type ToolchainUsed struct {
|
||||
Language string `json:"language"`
|
||||
Recipe string `json:"recipe"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// Wait is a step's wait, held and ended; a wait on a person is said as waiting on that person, never a stall (ADR 0283).
|
||||
type Wait struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// the commit the module's entry was last changed at
|
||||
Commit string `json:"commit,omitempty"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the gathered group, when the pipeline is its
|
||||
Group string `json:"group,omitempty"`
|
||||
// for its end, how it ended: answered, ran, released, superseded
|
||||
How string `json:"how,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// what the step waits on (design 47 *Health and going back*)
|
||||
On string `json:"on"`
|
||||
// the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id, for a pipeline of a run; such a pipeline delivers nothing
|
||||
Run string `json:"run,omitempty"`
|
||||
Since time.Time `json:"since"`
|
||||
// the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9)
|
||||
Source int64 `json:"source,omitempty"`
|
||||
Step string `json:"step"`
|
||||
V int64 `json:"v"`
|
||||
// for a wait on a person, who: the operator, a reviewer
|
||||
Who string `json:"who,omitempty"`
|
||||
}
|
||||
|
||||
// The values of Wait's on.
|
||||
const (
|
||||
WaitOnPerson = "person"
|
||||
WaitOnBuildNode = "build node"
|
||||
WaitOnRevisionView = "revision view"
|
||||
)
|
||||
|
||||
// The values of Wait's step.
|
||||
const (
|
||||
WaitStepLint = "lint"
|
||||
WaitStepUnit = "unit"
|
||||
WaitStepIntegration = "integration"
|
||||
WaitStepComposition = "composition"
|
||||
WaitStepReview = "review"
|
||||
WaitStepApproval = "approval"
|
||||
)
|
||||
|
||||
// Widening is a part serving a step the change alters, or an acting rule, a grant or a credential it widens, computed by the running runner (ADR 0666 section 23).
|
||||
type Widening struct {
|
||||
// the part, rule, grant or credential
|
||||
Name string `json:"name"`
|
||||
// what the change alters in it; for "could not run" the grants part did not answer grants-for (design 47 G section 441)
|
||||
Said string `json:"said,omitempty"`
|
||||
What string `json:"what"`
|
||||
}
|
||||
|
||||
// The values of Widening's what.
|
||||
const (
|
||||
WideningWhatServingPart = "serving part"
|
||||
WideningWhatActingRule = "acting rule"
|
||||
WideningWhatGrant = "grant"
|
||||
WideningWhatCredential = "credential"
|
||||
WideningWhatCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// RunInput is what run takes.
|
||||
type RunInput struct {
|
||||
Members []Member `json:"members"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// RunAnswer is what run answers.
|
||||
type RunAnswer struct {
|
||||
// the pipelines' keys
|
||||
Pipelines []string `json:"pipelines,omitempty"`
|
||||
Run string `json:"run"`
|
||||
}
|
||||
|
||||
// StartInput is what start takes.
|
||||
type StartInput struct {
|
||||
Branch string `json:"branch"`
|
||||
Module string `json:"module"`
|
||||
// why, written with the caller the runtime proves in the hand-act log
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// StartAnswer is what start answers.
|
||||
type StartAnswer struct {
|
||||
Pipeline string `json:"pipeline"`
|
||||
}
|
||||
|
||||
// ShowInput is what show takes.
|
||||
type ShowInput struct {
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
}
|
||||
|
||||
// ShowAnswer is what show answers.
|
||||
type ShowAnswer struct {
|
||||
Fill []Fill `json:"fill,omitempty"`
|
||||
Log []LogEntry `json:"log,omitempty"`
|
||||
// the outputs' names in step-outputs
|
||||
Outputs []string `json:"outputs,omitempty"`
|
||||
Pipeline Pipeline `json:"pipeline"`
|
||||
}
|
||||
|
||||
// ListInput is what list takes.
|
||||
type ListInput struct {
|
||||
Branch string `json:"branch,omitempty"`
|
||||
Commit string `json:"commit,omitempty"`
|
||||
Limit int64 `json:"limit,omitempty"`
|
||||
Module string `json:"module,omitempty"`
|
||||
Run string `json:"run,omitempty"`
|
||||
}
|
||||
|
||||
// ListAnswer is what list answers.
|
||||
type ListAnswer struct {
|
||||
Fill *Fill `json:"fill,omitempty"`
|
||||
Pipelines []Pipeline `json:"pipelines"`
|
||||
}
|
||||
|
||||
// StandsInput is what stands takes.
|
||||
type StandsInput struct {
|
||||
}
|
||||
|
||||
// StandsAnswer is what stands answers.
|
||||
type StandsAnswer struct {
|
||||
Stands []Wait `json:"stands"`
|
||||
}
|
||||
|
||||
// WhyCarriedInput is what why-carried takes.
|
||||
type WhyCarriedInput struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of WhyCarriedInput's step.
|
||||
const (
|
||||
WhyCarriedInputStepLint = "lint"
|
||||
WhyCarriedInputStepUnit = "unit"
|
||||
WhyCarriedInputStepIntegration = "integration"
|
||||
WhyCarriedInputStepComposition = "composition"
|
||||
WhyCarriedInputStepReview = "review"
|
||||
WhyCarriedInputStepApproval = "approval"
|
||||
)
|
||||
|
||||
// WhyCarriedAnswer is what why-carried answers.
|
||||
type WhyCarriedAnswer struct {
|
||||
CarriedFrom string `json:"carried-from,omitempty"`
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
}
|
||||
|
||||
// KeptInput is what kept takes.
|
||||
type KeptInput struct {
|
||||
Digest string `json:"digest,omitempty"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// KeptAnswer is what kept answers.
|
||||
type KeptAnswer struct {
|
||||
Fill *Fill `json:"fill,omitempty"`
|
||||
Kept []KeptResult `json:"kept"`
|
||||
}
|
||||
|
||||
// ReviewInput is what review takes.
|
||||
type ReviewInput struct {
|
||||
Commit string `json:"commit"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Module string `json:"module"`
|
||||
Outcome string `json:"outcome"`
|
||||
// what the review found
|
||||
Said string `json:"said,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ReviewInput's outcome.
|
||||
const (
|
||||
ReviewInputOutcomePassed = "passed"
|
||||
ReviewInputOutcomeFailed = "failed"
|
||||
)
|
||||
|
||||
// ReviewAnswer is what review answers.
|
||||
type ReviewAnswer struct {
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Result StepResult `json:"result"`
|
||||
}
|
||||
|
||||
// RerunInput is what rerun takes.
|
||||
type RerunInput struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
Step string `json:"step"`
|
||||
// why, written with the caller the runtime proves in the hand-act log
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// The values of RerunInput's step.
|
||||
const (
|
||||
RerunInputStepLint = "lint"
|
||||
RerunInputStepUnit = "unit"
|
||||
RerunInputStepIntegration = "integration"
|
||||
RerunInputStepComposition = "composition"
|
||||
RerunInputStepReview = "review"
|
||||
RerunInputStepApproval = "approval"
|
||||
)
|
||||
|
||||
// RerunAnswer is what rerun answers.
|
||||
type RerunAnswer struct {
|
||||
Pipeline string `json:"pipeline"`
|
||||
Result *StepResult `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
// AcceptInput is what accept takes.
|
||||
type AcceptInput struct {
|
||||
Artifact string `json:"artifact,omitempty"`
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
Step string `json:"step"`
|
||||
// why, written with the caller the runtime proves in the hand-act log
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// The values of AcceptInput's step.
|
||||
const (
|
||||
AcceptInputStepLint = "lint"
|
||||
AcceptInputStepUnit = "unit"
|
||||
AcceptInputStepIntegration = "integration"
|
||||
AcceptInputStepComposition = "composition"
|
||||
AcceptInputStepReview = "review"
|
||||
AcceptInputStepApproval = "approval"
|
||||
)
|
||||
|
||||
// AcceptAnswer is what accept answers.
|
||||
type AcceptAnswer struct {
|
||||
Result StepResult `json:"result"`
|
||||
}
|
||||
|
||||
// CancelInput is what cancel takes.
|
||||
type CancelInput struct {
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
// why, written with the caller the runtime proves in the hand-act log
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// CancelAnswer is what cancel answers.
|
||||
type CancelAnswer struct {
|
||||
Pipeline Pipeline `json:"pipeline"`
|
||||
}
|
||||
|
||||
// AskAgainInput is what ask-again takes.
|
||||
type AskAgainInput struct {
|
||||
// the pipeline's key
|
||||
Pipeline string `json:"pipeline"`
|
||||
// why, written with the caller the runtime proves in the hand-act log
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// AskAgainAnswer is what ask-again answers.
|
||||
type AskAgainAnswer struct {
|
||||
Result StepResult `json:"result"`
|
||||
}
|
||||
|
||||
// PipelineStartedEvent is the body of the event pipeline-started.
|
||||
type PipelineStartedEvent = PipelineStarted
|
||||
|
||||
// PipelineEndedEvent is the body of the event pipeline-ended.
|
||||
type PipelineEndedEvent = PipelineEnded
|
||||
|
||||
// GroupEndedEvent is the body of the event group-ended.
|
||||
type GroupEndedEvent = GroupEnded
|
||||
|
||||
// RunStartedEvent is the body of the event run-started.
|
||||
type RunStartedEvent = RunStarted
|
||||
|
||||
// StepStartedEvent is the body of the event step-started.
|
||||
type StepStartedEvent = StepEvent
|
||||
|
||||
// StepEndedEvent is the body of the event step-ended.
|
||||
type StepEndedEvent = StepEvent
|
||||
|
||||
// WaitHeldEvent is the body of the event wait-held.
|
||||
type WaitHeldEvent = Wait
|
||||
|
||||
// WaitEndedEvent is the body of the event wait-ended.
|
||||
type WaitEndedEvent = Wait
|
||||
|
||||
// PipelinesByBranchRevisionModuleValue is one value of the state pipelines under the key <branch>.<revision>.<module>.
|
||||
type PipelinesByBranchRevisionModuleValue = Pipeline
|
||||
|
||||
// KeptByLevelDigestValue is one value of the state kept under the key <level>.<digest>.
|
||||
type KeptByLevelDigestValue = KeptResult
|
||||
|
||||
// StepLogByPipelineValue is one value of the state step-log under the key <pipeline>.
|
||||
type StepLogByPipelineValue = LogEntry
|
||||
|
||||
// StepOutputsByPipelineStepArtifactValue is one value of the state step-outputs under the key <pipeline>.<step>.<artifact>.
|
||||
type StepOutputsByPipelineStepArtifactValue = string
|
||||
@@ -0,0 +1,90 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
package meshpipelinerunner
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFixtures reads every fixture of seats/mesh-pipeline-runner/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 pipeline started with the steps its policy gives", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-started.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"status\":\"required\",\"step\":\"lint\"},{\"status\":\"bypass\",\"step\":\"review\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"status\":\"required\",\"step\":\"lint\"},{\"status\":\"bypass\",\"step\":\"review\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v PipelineStartedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-started\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a pipeline ended passed, an optional step failed, over budget and widening named", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"tests\":{\"integration\":3,\"unit\":42},\"v\":1,\"widens\":[{\"name\":\"mesh-build-go:program\",\"said\":\"its test runner\",\"what\":\"serving part\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v PipelineEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a pipeline ended failed, naming the step that held it", subject: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"on\":\"the operator\",\"outcome\":\"waiting\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"failed\",\"over-budget\":true,\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"outcome\":\"failed\",\"status\":\"required\",\"step\":\"unit\"},{\"on\":\"the operator\",\"outcome\":\"waiting\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1,\"why\":\"unit of nats:program failed\"}",
|
||||
decode: func(b []byte) (any, error) { var v PipelineEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.pipeline-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a group's one pipeline ended on a watched branch", subject: "mesh.seat.mesh-pipeline-runner.event.group-ended.main.registry-1966", given: "{\"branch\":\"main\",\"ended\":\"2026-11-10T10:20:00Z\",\"group\":\"registry-1966\",\"outcome\":\"passed\",\"pipelines\":[{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"group\":\"registry-1966\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}],\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"branch\":\"main\",\"ended\":\"2026-11-10T10:20:00Z\",\"group\":\"registry-1966\",\"outcome\":\"passed\",\"pipelines\":[{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"group\":\"registry-1966\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}],\"revision\":12,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v GroupEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.group-ended\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a run on request started", subject: "mesh.seat.mesh-pipeline-runner.event.run-started.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"by\":\"fix-1965@shanks\",\"members\":[{\"branch\":\"feature/1966-x\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"module\":\"nats\"}],\"run\":\"run-m2kx9a\",\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"by\":\"fix-1965@shanks\",\"members\":[{\"branch\":\"feature/1966-x\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"module\":\"nats\"}],\"run\":\"run-m2kx9a\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v RunStartedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.run-started\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a step started", subject: "mesh.seat.mesh-pipeline-runner.event.step-started.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"outcome\":\"running\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"outcome\":\"running\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},\"revision\":12,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepStartedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.step-started\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a rerun step ended passed, with its proved caller", subject: "mesh.seat.mesh-pipeline-runner.event.step-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"at\":\"2026-11-10T10:05:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"artifact\":\"nats:program\",\"by\":\"operator@shanks\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"rerun\":true,\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-10T10:05:00Z\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"artifact\":\"nats:program\",\"by\":\"operator@shanks\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"rerun\":true,\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},\"revision\":12,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.step-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a bypassed step said", subject: "mesh.seat.mesh-pipeline-runner.event.step-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},\"revision\":12,\"source\":3589,\"v\":1}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"result\":{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},\"revision\":12,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.step-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "an approval waits on the operator", subject: "mesh.seat.mesh-pipeline-runner.event.wait-held.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}",
|
||||
decode: func(b []byte) (any, error) { var v WaitHeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.wait-held\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "the wait ended answered", subject: "mesh.seat.mesh-pipeline-runner.event.wait-ended.nats.main.0123456789abcdef0123456789abcdef01234567", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"how\":\"answered\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"how\":\"answered\",\"module\":\"nats\",\"on\":\"person\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:10:00Z\",\"source\":3589,\"step\":\"approval\",\"v\":1,\"who\":\"the operator\"}",
|
||||
decode: func(b []byte) (any, error) { var v WaitEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-pipeline-runner\\.event\\.wait-ended\\.[^.*> ]+\\.[^.*> ]+\\.[^.*> ]+$")},
|
||||
{name: "a pipeline kept", subject: "", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:20:00Z\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"started\":\"2026-11-10T10:00:00Z\",\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"},{\"artifact\":\"nats:program\",\"carried-from\":\"main.11.nats\",\"fingerprint\":\"fp-0123\",\"outcome\":\"carried\",\"status\":\"required\",\"step\":\"unit\",\"tests\":{\"unit\":42}},{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"node\":\"g14\",\"outcome\":\"failed\",\"seat\":\"node-build-go\",\"status\":\"optional\",\"step\":\"integration\",\"tests\":{\"integration\":3},\"why\":\"TestTheBusWhole failed\"},{\"outcome\":\"passed\",\"seat\":\"mesh-wants\",\"status\":\"required\",\"step\":\"composition\"},{\"outcome\":\"bypassed\",\"status\":\"bypass\",\"step\":\"review\"},{\"outcome\":\"passed\",\"status\":\"required\",\"step\":\"approval\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v PipelinesByBranchRevisionModuleValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a kept result", subject: "", given: "{\"digest\":\"sha256:aa\",\"level\":\"unit\",\"package\":\"git.novox.be/novox/nats\",\"pipeline\":\"main.12.nats\"}", wire: "{\"digest\":\"sha256:aa\",\"level\":\"unit\",\"package\":\"git.novox.be/novox/nats\",\"pipeline\":\"main.12.nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptByLevelDigestValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "run asks one member at a commit", subject: "", given: "{\"members\":[{\"branch\":\"feature/1966-x\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"module\":\"nats\"}]}", wire: "{\"members\":[{\"branch\":\"feature/1966-x\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"module\":\"nats\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v RunInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "run answers its id and pipelines", subject: "", given: "{\"pipelines\":[\"feature~2f1966-x.0.nats\"],\"run\":\"run-m2kx9a\"}", wire: "{\"pipelines\":[\"feature~2f1966-x.0.nats\"],\"run\":\"run-m2kx9a\"}",
|
||||
decode: func(b []byte) (any, error) { var v RunAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "review of a commit", subject: "", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"said\":\"reads well\"}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"passed\",\"said\":\"reads well\"}",
|
||||
decode: func(b []byte) (any, error) { var v ReviewInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "review answers its step", subject: "", given: "{\"pipeline\":\"main.12.nats\",\"result\":{\"outcome\":\"passed\",\"status\":\"optional\",\"step\":\"review\"}}", wire: "{\"pipeline\":\"main.12.nats\",\"result\":{\"outcome\":\"passed\",\"status\":\"optional\",\"step\":\"review\"}}",
|
||||
decode: func(b []byte) (any, error) { var v ReviewAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "show answers a pipeline with its log and fill", subject: "", given: "{\"fill\":[{\"bytes\":4096,\"cap\":268435456,\"store\":\"pipelines\"}],\"log\":[{\"artifact\":\"nats:program\",\"at\":\"2026-11-10T10:00:00Z\",\"pipeline\":\"main.12.nats\",\"step\":\"lint\",\"what\":\"started\"}],\"outputs\":[\"main.12.nats.lint.nats:program\"],\"pipeline\":{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"running\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}}", wire: "{\"fill\":[{\"bytes\":4096,\"cap\":268435456,\"store\":\"pipelines\"}],\"log\":[{\"artifact\":\"nats:program\",\"at\":\"2026-11-10T10:00:00Z\",\"pipeline\":\"main.12.nats\",\"step\":\"lint\",\"what\":\"started\"}],\"outputs\":[\"main.12.nats.lint.nats:program\"],\"pipeline\":{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"outcome\":\"running\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"steps\":[{\"artifact\":\"nats:program\",\"ask\":\"m2kx9a1b3c4d5e\",\"fingerprint\":\"fp-0123\",\"node\":\"ace\",\"outcome\":\"passed\",\"seat\":\"node-build-go\",\"status\":\"required\",\"step\":\"lint\"}],\"v\":1}}",
|
||||
decode: func(b []byte) (any, error) { var v ShowAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "accept asks with why", subject: "", given: "{\"artifact\":\"nats:program\",\"pipeline\":\"main.12.nats\",\"step\":\"integration\",\"why\":\"flaky upstream, issue 1966\"}", wire: "{\"artifact\":\"nats:program\",\"pipeline\":\"main.12.nats\",\"step\":\"integration\",\"why\":\"flaky upstream, issue 1966\"}",
|
||||
decode: func(b []byte) (any, error) { var v AcceptInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "stands answers a wait on a build node", subject: "", given: "{\"stands\":[{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"on\":\"build node\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:00:00Z\",\"source\":3589,\"step\":\"unit\",\"v\":1}]}", wire: "{\"stands\":[{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fp\":\"fp-0123\",\"module\":\"nats\",\"on\":\"build node\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"since\":\"2026-11-10T10:00:00Z\",\"source\":3589,\"step\":\"unit\",\"v\":1}]}",
|
||||
decode: func(b []byte) (any, error) { var v StandsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept answers by digest", subject: "", given: "{\"fill\":{\"bytes\":300,\"cap\":134217728,\"store\":\"kept\"},\"kept\":[{\"digest\":\"sha256:aa\",\"level\":\"unit\",\"package\":\"git.novox.be/novox/nats\",\"pipeline\":\"main.12.nats\"}]}", wire: "{\"fill\":{\"bytes\":300,\"cap\":134217728,\"store\":\"kept\"},\"kept\":[{\"digest\":\"sha256:aa\",\"level\":\"unit\",\"package\":\"git.novox.be/novox/nats\",\"pipeline\":\"main.12.nats\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v KeptAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
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/meshpipelinerunner
|
||||
|
||||
go 1.26.0
|
||||
@@ -8,28 +8,47 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-wants"
|
||||
|
||||
const (
|
||||
VerbUpgrade = "upgrade"
|
||||
VerbBus = "bus"
|
||||
VerbUpgrade = "upgrade"
|
||||
VerbBus = "bus"
|
||||
VerbRevision = "revision"
|
||||
VerbEntry = "entry"
|
||||
VerbDifference = "difference"
|
||||
VerbInput = "input"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPolicyChanged = "policy-changed"
|
||||
AcceptStep = "step"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPolicyChanged = "policy-changed"
|
||||
EventAssignmentRevision = "assignment-revision"
|
||||
EventDifference = "difference"
|
||||
EventWanted = "wanted"
|
||||
EventWaitHeld = "wait-held"
|
||||
EventWaitEnded = "wait-ended"
|
||||
EventFilling = "filling"
|
||||
EventFull = "full"
|
||||
EventRoom = "room"
|
||||
EventStepEnded = "step-ended"
|
||||
EventVersionDelivered = "version-delivered"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbUpgrade, VerbBus}
|
||||
return []string{VerbUpgrade, VerbBus, VerbRevision, VerbEntry, VerbDifference, VerbInput}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventPolicyChanged}
|
||||
return []string{EventPolicyChanged, EventAssignmentRevision, EventDifference, EventWanted, EventWaitHeld, EventWaitEnded, EventFilling, EventFull, EventRoom, EventStepEnded, EventVersionDelivered}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
@@ -41,10 +60,54 @@ const (
|
||||
// SubjectPolicyChanged is where policy-changed is published.
|
||||
const SubjectPolicyChanged = "mesh.seat.mesh-wants.event.policy-changed"
|
||||
|
||||
// SubjectAssignmentRevision is where assignment-revision is published.
|
||||
const SubjectAssignmentRevision = "mesh.seat.mesh-wants.event.assignment-revision"
|
||||
|
||||
// SubjectDifference is where difference is published.
|
||||
const SubjectDifference = "mesh.seat.mesh-wants.event.difference"
|
||||
|
||||
// SubjectWanted is where wanted is published.
|
||||
const SubjectWanted = "mesh.seat.mesh-wants.event.wanted"
|
||||
|
||||
// SubjectWaitHeld is where wait-held is published.
|
||||
const SubjectWaitHeld = "mesh.seat.mesh-wants.event.wait-held"
|
||||
|
||||
// SubjectWaitEnded is where wait-ended is published.
|
||||
const SubjectWaitEnded = "mesh.seat.mesh-wants.event.wait-ended"
|
||||
|
||||
// SubjectFilling is where filling is published.
|
||||
const SubjectFilling = "mesh.seat.mesh-wants.event.filling"
|
||||
|
||||
// SubjectFull is where full is published.
|
||||
const SubjectFull = "mesh.seat.mesh-wants.event.full"
|
||||
|
||||
// SubjectRoom is where room is published.
|
||||
const SubjectRoom = "mesh.seat.mesh-wants.event.room"
|
||||
|
||||
// StreamStepEnded is the stream step-ended is kept in.
|
||||
const StreamStepEnded = "SEAT_mesh-wants_step-ended"
|
||||
|
||||
// SubjectStepEnded is where step-ended is published, on mesh.seat.mesh-wants.event.step-ended.<node>.
|
||||
func SubjectStepEnded(node string) string { return "mesh.seat.mesh-wants.event.step-ended." + node }
|
||||
|
||||
// SubjectStepEndedAll hears every step-ended.
|
||||
const SubjectStepEndedAll = "mesh.seat.mesh-wants.event.step-ended.*"
|
||||
|
||||
// StreamVersionDelivered is the stream version-delivered is kept in.
|
||||
const StreamVersionDelivered = "SEAT_mesh-wants_version-delivered"
|
||||
|
||||
// SubjectVersionDelivered is where version-delivered is published.
|
||||
const SubjectVersionDelivered = "mesh.seat.mesh-wants.event.version-delivered"
|
||||
|
||||
// AcceptSubjectStep is where step is sent.
|
||||
const AcceptSubjectStep = "mesh.seat.mesh-wants.accept.step"
|
||||
|
||||
const (
|
||||
StateWants = "wants"
|
||||
StateDifferences = "differences"
|
||||
StateCompositions = "compositions"
|
||||
StateWants = "wants"
|
||||
StateDifferences = "differences"
|
||||
StateCompositions = "compositions"
|
||||
StateAssignmentRevisions = "assignment-revisions"
|
||||
StateInputs = "inputs"
|
||||
)
|
||||
|
||||
// WantsByWantNodeModuleKey is the key of one value of the state wants under the form "want.<node>.<module>".
|
||||
@@ -236,6 +299,368 @@ func DecodeCompositionsByGroupHeadsValue(raw []byte) (CompositionsByGroupHeadsVa
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AssignmentRevisionsByTrunkRevisionKey is the key of one value of the state assignment-revisions under the form "trunk.<revision>".
|
||||
func AssignmentRevisionsByTrunkRevisionKey(revision string) string { return "trunk." + revision }
|
||||
|
||||
// ParseAssignmentRevisionsByTrunkRevisionKey reads the parts of a key of the form "trunk.<revision>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAssignmentRevisionsByTrunkRevisionKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "trunk.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[6:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodeAssignmentRevisionsByTrunkRevisionValue reads one value of the state assignment-revisions under the form "trunk.<revision>", refusing a field AssignmentRevisionsByTrunkRevisionValue does not know and any text after the value.
|
||||
func DecodeAssignmentRevisionsByTrunkRevisionValue(raw []byte) (AssignmentRevisionsByTrunkRevisionValue, error) {
|
||||
var v AssignmentRevisionsByTrunkRevisionValue
|
||||
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
|
||||
}
|
||||
|
||||
// AssignmentRevisionsByCandidateGroupHeadsKey is the key of one value of the state assignment-revisions under the form "candidate.<group>.<heads>".
|
||||
func AssignmentRevisionsByCandidateGroupHeadsKey(group, heads string) string {
|
||||
return "candidate." + group + "." + heads
|
||||
}
|
||||
|
||||
// ParseAssignmentRevisionsByCandidateGroupHeadsKey reads the parts of a key of the form "candidate.<group>.<heads>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAssignmentRevisionsByCandidateGroupHeadsKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "candidate.") {
|
||||
return "", "", false
|
||||
}
|
||||
rest = rest[10:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after1
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v3 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v1, v3, true
|
||||
}
|
||||
|
||||
// DecodeAssignmentRevisionsByCandidateGroupHeadsValue reads one value of the state assignment-revisions under the form "candidate.<group>.<heads>", refusing a field AssignmentRevisionsByCandidateGroupHeadsValue does not know and any text after the value.
|
||||
func DecodeAssignmentRevisionsByCandidateGroupHeadsValue(raw []byte) (AssignmentRevisionsByCandidateGroupHeadsValue, error) {
|
||||
var v AssignmentRevisionsByCandidateGroupHeadsValue
|
||||
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
|
||||
}
|
||||
|
||||
// AssignmentRevisionsByEntryDigestKey is the key of one value of the state assignment-revisions under the form "entry.<digest>".
|
||||
func AssignmentRevisionsByEntryDigestKey(digest string) string { return "entry." + digest }
|
||||
|
||||
// ParseAssignmentRevisionsByEntryDigestKey reads the parts of a key of the form "entry.<digest>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAssignmentRevisionsByEntryDigestKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "entry.") {
|
||||
return "", false
|
||||
}
|
||||
rest = rest[6:]
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v1 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v1, true
|
||||
}
|
||||
|
||||
// DecodeAssignmentRevisionsByEntryDigestValue reads one value of the state assignment-revisions under the form "entry.<digest>", refusing a field AssignmentRevisionsByEntryDigestValue does not know and any text after the value.
|
||||
func DecodeAssignmentRevisionsByEntryDigestValue(raw []byte) (AssignmentRevisionsByEntryDigestValue, error) {
|
||||
var v AssignmentRevisionsByEntryDigestValue
|
||||
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
|
||||
}
|
||||
|
||||
// InputsByTimeDigestKey is the key of one value of the state inputs under the form "<time>.<digest>".
|
||||
func InputsByTimeDigestKey(time, digest string) string { return time + "." + digest }
|
||||
|
||||
// ParseInputsByTimeDigestKey reads the parts of a key of the form "<time>.<digest>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseInputsByTimeDigestKey(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
|
||||
}
|
||||
|
||||
// DecodeInputsByTimeDigestValue reads one value of the state inputs under the form "<time>.<digest>", refusing a field InputsByTimeDigestValue does not know and any text after the value.
|
||||
func DecodeInputsByTimeDigestValue(raw []byte) (InputsByTimeDigestValue, error) {
|
||||
var v InputsByTimeDigestValue
|
||||
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
|
||||
}
|
||||
|
||||
// AssignmentEntry is one module version on a node of an assignment graph revision, stored once by its digest (ADR 0656).
|
||||
type AssignmentEntry struct {
|
||||
// the watched branch its placement names, whose catalog graph the entry comes from (design 47 lines 523-525)
|
||||
Branch string `json:"branch"`
|
||||
// the digest of its catalog graph entry
|
||||
Catalog string `json:"catalog"`
|
||||
Edges []Edge `json:"edges,omitempty"`
|
||||
// the fingerprint it is to run
|
||||
Fp string `json:"fp"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// AssignmentRevisionCapabilitiesItem is a type of the contract.
|
||||
type AssignmentRevisionCapabilitiesItem struct {
|
||||
// the digest of the node's capability reading
|
||||
Digest string `json:"digest"`
|
||||
Node string `json:"node"`
|
||||
}
|
||||
|
||||
// AssignmentRevision is an assignment graph revision: the list of its entries' digests and the inputs it was computed from, so it can be computed again and compared.
|
||||
type AssignmentRevision struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Capabilities []AssignmentRevisionCapabilitiesItem `json:"capabilities,omitempty"`
|
||||
// the catalog graph revision of each watched branch a placement names, which the entries come from
|
||||
Catalogs []CatalogOf `json:"catalogs"`
|
||||
// what made it: catalog-revision, placement-changed or capabilities-changed
|
||||
Cause string `json:"cause,omitempty"`
|
||||
Entries []NodeEntryRef `json:"entries"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Heads string `json:"heads,omitempty"`
|
||||
// trunk or candidate
|
||||
Kind string `json:"kind"`
|
||||
// the digest of the placements it was computed from
|
||||
Placements string `json:"placements"`
|
||||
// counted by its holder
|
||||
Revision int64 `json:"revision"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// CatalogOf is one catalog graph revision of a watched branch the revision was computed from (design 47 lines 1416-1418).
|
||||
type CatalogOf struct {
|
||||
// the watched branch
|
||||
Branch string `json:"branch"`
|
||||
// that branch's catalog graph revision
|
||||
Revision int64 `json:"revision"`
|
||||
// the source revision of that branch it carries
|
||||
Source int64 `json:"source,omitempty"`
|
||||
}
|
||||
|
||||
// Change is one module on a node whose version differs between two revisions.
|
||||
type Change struct {
|
||||
// the edges that moved
|
||||
Edges []Edge `json:"edges,omitempty"`
|
||||
// the fingerprint before; absent when it is new there
|
||||
From string `json:"from,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
// the fingerprint after; absent when it goes
|
||||
To string `json:"to,omitempty"`
|
||||
}
|
||||
|
||||
// DifferenceRefusedItem is a type of the contract.
|
||||
type DifferenceRefusedItem struct {
|
||||
Module string `json:"module"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// Difference is two assignment graph revisions compared: a change's delivery, with its order read off the edges and no plan stored (ADR 0656).
|
||||
type Difference struct {
|
||||
Changes []Change `json:"changes"`
|
||||
// the revision compared from
|
||||
From int64 `json:"from"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Heads string `json:"heads,omitempty"`
|
||||
// the nodes it touches
|
||||
Nodes []string `json:"nodes,omitempty"`
|
||||
// a module whose fingerprint changed while the difference is empty, refused by name
|
||||
Refused []DifferenceRefusedItem `json:"refused,omitempty"`
|
||||
// the order as a view: each tier the changes whose acting parts acted in the tiers before it (ADR 0603 §6 as ADR 0656 changes it)
|
||||
Tiers [][]NodeEntryRef `json:"tiers,omitempty"`
|
||||
// the revision compared to
|
||||
To int64 `json:"to"`
|
||||
}
|
||||
|
||||
// Edge is an edge from one module version on a node to another: provisioning, contribution, or an acting part's version that is to act on it in a step (ADR 0656).
|
||||
type Edge struct {
|
||||
// for acting, how long the new version may take before it acts
|
||||
Bound string `json:"bound,omitempty"`
|
||||
// the other end's fingerprint
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// provisioning, contribution or acting
|
||||
Kind string `json:"kind"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
// for provisioning, the provision
|
||||
Provision string `json:"provision,omitempty"`
|
||||
// for contribution, the seat it contributes to; for acting, the seat whose rule gave the edge
|
||||
Seat string `json:"seat,omitempty"`
|
||||
// for acting, the step: take-in, validate, check, build, compose, grant or place
|
||||
Step string `json:"step,omitempty"`
|
||||
}
|
||||
|
||||
// Fill is a store's fill against its cap.
|
||||
type Fill struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Bytes int64 `json:"bytes"`
|
||||
// bytes
|
||||
Cap int64 `json:"cap"`
|
||||
// what full refuses
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// the kept data, by its name in the holder's manifest
|
||||
Store string `json:"store"`
|
||||
}
|
||||
|
||||
// NodeEntryRef is a type of the contract.
|
||||
type NodeEntryRef struct {
|
||||
// the entry's digest, its object's name
|
||||
Digest string `json:"digest"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
}
|
||||
|
||||
// StepEnded is the composition step's end, said by the assigner on the node it runs on (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at.
|
||||
type StepEnded struct {
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
Module string `json:"module"`
|
||||
// the node the assigner ran it on, as in the subject
|
||||
Node string `json:"node"`
|
||||
// never passed for a step that composed nothing
|
||||
Outcome string `json:"outcome"`
|
||||
Pipeline string `json:"pipeline"`
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// why it failed or could not run: the two modules owning one path, the part not heard
|
||||
Said string `json:"said,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
Step string `json:"step"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
// a node asleep, passed with a warning (ADR 0593 section 9)
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepEnded's outcome.
|
||||
const (
|
||||
StepEndedOutcomePassed = "passed"
|
||||
StepEndedOutcomeFailed = "failed"
|
||||
StepEndedOutcomeNothingToRun = "nothing to run"
|
||||
StepEndedOutcomeCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// The values of StepEnded's step.
|
||||
const (
|
||||
StepEndedStepComposition = "composition"
|
||||
)
|
||||
|
||||
// StepRun is the composition step of one module's pipeline (design 47 *Pipeline steps and the policy*, *The pipeline makes the check*): the assigner composes each machine's declaration at the change's heads with the composer built from them, in the build seat's sandbox, and refuses a change in which two modules own one path.
|
||||
type StepRun struct {
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the commit the step runs at
|
||||
Commit string `json:"commit"`
|
||||
// the module's build-input fingerprint at the commit
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Module string `json:"module"`
|
||||
// the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the step is asked again by the runner's rerun
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// the catalog graph revision of the branch the pipeline runs for
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the run on request's id: its composition writes no want (ADR 0666 section 18)
|
||||
Run string `json:"run,omitempty"`
|
||||
// the source revision of the watched branch; absent for a run on request
|
||||
Source int64 `json:"source,omitempty"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of StepRun's step.
|
||||
const (
|
||||
StepRunStepComposition = "composition"
|
||||
)
|
||||
|
||||
// Wait is a step's wait the assigner holds: placing, wanting or composing until an acting part's new version runs.
|
||||
type Wait struct {
|
||||
// a duration such as 30m
|
||||
Bound string `json:"bound,omitempty"`
|
||||
// on a release, who released it and why
|
||||
By string `json:"by,omitempty"`
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// on wait-ended: ran or released
|
||||
How string `json:"how,omitempty"`
|
||||
// the entry that waits
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node,omitempty"`
|
||||
// the acting part waited for
|
||||
Part string `json:"part"`
|
||||
Since time.Time `json:"since"`
|
||||
Step string `json:"step"`
|
||||
// its new version's fingerprint
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// UpgradeInput is what upgrade takes.
|
||||
type UpgradeInput struct {
|
||||
// "true": each node's own composition, by its digest, and the assigner's findings
|
||||
@@ -264,9 +689,140 @@ type BusInput struct {
|
||||
// BusAnswer is what bus answers.
|
||||
type BusAnswer = map[string]any
|
||||
|
||||
// RevisionInput is what revision takes.
|
||||
type RevisionInput struct {
|
||||
// a candidate's group
|
||||
Group string `json:"group,omitempty"`
|
||||
// a candidate's heads
|
||||
Heads string `json:"heads,omitempty"`
|
||||
// a kept revision; absent: the newest of trunk, or of the candidate named
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
}
|
||||
|
||||
// RevisionAnswer is what revision answers.
|
||||
type RevisionAnswer struct {
|
||||
Revision AssignmentRevision `json:"revision"`
|
||||
}
|
||||
|
||||
// EntryInput is what entry takes.
|
||||
type EntryInput struct {
|
||||
Digest string `json:"digest,omitempty"`
|
||||
// a candidate's group
|
||||
Group string `json:"group,omitempty"`
|
||||
// a candidate's heads
|
||||
Heads string `json:"heads,omitempty"`
|
||||
Module string `json:"module,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
// a kept revision; absent: the newest of trunk, or of the candidate named
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
}
|
||||
|
||||
// EntryAnswer is what entry answers.
|
||||
type EntryAnswer struct {
|
||||
Digest string `json:"digest"`
|
||||
Entry AssignmentEntry `json:"entry"`
|
||||
}
|
||||
|
||||
// DifferenceInput is what difference takes.
|
||||
type DifferenceInput struct {
|
||||
From int64 `json:"from,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Heads string `json:"heads,omitempty"`
|
||||
To int64 `json:"to,omitempty"`
|
||||
}
|
||||
|
||||
// DifferenceAnswer is what difference answers.
|
||||
type DifferenceAnswer = Difference
|
||||
|
||||
// InputInput is what input takes.
|
||||
type InputInput struct {
|
||||
// the input's sha256
|
||||
Digest string `json:"digest"`
|
||||
}
|
||||
|
||||
// InputAnswer is what input answers.
|
||||
type InputAnswer struct {
|
||||
// the input's sha256
|
||||
Digest string `json:"digest"`
|
||||
// the input's exact bytes, base64
|
||||
Input string `json:"input"`
|
||||
}
|
||||
|
||||
// StepAccept is the body of step.
|
||||
type StepAccept = StepRun
|
||||
|
||||
// PolicyChangedEvent is the body of the event policy-changed.
|
||||
type PolicyChangedEvent = map[string]any
|
||||
|
||||
// AssignmentRevisionEvent is the body of the event assignment-revision.
|
||||
type AssignmentRevisionEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the catalog graph revision of each watched branch a placement names, which the entries come from
|
||||
Catalogs []CatalogOf `json:"catalogs"`
|
||||
Cause string `json:"cause,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Heads string `json:"heads,omitempty"`
|
||||
Kind string `json:"kind"`
|
||||
Revision int64 `json:"revision"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// DifferenceEvent is the body of the event difference.
|
||||
type DifferenceEvent struct {
|
||||
// how many module versions it changes
|
||||
Changes int64 `json:"changes,omitempty"`
|
||||
From int64 `json:"from"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Heads string `json:"heads,omitempty"`
|
||||
Nodes []string `json:"nodes,omitempty"`
|
||||
Source int64 `json:"source,omitempty"`
|
||||
To int64 `json:"to"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// WantedEvent is the body of the event wanted.
|
||||
type WantedEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Fp string `json:"fp"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
Revision int64 `json:"revision"`
|
||||
Source int64 `json:"source,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// WaitHeldEvent is the body of the event wait-held.
|
||||
type WaitHeldEvent = Wait
|
||||
|
||||
// WaitEndedEvent is the body of the event wait-ended.
|
||||
type WaitEndedEvent = Wait
|
||||
|
||||
// FillingEvent is the body of the event filling.
|
||||
type FillingEvent = Fill
|
||||
|
||||
// FullEvent is the body of the event full.
|
||||
type FullEvent = Fill
|
||||
|
||||
// RoomEvent is the body of the event room.
|
||||
type RoomEvent = Fill
|
||||
|
||||
// StepEndedEvent is the body of the event step-ended.
|
||||
type StepEndedEvent = StepEnded
|
||||
|
||||
// VersionDeliveredEvent is the body of the event version-delivered.
|
||||
type VersionDeliveredEvent struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
// the machines away when it was said
|
||||
Away []string `json:"away,omitempty"`
|
||||
// the module
|
||||
Module string `json:"module"`
|
||||
// the digest of each of its parts, by artifact reference
|
||||
Parts map[string]string `json:"parts"`
|
||||
V int64 `json:"v"`
|
||||
// MAJOR.MINOR.PATCH
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// WantsByWantNodeModuleValue is one value of the state wants under the key want.<node>.<module>.
|
||||
type WantsByWantNodeModuleValue struct {
|
||||
// again or skip
|
||||
@@ -275,15 +831,19 @@ type WantsByWantNodeModuleValue struct {
|
||||
Fp string `json:"fp,omitempty"`
|
||||
Hold bool `json:"hold,omitempty"`
|
||||
Newest string `json:"newest,omitempty"`
|
||||
Put bool `json:"put,omitempty"`
|
||||
Release string `json:"release,omitempty"`
|
||||
Removed bool `json:"removed,omitempty"`
|
||||
// the digest of each of the module's parts, by artifact reference; the node-engine fetches and checks each part by it (design 47 G section 379)
|
||||
Parts map[string]string `json:"parts,omitempty"`
|
||||
Put bool `json:"put,omitempty"`
|
||||
Release string `json:"release,omitempty"`
|
||||
Removed bool `json:"removed,omitempty"`
|
||||
// the rule that holds the node back, 1 to 10
|
||||
Rule int64 `json:"rule,omitempty"`
|
||||
Self bool `json:"self,omitempty"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
Words string `json:"words,omitempty"`
|
||||
Yes string `json:"yes,omitempty"`
|
||||
Rule int64 `json:"rule,omitempty"`
|
||||
Self bool `json:"self,omitempty"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
// the module's released version, for people; none for a build of another watched branch (design 47 G section 379)
|
||||
Version string `json:"version,omitempty"`
|
||||
Words string `json:"words,omitempty"`
|
||||
Yes string `json:"yes,omitempty"`
|
||||
}
|
||||
|
||||
// The values of WantsByWantNodeModuleValue's backup.
|
||||
@@ -335,3 +895,15 @@ type CompositionsByGroupHeadsValue struct {
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// AssignmentRevisionsByTrunkRevisionValue is one value of the state assignment-revisions under the key trunk.<revision>.
|
||||
type AssignmentRevisionsByTrunkRevisionValue = AssignmentRevision
|
||||
|
||||
// AssignmentRevisionsByCandidateGroupHeadsValue is one value of the state assignment-revisions under the key candidate.<group>.<heads>.
|
||||
type AssignmentRevisionsByCandidateGroupHeadsValue = AssignmentRevision
|
||||
|
||||
// AssignmentRevisionsByEntryDigestValue is one value of the state assignment-revisions under the key entry.<digest>.
|
||||
type AssignmentRevisionsByEntryDigestValue = AssignmentEntry
|
||||
|
||||
// InputsByTimeDigestValue is one value of the state inputs under the key <time>.<digest>.
|
||||
type InputsByTimeDigestValue = string
|
||||
|
||||
@@ -17,6 +17,32 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "an assignment graph revision kept", subject: "mesh.seat.mesh-wants.event.assignment-revision", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"placement-changed\",\"kind\":\"trunk\",\"revision\":40,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"placement-changed\",\"kind\":\"trunk\",\"revision\":40,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AssignmentRevisionEvent
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.assignment-revision$")},
|
||||
{name: "a difference worked out", subject: "mesh.seat.mesh-wants.event.difference", given: "{\"changes\":1,\"from\":40,\"nodes\":[\"n1\"],\"source\":3589,\"to\":41,\"v\":1}", wire: "{\"changes\":1,\"from\":40,\"nodes\":[\"n1\"],\"source\":3589,\"to\":41,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v DifferenceEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.difference$")},
|
||||
{name: "an entry wanted from a trunk revision", subject: "mesh.seat.mesh-wants.event.wanted", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40,\"source\":3589,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v WantedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wanted$")},
|
||||
{name: "a composing wait held with its bound", subject: "mesh.seat.mesh-wants.event.wait-held", given: "{\"bound\":\"30m\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", wire: "{\"bound\":\"30m\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}",
|
||||
decode: func(b []byte) (any, error) { var v WaitHeldEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wait-held$")},
|
||||
{name: "a wait ended, released by hand", subject: "mesh.seat.mesh-wants.event.wait-ended", given: "{\"bound\":\"30m\",\"by\":\"lead@shanks: the node is away\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"how\":\"released\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}", wire: "{\"bound\":\"30m\",\"by\":\"lead@shanks: the node is away\",\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"how\":\"released\",\"module\":\"xclip\",\"node\":\"n1\",\"part\":\"node-engine\",\"since\":\"2026-11-09T19:00:00Z\",\"step\":\"compose\",\"version\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}",
|
||||
decode: func(b []byte) (any, error) { var v WaitEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.wait-ended$")},
|
||||
{name: "the store past 80 % of its cap", subject: "mesh.seat.mesh-wants.event.filling", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":450000000,\"cap\":536870912,\"store\":\"assignment-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":450000000,\"cap\":536870912,\"store\":\"assignment-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v FillingEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.filling$")},
|
||||
{name: "the store full, keeping its last revision", subject: "mesh.seat.mesh-wants.event.full", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":536870912,\"cap\":536870912,\"refused\":\"the next revision; no new want is written\",\"store\":\"assignment-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":536870912,\"cap\":536870912,\"refused\":\"the next revision; no new want is written\",\"store\":\"assignment-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v FullEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.full$")},
|
||||
{name: "the store back below its cap", subject: "mesh.seat.mesh-wants.event.room", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":300000000,\"cap\":536870912,\"store\":\"assignment-revisions\"}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"bytes\":300000000,\"cap\":536870912,\"store\":\"assignment-revisions\"}",
|
||||
decode: func(b []byte) (any, error) { var v RoomEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.room$")},
|
||||
{name: "the composition step ended passed on the assigner's node, a node asleep warned", subject: "mesh.seat.mesh-wants.event.step-ended.novox", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:01:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d6a\",\"module\":\"nats\",\"node\":\"novox\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"composition\",\"v\":1,\"warnings\":[\"g14 asleep: composed from its last capabilities\"]}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:01:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d6a\",\"module\":\"nats\",\"node\":\"novox\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"composition\",\"v\":1,\"warnings\":[\"g14 asleep: composed from its last capabilities\"]}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{name: "the composition step failed, two modules owning one path", subject: "mesh.seat.mesh-wants.event.step-ended.novox", given: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d6b\",\"module\":\"nats\",\"node\":\"novox\",\"outcome\":\"failed\",\"pipeline\":\"main.12.nats\",\"said\":\"nats and xclip both own /etc/nats.conf on ace\",\"step\":\"composition\",\"v\":1}", wire: "{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d6b\",\"module\":\"nats\",\"node\":\"novox\",\"outcome\":\"failed\",\"pipeline\":\"main.12.nats\",\"said\":\"nats and xclip both own /etc/nats.conf on ace\",\"step\":\"composition\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{name: "a version delivered with the machines away", subject: "mesh.seat.mesh-wants.event.version-delivered", given: "{\"away\":[\"laptop\"],\"module\":\"mesh-sdk\",\"parts\":{\"mesh-sdk:go\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},\"v\":1,\"version\":\"0.1.15\"}", wire: "{\"away\":[\"laptop\"],\"module\":\"mesh-sdk\",\"parts\":{\"mesh-sdk:go\":\"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"},\"v\":1,\"version\":\"0.1.15\"}",
|
||||
decode: func(b []byte) (any, error) { var v VersionDeliveredEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.event\\.version-delivered$")},
|
||||
{name: "a want", subject: "", given: "{\"fp\":\"ab12\",\"rule\":3,\"v\":1}", wire: "{\"fp\":\"ab12\",\"rule\":3,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v WantsByWantNodeModuleValue
|
||||
@@ -47,6 +73,46 @@ func TestFixtures(t *testing.T) {
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a trunk assignment graph revision naming its inputs", subject: "", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"kind\":\"trunk\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":40,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"kind\":\"trunk\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":40,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AssignmentRevisionsByTrunkRevisionValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "a candidate's assignment graph revision", subject: "", given: "{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":13,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":41,\"v\":1}", wire: "{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":13,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"kind\":\"candidate\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":41,\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AssignmentRevisionsByCandidateGroupHeadsValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "an assignment entry with an acting edge and a provisioning edge", subject: "", given: "{\"branch\":\"main\",\"catalog\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"edges\":[{\"bound\":\"30m\",\"fp\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\",\"kind\":\"acting\",\"module\":\"node-engine\",\"node\":\"n1\",\"seat\":\"node-engine\",\"step\":\"compose\"},{\"kind\":\"provisioning\",\"module\":\"postgres\",\"node\":\"n2\",\"provision\":\"database\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"v\":1}", wire: "{\"branch\":\"main\",\"catalog\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"edges\":[{\"bound\":\"30m\",\"fp\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\",\"kind\":\"acting\",\"module\":\"node-engine\",\"node\":\"n1\",\"seat\":\"node-engine\",\"step\":\"compose\"},{\"kind\":\"provisioning\",\"module\":\"postgres\",\"node\":\"n2\",\"provision\":\"database\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v AssignmentRevisionsByEntryDigestValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "revision asks the trunk's newest", subject: "", given: "{}", wire: "{}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision asks a candidate's", subject: "", given: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}", wire: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "revision answers one revision naming its inputs", subject: "", given: "{\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"kind\":\"trunk\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":40,\"v\":1}}", wire: "{\"revision\":{\"at\":\"2026-11-09T19:00:00Z\",\"capabilities\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"node\":\"n1\"}],\"catalogs\":[{\"branch\":\"main\",\"revision\":12,\"source\":3589}],\"cause\":\"catalog-revision\",\"entries\":[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}],\"kind\":\"trunk\",\"placements\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"revision\":40,\"v\":1}}",
|
||||
decode: func(b []byte) (any, error) { var v RevisionAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "entry asks by node and module in a revision", subject: "", given: "{\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40}", wire: "{\"module\":\"xclip\",\"node\":\"n1\",\"revision\":40}",
|
||||
decode: func(b []byte) (any, error) { var v EntryInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "entry answers the entry with its edges", subject: "", given: "{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"entry\":{\"branch\":\"main\",\"catalog\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"edges\":[{\"bound\":\"30m\",\"fp\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\",\"kind\":\"acting\",\"module\":\"node-engine\",\"node\":\"n1\",\"seat\":\"node-engine\",\"step\":\"compose\"},{\"kind\":\"provisioning\",\"module\":\"postgres\",\"node\":\"n2\",\"provision\":\"database\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"v\":1}}", wire: "{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"entry\":{\"branch\":\"main\",\"catalog\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"edges\":[{\"bound\":\"30m\",\"fp\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\",\"kind\":\"acting\",\"module\":\"node-engine\",\"node\":\"n1\",\"seat\":\"node-engine\",\"step\":\"compose\"},{\"kind\":\"provisioning\",\"module\":\"postgres\",\"node\":\"n2\",\"provision\":\"database\"}],\"fp\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"v\":1}}",
|
||||
decode: func(b []byte) (any, error) { var v EntryAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "difference asks a candidate's against trunk", subject: "", given: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}", wire: "{\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\"}",
|
||||
decode: func(b []byte) (any, error) { var v DifferenceInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "difference answers the changes and their order", subject: "", given: "{\"changes\":[{\"from\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"to\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}],\"from\":40,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"nodes\":[\"n1\"],\"tiers\":[[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}]],\"to\":41}", wire: "{\"changes\":[{\"from\":\"src2:b427bdde1f100e2f52490cfa9df0c5112dd3700226b4892349f0c14a15a4af56\",\"module\":\"xclip\",\"node\":\"n1\",\"to\":\"src2:7dd0db8e98224f46121a5ae05c0b9c5a430eff531a5120aa40b1a59237853a3f\"}],\"from\":40,\"group\":\"feat/47-G\",\"heads\":\"0123456789ab\",\"nodes\":[\"n1\"],\"tiers\":[[{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"module\":\"xclip\",\"node\":\"n1\"}]],\"to\":41}",
|
||||
decode: func(b []byte) (any, error) { var v DifferenceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "difference refuses a changed fingerprint with no difference, by name", subject: "", given: "{\"changes\":[],\"from\":40,\"refused\":[{\"module\":\"xclip\",\"why\":\"its fingerprint changed and its difference is empty\"}],\"to\":41}", wire: "{\"changes\":[],\"from\":40,\"refused\":[{\"module\":\"xclip\",\"why\":\"its fingerprint changed and its difference is empty\"}],\"to\":41}",
|
||||
decode: func(b []byte) (any, error) { var v DifferenceAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a composition step asked by the runner", subject: "mesh.seat.mesh-wants.accept.step", given: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"step\":\"composition\"}", wire: "{\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"pipeline\":\"main.12.nats\",\"revision\":12,\"source\":3589,\"step\":\"composition\"}",
|
||||
decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.mesh-wants\\.accept\\.step$")},
|
||||
{name: "input asks a composition step's input by digest", subject: "", given: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}", wire: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\"}",
|
||||
decode: func(b []byte) (any, error) { var v InputInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "input answers the exact bytes", subject: "", given: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"input\":\"eyJ2IjoxfQ==\"}", wire: "{\"digest\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"input\":\"eyJ2IjoxfQ==\"}",
|
||||
decode: func(b []byte) (any, error) { var v InputAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -15,36 +15,71 @@ import (
|
||||
const Seat = "node-build-go"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbKeptArtifact = "kept-artifact"
|
||||
VerbSteps = "steps"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptStep = "step"
|
||||
AcceptRecheck = "recheck"
|
||||
AcceptRun = "run"
|
||||
)
|
||||
|
||||
const (
|
||||
EventStepEnded = "step-ended"
|
||||
)
|
||||
|
||||
// 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, VerbDrop}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop, VerbKeptArtifact, VerbSteps}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventStepEnded}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "node-build-go.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamStepEnded is the stream step-ended is kept in.
|
||||
const StreamStepEnded = "SEAT_node-build-go_step-ended"
|
||||
|
||||
// SubjectStepEnded is where step-ended is published, on mesh.seat.node-build-go.event.step-ended.<node>.
|
||||
func SubjectStepEnded(node string) string { return "mesh.seat.node-build-go.event.step-ended." + node }
|
||||
|
||||
// SubjectStepEndedAll hears every step-ended.
|
||||
const SubjectStepEndedAll = "mesh.seat.node-build-go.event.step-ended.*"
|
||||
|
||||
// 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"
|
||||
|
||||
// AcceptSubjectStep is where step is sent.
|
||||
const AcceptSubjectStep = "mesh.seat.node-build-go.accept.step"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-go.accept.recheck"
|
||||
|
||||
// AcceptSubjectRun is where run is sent.
|
||||
const AcceptSubjectRun = "mesh.seat.node-build-go.accept.run"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateDetectedSteps = "detected-steps"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
@@ -224,6 +259,42 @@ func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageVa
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DetectedStepsByModuleArtifactKey is the key of one value of the state detected-steps under the form "<module>.<artifact>".
|
||||
func DetectedStepsByModuleArtifactKey(module, artifact string) string { return module + "." + artifact }
|
||||
|
||||
// ParseDetectedStepsByModuleArtifactKey reads the parts of a key of the form "<module>.<artifact>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseDetectedStepsByModuleArtifactKey(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
|
||||
}
|
||||
|
||||
// DecodeDetectedStepsByModuleArtifactValue reads one value of the state detected-steps under the form "<module>.<artifact>", refusing a field DetectedStepsByModuleArtifactValue does not know and any text after the value.
|
||||
func DecodeDetectedStepsByModuleArtifactValue(raw []byte) (DetectedStepsByModuleArtifactValue, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
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
|
||||
}
|
||||
|
||||
// AskArtifact is one artifact of a build ask: built from the fetched tree, or copied from an upstream pin.
|
||||
type AskArtifact struct {
|
||||
Artifact string `json:"artifact"`
|
||||
@@ -236,8 +307,10 @@ type AskArtifact struct {
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// BuiltArtifact is one artifact a build made: its digest and the reference it was published under.
|
||||
@@ -281,6 +354,28 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// DetectedStep is a type of the contract.
|
||||
type DetectedStep struct {
|
||||
// the packages the step runs, by the language's convention
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of DetectedStep's step.
|
||||
const (
|
||||
DetectedStepStepLint = "lint"
|
||||
DetectedStepStepUnit = "unit"
|
||||
DetectedStepStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// DetectedSteps is the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326).
|
||||
type DetectedSteps struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -352,6 +447,18 @@ type FetchRefusal struct {
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// KeptResult is a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names.
|
||||
type KeptResult struct {
|
||||
// sha256:<hex> of what the package's tests read
|
||||
Digest string `json:"digest"`
|
||||
// unit or integration
|
||||
Level string `json:"level"`
|
||||
Package string `json:"package"`
|
||||
// the pipeline whose step kept it
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// LevelAnswerDigestNeedsItem is a type of the contract.
|
||||
type LevelAnswerDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
@@ -550,7 +657,7 @@ type StepAsk struct {
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
// build, check, compose or step
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
@@ -559,11 +666,72 @@ type StepAsk struct {
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose
|
||||
Run *RunJob `json:"run,omitempty"`
|
||||
// a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*)
|
||||
Step *StepRun `json:"step,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
// StepEnded is a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at.
|
||||
type StepEnded struct {
|
||||
Artifact string `json:"artifact"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the packages not run because the ask's kept results held them
|
||||
Carried []KeptResult `json:"carried,omitempty"`
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// the packages that passed at their digest, for the runner to keep
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// the node that ran it, as in the subject
|
||||
Node string `json:"node"`
|
||||
// never passed for a step that ran nothing
|
||||
Outcome string `json:"outcome"`
|
||||
// the step's output when it fits the message
|
||||
Output string `json:"output,omitempty"`
|
||||
// the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16)
|
||||
OutputObject string `json:"output-object,omitempty"`
|
||||
Pipeline string `json:"pipeline"`
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// why it failed or could not run, naming the part not heard
|
||||
Said string `json:"said,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
Step string `json:"step"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepEnded's outcome.
|
||||
const (
|
||||
StepEndedOutcomePassed = "passed"
|
||||
StepEndedOutcomeFailed = "failed"
|
||||
StepEndedOutcomeNothingToRun = "nothing to run"
|
||||
StepEndedOutcomeCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// The values of StepEnded's step.
|
||||
const (
|
||||
StepEndedStepLint = "lint"
|
||||
StepEndedStepUnit = "unit"
|
||||
StepEndedStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// StepNames is the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part.
|
||||
type StepNames struct {
|
||||
// every watched branch a registration names
|
||||
Branches []string `json:"branches"`
|
||||
// every module the registrations name
|
||||
Modules []string `json:"modules"`
|
||||
// every repository a registration's git origin names, as <owner>/<name>
|
||||
Repositories []string `json:"repositories"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
type StepResult struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts,omitempty"`
|
||||
Built bool `json:"built,omitempty"`
|
||||
@@ -573,7 +741,9 @@ type StepResult struct {
|
||||
Exit int64 `json:"exit,omitempty"`
|
||||
Fetch *FetchAnswer `json:"fetch,omitempty"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// what the holder's node lacks of it
|
||||
Lacks []string `json:"lacks,omitempty"`
|
||||
Levels []LevelAnswer `json:"levels,omitempty"`
|
||||
@@ -589,6 +759,42 @@ type StepResult struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// StepRun is one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip.
|
||||
type StepRun struct {
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the commit the step runs at
|
||||
Commit string `json:"commit"`
|
||||
// where the step reads the change's heads
|
||||
Fetch Fetch `json:"fetch"`
|
||||
// the artifact's build-input fingerprint at the commit
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*)
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Names StepNames `json:"names"`
|
||||
// the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the step is asked again by the runner's rerun
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// the source revision of the watched branch the pipeline runs for; absent for a run on request
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the pipeline step
|
||||
Step string `json:"step"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepRun's step.
|
||||
const (
|
||||
StepRunStepLint = "lint"
|
||||
StepRunStepUnit = "unit"
|
||||
StepRunStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// TakenVersion is of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said.
|
||||
type TakenVersion struct {
|
||||
Asked string `json:"asked"`
|
||||
@@ -600,6 +806,12 @@ type TakenVersion struct {
|
||||
Sum string `json:"sum,omitempty"`
|
||||
}
|
||||
|
||||
// TestCounts is how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget).
|
||||
type TestCounts struct {
|
||||
Integration int64 `json:"integration,omitempty"`
|
||||
Unit int64 `json:"unit,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -653,15 +865,83 @@ type DropInput struct {
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// KeptArtifactInput is what kept-artifact takes.
|
||||
type KeptArtifactInput struct {
|
||||
// the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it
|
||||
Digest string `json:"digest"`
|
||||
// its build's fingerprint
|
||||
Fp string `json:"fp"`
|
||||
// the module, the holder of oci-artifact-registry
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// KeptArtifactAnswer is what kept-artifact answers.
|
||||
type KeptArtifactAnswer struct {
|
||||
// the digest of the bytes kept
|
||||
Digest string `json:"digest,omitempty"`
|
||||
// why it could not answer
|
||||
Error string `json:"error,omitempty"`
|
||||
// the fingerprint asked
|
||||
Fp string `json:"fp"`
|
||||
// the module asked
|
||||
Module string `json:"module"`
|
||||
// the object's name in it: the digest
|
||||
Object string `json:"object,omitempty"`
|
||||
// why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// bytes
|
||||
Size int64 `json:"size,omitempty"`
|
||||
// the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus
|
||||
Store string `json:"store,omitempty"`
|
||||
// the refusal in words, naming the module
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// The values of KeptArtifactAnswer's refused.
|
||||
const (
|
||||
KeptArtifactAnswerRefusedClaimsNoOciArtifactRegistry = "claims no oci-artifact-registry"
|
||||
KeptArtifactAnswerRefusedNotKept = "not kept"
|
||||
KeptArtifactAnswerRefusedDigestDiffers = "digest differs"
|
||||
)
|
||||
|
||||
// StepsInput is what steps takes.
|
||||
type StepsInput struct {
|
||||
// find them anew, not from the kept answer
|
||||
Again bool `json:"again,omitempty"`
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
Fetch Fetch `json:"fetch"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// StepsAnswer is what steps answers.
|
||||
type StepsAnswer struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
// answered from the kept answer
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
}
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// StepAccept is the body of step.
|
||||
type StepAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// RunAccept is the body of run.
|
||||
type RunAccept = StepAsk
|
||||
|
||||
// StepEndedEvent is the body of the event step-ended.
|
||||
type StepEndedEvent = StepEnded
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
@@ -676,3 +956,6 @@ type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
|
||||
// DetectedStepsByModuleArtifactValue is one value of the state detected-steps under the key <module>.<artifact>.
|
||||
type DetectedStepsByModuleArtifactValue = DetectedSteps
|
||||
|
||||
@@ -17,6 +17,10 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a unit step ended passed on its node, with its counts and what it carried", subject: "mesh.seat.node-build-go.event.step-ended.ace", given: "{\"artifact\":\"nats:program\",\"carried\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\"}],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"kept\":[{\"digest\":\"sha256:cccc\",\"level\":\"unit\",\"package\":\"./modules/nats/b\"}],\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"unit\",\"tests\":{\"unit\":14},\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"carried\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\"}],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"kept\":[{\"digest\":\"sha256:cccc\",\"level\":\"unit\",\"package\":\"./modules/nats/b\"}],\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"unit\",\"tests\":{\"unit\":14},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{name: "an integration step that could not run, naming the part not heard", subject: "mesh.seat.node-build-go.event.step-ended.g14", given: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"integration\",\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"integration\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{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}",
|
||||
@@ -43,6 +47,8 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v CheckAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.check$")},
|
||||
{name: "a finished build step with its artifacts", subject: "", given: "{\"ended\":\"2026-11-05T10:03:00Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"result\":{\"artifacts\":[{\"artifact\":\"go\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"reference\":\"container-image-registry/nats/go@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}],\"imports\":[\"git.novox.be/novox/mesh-sdk/go\"],\"toolchain\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"build\",\"v\":1}", wire: "{\"ended\":\"2026-11-05T10:03:00Z\",\"id\":\"a1b2\",\"node\":\"ace\",\"result\":{\"artifacts\":[{\"artifact\":\"go\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"reference\":\"container-image-registry/nats/go@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}],\"imports\":[\"git.novox.be/novox/mesh-sdk/go\"],\"toolchain\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"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 finished build step that kept its artifact on its node", subject: "", given: "{\"ended\":\"2026-11-05T10:03:00Z\",\"id\":\"a1b3\",\"node\":\"ace\",\"result\":{\"artifacts\":[{\"artifact\":\"go\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"reference\":\"container-image-registry/nats/go@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}],\"imports\":[\"git.novox.be/novox/mesh-sdk/go\"],\"kept\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"toolchain\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"build\",\"v\":1}", wire: "{\"ended\":\"2026-11-05T10:03:00Z\",\"id\":\"a1b3\",\"node\":\"ace\",\"result\":{\"artifacts\":[{\"artifact\":\"go\",\"digest\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"reference\":\"container-image-registry/nats/go@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}],\"imports\":[\"git.novox.be/novox/mesh-sdk/go\"],\"kept\":\"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"toolchain\":{\"language\":\"go\",\"recipe\":\"1\",\"version\":\"1.26.0\"}},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"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 finished check step with its levels", subject: "", given: "{\"ended\":\"2026-11-05T10:06:00Z\",\"id\":\"c3d4\",\"node\":\"ace\",\"result\":{\"fetch\":{\"base\":\"abcdef0123456789abcdef0123456789abcdef01\",\"changed\":[\"a.go\",\"modules/m/main.go\"],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"merge\":\"fedcba9876543210fedcba9876543210fedcba98\",\"modules\":[\".\"],\"trees\":{\"modules/m\":{\"locks\":{\"go.sum\":\"c5fc83c01e92404452b986527d239140ccf9a48b88e0c268fbf38c2e1429e9c9\"},\"manifest\":\"ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356\",\"tree\":\"1111111111111111111111111111111111111111\"}},\"workspace\":\"mvii1iwu5414e4\"},\"levels\":[{\"digest\":{\"level\":\"unit\",\"packages\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"package\":\"./modules/a\"}]},\"kept\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"package\":\"./modules/a\",\"tests\":12}],\"level\":\"unit\",\"tests\":[{\"package\":\"./modules/b\",\"pass\":true}],\"unmet\":[{\"needs\":[\"docker\"],\"package\":\"./modules/c\"}]}]},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"check\",\"v\":1}", wire: "{\"ended\":\"2026-11-05T10:06:00Z\",\"id\":\"c3d4\",\"node\":\"ace\",\"result\":{\"fetch\":{\"base\":\"abcdef0123456789abcdef0123456789abcdef01\",\"changed\":[\"a.go\",\"modules/m/main.go\"],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"merge\":\"fedcba9876543210fedcba9876543210fedcba98\",\"modules\":[\".\"],\"trees\":{\"modules/m\":{\"locks\":{\"go.sum\":\"c5fc83c01e92404452b986527d239140ccf9a48b88e0c268fbf38c2e1429e9c9\"},\"manifest\":\"ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356\",\"tree\":\"1111111111111111111111111111111111111111\"}},\"workspace\":\"mvii1iwu5414e4\"},\"levels\":[{\"digest\":{\"level\":\"unit\",\"packages\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"package\":\"./modules/a\"}]},\"kept\":[{\"digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"package\":\"./modules/a\",\"tests\":12}],\"level\":\"unit\",\"tests\":[{\"package\":\"./modules/b\",\"pass\":true}],\"unmet\":[{\"needs\":[\"docker\"],\"package\":\"./modules/c\"}]}]},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"passed\",\"tool\":\"check\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a declined step", subject: "", given: "{\"id\":\"c3d5\",\"node\":\"ace\",\"result\":{\"declined\":true,\"lacks\":[\"docker\"],\"needs\":[\"docker\"]},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"refused\",\"tool\":\"check\",\"v\":1}", wire: "{\"id\":\"c3d5\",\"node\":\"ace\",\"result\":{\"declined\":true,\"lacks\":[\"docker\"],\"needs\":[\"docker\"]},\"started\":\"2026-11-05T10:00:00Z\",\"state\":\"refused\",\"tool\":\"check\",\"v\":1}",
|
||||
@@ -57,8 +63,34 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-go.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"go\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.step$")},
|
||||
{name: "a run ask of the runner, the program built from the change and run over its heads", subject: "mesh.seat.node-build-go.accept.run", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-05T10:00:00Z\",\"id\":\"r5e6\",\"kind\":\"run\",\"language\":\"go\",\"run\":{\"args\":[\"-verdict\"],\"heads\":[{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-delivery\"},{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-sdk\"}],\"input\":{\"digest\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"size\":7,\"verb\":\"seat:mesh-delivery-checker.input\"},\"program\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"dir\":\"modules/mesh-delivery-checker\",\"package\":\"./cmd/mesh-checking-program\",\"repository\":\"novox/mesh-delivery\"},\"reader\":\"checking program of mesh-delivery head\"},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v RunAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-go\\.accept\\.run$")},
|
||||
{name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact asks", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers where the bytes are", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a module that is claims no oci-artifact-registry", subject: "", given: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}", wire: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build it no longer keeps", subject: "", given: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}", wire: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build kept under another digest", subject: "", given: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}", wire: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers an error, never none", subject: "", given: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps asks an artifact's pipeline steps at a commit", subject: "", given: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}", wire: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v StepsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps answers lint and unit tests", subject: "", given: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}", wire: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v StepsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -15,36 +15,69 @@ import (
|
||||
const Seat = "node-build-image"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbKeptArtifact = "kept-artifact"
|
||||
VerbSteps = "steps"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptStep = "step"
|
||||
AcceptRecheck = "recheck"
|
||||
)
|
||||
|
||||
const (
|
||||
EventStepEnded = "step-ended"
|
||||
)
|
||||
|
||||
// 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, VerbDrop}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop, VerbKeptArtifact, VerbSteps}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventStepEnded}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "node-build-image.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamStepEnded is the stream step-ended is kept in.
|
||||
const StreamStepEnded = "SEAT_node-build-image_step-ended"
|
||||
|
||||
// SubjectStepEnded is where step-ended is published, on mesh.seat.node-build-image.event.step-ended.<node>.
|
||||
func SubjectStepEnded(node string) string {
|
||||
return "mesh.seat.node-build-image.event.step-ended." + node
|
||||
}
|
||||
|
||||
// SubjectStepEndedAll hears every step-ended.
|
||||
const SubjectStepEndedAll = "mesh.seat.node-build-image.event.step-ended.*"
|
||||
|
||||
// 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"
|
||||
|
||||
// AcceptSubjectStep is where step is sent.
|
||||
const AcceptSubjectStep = "mesh.seat.node-build-image.accept.step"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-image.accept.recheck"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateDetectedSteps = "detected-steps"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
@@ -224,6 +257,42 @@ func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageVa
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DetectedStepsByModuleArtifactKey is the key of one value of the state detected-steps under the form "<module>.<artifact>".
|
||||
func DetectedStepsByModuleArtifactKey(module, artifact string) string { return module + "." + artifact }
|
||||
|
||||
// ParseDetectedStepsByModuleArtifactKey reads the parts of a key of the form "<module>.<artifact>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseDetectedStepsByModuleArtifactKey(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
|
||||
}
|
||||
|
||||
// DecodeDetectedStepsByModuleArtifactValue reads one value of the state detected-steps under the form "<module>.<artifact>", refusing a field DetectedStepsByModuleArtifactValue does not know and any text after the value.
|
||||
func DecodeDetectedStepsByModuleArtifactValue(raw []byte) (DetectedStepsByModuleArtifactValue, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
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
|
||||
}
|
||||
|
||||
// AskArtifact is one artifact of a build ask: built from the fetched tree, or copied from an upstream pin.
|
||||
type AskArtifact struct {
|
||||
Artifact string `json:"artifact"`
|
||||
@@ -236,8 +305,10 @@ type AskArtifact struct {
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// BuiltArtifact is one artifact a build made: its digest and the reference it was published under.
|
||||
@@ -281,6 +352,28 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// DetectedStep is a type of the contract.
|
||||
type DetectedStep struct {
|
||||
// the packages the step runs, by the language's convention
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of DetectedStep's step.
|
||||
const (
|
||||
DetectedStepStepLint = "lint"
|
||||
DetectedStepStepUnit = "unit"
|
||||
DetectedStepStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// DetectedSteps is the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326).
|
||||
type DetectedSteps struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -352,6 +445,18 @@ type FetchRefusal struct {
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// KeptResult is a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names.
|
||||
type KeptResult struct {
|
||||
// sha256:<hex> of what the package's tests read
|
||||
Digest string `json:"digest"`
|
||||
// unit or integration
|
||||
Level string `json:"level"`
|
||||
Package string `json:"package"`
|
||||
// the pipeline whose step kept it
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// LevelAnswerDigestNeedsItem is a type of the contract.
|
||||
type LevelAnswerDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
@@ -550,7 +655,7 @@ type StepAsk struct {
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
// build, check, compose or step
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
@@ -559,11 +664,72 @@ type StepAsk struct {
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose
|
||||
Run *RunJob `json:"run,omitempty"`
|
||||
// a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*)
|
||||
Step *StepRun `json:"step,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
// StepEnded is a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at.
|
||||
type StepEnded struct {
|
||||
Artifact string `json:"artifact"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the packages not run because the ask's kept results held them
|
||||
Carried []KeptResult `json:"carried,omitempty"`
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// the packages that passed at their digest, for the runner to keep
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// the node that ran it, as in the subject
|
||||
Node string `json:"node"`
|
||||
// never passed for a step that ran nothing
|
||||
Outcome string `json:"outcome"`
|
||||
// the step's output when it fits the message
|
||||
Output string `json:"output,omitempty"`
|
||||
// the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16)
|
||||
OutputObject string `json:"output-object,omitempty"`
|
||||
Pipeline string `json:"pipeline"`
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// why it failed or could not run, naming the part not heard
|
||||
Said string `json:"said,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
Step string `json:"step"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepEnded's outcome.
|
||||
const (
|
||||
StepEndedOutcomePassed = "passed"
|
||||
StepEndedOutcomeFailed = "failed"
|
||||
StepEndedOutcomeNothingToRun = "nothing to run"
|
||||
StepEndedOutcomeCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// The values of StepEnded's step.
|
||||
const (
|
||||
StepEndedStepLint = "lint"
|
||||
StepEndedStepUnit = "unit"
|
||||
StepEndedStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// StepNames is the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part.
|
||||
type StepNames struct {
|
||||
// every watched branch a registration names
|
||||
Branches []string `json:"branches"`
|
||||
// every module the registrations name
|
||||
Modules []string `json:"modules"`
|
||||
// every repository a registration's git origin names, as <owner>/<name>
|
||||
Repositories []string `json:"repositories"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
type StepResult struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts,omitempty"`
|
||||
Built bool `json:"built,omitempty"`
|
||||
@@ -573,7 +739,9 @@ type StepResult struct {
|
||||
Exit int64 `json:"exit,omitempty"`
|
||||
Fetch *FetchAnswer `json:"fetch,omitempty"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// what the holder's node lacks of it
|
||||
Lacks []string `json:"lacks,omitempty"`
|
||||
Levels []LevelAnswer `json:"levels,omitempty"`
|
||||
@@ -589,6 +757,42 @@ type StepResult struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// StepRun is one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip.
|
||||
type StepRun struct {
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the commit the step runs at
|
||||
Commit string `json:"commit"`
|
||||
// where the step reads the change's heads
|
||||
Fetch Fetch `json:"fetch"`
|
||||
// the artifact's build-input fingerprint at the commit
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*)
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Names StepNames `json:"names"`
|
||||
// the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the step is asked again by the runner's rerun
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// the source revision of the watched branch the pipeline runs for; absent for a run on request
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the pipeline step
|
||||
Step string `json:"step"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepRun's step.
|
||||
const (
|
||||
StepRunStepLint = "lint"
|
||||
StepRunStepUnit = "unit"
|
||||
StepRunStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// TakenVersion is of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said.
|
||||
type TakenVersion struct {
|
||||
Asked string `json:"asked"`
|
||||
@@ -600,6 +804,12 @@ type TakenVersion struct {
|
||||
Sum string `json:"sum,omitempty"`
|
||||
}
|
||||
|
||||
// TestCounts is how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget).
|
||||
type TestCounts struct {
|
||||
Integration int64 `json:"integration,omitempty"`
|
||||
Unit int64 `json:"unit,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -653,15 +863,80 @@ type DropInput struct {
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// KeptArtifactInput is what kept-artifact takes.
|
||||
type KeptArtifactInput struct {
|
||||
// the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it
|
||||
Digest string `json:"digest"`
|
||||
// its build's fingerprint
|
||||
Fp string `json:"fp"`
|
||||
// the module, the holder of oci-artifact-registry
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// KeptArtifactAnswer is what kept-artifact answers.
|
||||
type KeptArtifactAnswer struct {
|
||||
// the digest of the bytes kept
|
||||
Digest string `json:"digest,omitempty"`
|
||||
// why it could not answer
|
||||
Error string `json:"error,omitempty"`
|
||||
// the fingerprint asked
|
||||
Fp string `json:"fp"`
|
||||
// the module asked
|
||||
Module string `json:"module"`
|
||||
// the object's name in it: the digest
|
||||
Object string `json:"object,omitempty"`
|
||||
// why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// bytes
|
||||
Size int64 `json:"size,omitempty"`
|
||||
// the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus
|
||||
Store string `json:"store,omitempty"`
|
||||
// the refusal in words, naming the module
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// The values of KeptArtifactAnswer's refused.
|
||||
const (
|
||||
KeptArtifactAnswerRefusedClaimsNoOciArtifactRegistry = "claims no oci-artifact-registry"
|
||||
KeptArtifactAnswerRefusedNotKept = "not kept"
|
||||
KeptArtifactAnswerRefusedDigestDiffers = "digest differs"
|
||||
)
|
||||
|
||||
// StepsInput is what steps takes.
|
||||
type StepsInput struct {
|
||||
// find them anew, not from the kept answer
|
||||
Again bool `json:"again,omitempty"`
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
Fetch Fetch `json:"fetch"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// StepsAnswer is what steps answers.
|
||||
type StepsAnswer struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
// answered from the kept answer
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
}
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// StepAccept is the body of step.
|
||||
type StepAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// StepEndedEvent is the body of the event step-ended.
|
||||
type StepEndedEvent = StepEnded
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
@@ -676,3 +951,6 @@ type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
|
||||
// DetectedStepsByModuleArtifactValue is one value of the state detected-steps under the key <module>.<artifact>.
|
||||
type DetectedStepsByModuleArtifactValue = DetectedSteps
|
||||
|
||||
@@ -17,6 +17,10 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a lint step ended passed on its node", subject: "mesh.seat.node-build-image.event.step-ended.ace", given: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"lint\",\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"lint\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{name: "a lint step that could not run, naming the part not heard", subject: "mesh.seat.node-build-image.event.step-ended.g14", given: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"lint\",\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"lint\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{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}",
|
||||
@@ -43,8 +47,32 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a lint step ask of the runner with the names", subject: "mesh.seat.node-build-image.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"image\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"lint\"},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-image\\.accept\\.step$")},
|
||||
{name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact asks", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers where the bytes are", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a module that is claims no oci-artifact-registry", subject: "", given: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}", wire: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build it no longer keeps", subject: "", given: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}", wire: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build kept under another digest", subject: "", given: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}", wire: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers an error, never none", subject: "", given: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps asks an artifact's pipeline steps at a commit", subject: "", given: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}", wire: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v StepsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps answers lint and unit tests", subject: "", given: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}", wire: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v StepsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -15,36 +15,69 @@ import (
|
||||
const Seat = "node-build-node"
|
||||
|
||||
const (
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbCurrent = "current"
|
||||
VerbPause = "pause"
|
||||
VerbResume = "resume"
|
||||
VerbDrop = "drop"
|
||||
VerbKeptArtifact = "kept-artifact"
|
||||
VerbSteps = "steps"
|
||||
)
|
||||
|
||||
const (
|
||||
AcceptDelivery = "delivery"
|
||||
AcceptCheck = "check"
|
||||
AcceptStep = "step"
|
||||
AcceptRecheck = "recheck"
|
||||
)
|
||||
|
||||
const (
|
||||
EventStepEnded = "step-ended"
|
||||
)
|
||||
|
||||
// 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, VerbDrop}
|
||||
return []string{VerbCurrent, VerbPause, VerbResume, VerbDrop, VerbKeptArtifact, VerbSteps}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventStepEnded}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "node-build-node.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// StreamStepEnded is the stream step-ended is kept in.
|
||||
const StreamStepEnded = "SEAT_node-build-node_step-ended"
|
||||
|
||||
// SubjectStepEnded is where step-ended is published, on mesh.seat.node-build-node.event.step-ended.<node>.
|
||||
func SubjectStepEnded(node string) string {
|
||||
return "mesh.seat.node-build-node.event.step-ended." + node
|
||||
}
|
||||
|
||||
// SubjectStepEndedAll hears every step-ended.
|
||||
const SubjectStepEndedAll = "mesh.seat.node-build-node.event.step-ended.*"
|
||||
|
||||
// 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"
|
||||
|
||||
// AcceptSubjectStep is where step is sent.
|
||||
const AcceptSubjectStep = "mesh.seat.node-build-node.accept.step"
|
||||
|
||||
// AcceptSubjectRecheck is where recheck is sent.
|
||||
const AcceptSubjectRecheck = "mesh.seat.node-build-node.accept.recheck"
|
||||
|
||||
const (
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateSteps = "steps"
|
||||
StatePauses = "pauses"
|
||||
StateToolchains = "toolchains"
|
||||
StateDetectedSteps = "detected-steps"
|
||||
)
|
||||
|
||||
// StepsByNodeIDKey is the key of one value of the state steps under the form "<node>.<id>".
|
||||
@@ -224,6 +257,42 @@ func DecodeToolchainsByNodeLanguageValue(raw []byte) (ToolchainsByNodeLanguageVa
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DetectedStepsByModuleArtifactKey is the key of one value of the state detected-steps under the form "<module>.<artifact>".
|
||||
func DetectedStepsByModuleArtifactKey(module, artifact string) string { return module + "." + artifact }
|
||||
|
||||
// ParseDetectedStepsByModuleArtifactKey reads the parts of a key of the form "<module>.<artifact>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseDetectedStepsByModuleArtifactKey(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
|
||||
}
|
||||
|
||||
// DecodeDetectedStepsByModuleArtifactValue reads one value of the state detected-steps under the form "<module>.<artifact>", refusing a field DetectedStepsByModuleArtifactValue does not know and any text after the value.
|
||||
func DecodeDetectedStepsByModuleArtifactValue(raw []byte) (DetectedStepsByModuleArtifactValue, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
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
|
||||
}
|
||||
|
||||
// AskArtifact is one artifact of a build ask: built from the fetched tree, or copied from an upstream pin.
|
||||
type AskArtifact struct {
|
||||
Artifact string `json:"artifact"`
|
||||
@@ -236,8 +305,10 @@ type AskArtifact struct {
|
||||
type BuildAnswer struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// BuiltArtifact is one artifact a build made: its digest and the reference it was published under.
|
||||
@@ -281,6 +352,28 @@ type ComposeAnswer struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// DetectedStep is a type of the contract.
|
||||
type DetectedStep struct {
|
||||
// the packages the step runs, by the language's convention
|
||||
Packages []string `json:"packages,omitempty"`
|
||||
Step string `json:"step"`
|
||||
}
|
||||
|
||||
// The values of DetectedStep's step.
|
||||
const (
|
||||
DetectedStepStepLint = "lint"
|
||||
DetectedStepStepUnit = "unit"
|
||||
DetectedStepStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// DetectedSteps is the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326).
|
||||
type DetectedSteps struct {
|
||||
At *time.Time `json:"at,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// Drop is an ask a caller no longer waits for.
|
||||
type Drop struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -352,6 +445,18 @@ type FetchRefusal struct {
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
// KeptResult is a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names.
|
||||
type KeptResult struct {
|
||||
// sha256:<hex> of what the package's tests read
|
||||
Digest string `json:"digest"`
|
||||
// unit or integration
|
||||
Level string `json:"level"`
|
||||
Package string `json:"package"`
|
||||
// the pipeline whose step kept it
|
||||
Pipeline string `json:"pipeline,omitempty"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// LevelAnswerDigestNeedsItem is a type of the contract.
|
||||
type LevelAnswerDigestNeedsItem struct {
|
||||
Needs []string `json:"needs,omitempty"`
|
||||
@@ -550,7 +655,7 @@ type StepAsk struct {
|
||||
Check *StepAskCheck `json:"check,omitempty"`
|
||||
Compose *StepAskCompose `json:"compose,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// build, check or compose
|
||||
// build, check, compose or step
|
||||
Kind string `json:"kind"`
|
||||
// go, typescript or image
|
||||
Language string `json:"language"`
|
||||
@@ -559,11 +664,72 @@ type StepAsk struct {
|
||||
Packages map[string]string `json:"packages,omitempty"`
|
||||
// a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose
|
||||
Run *RunJob `json:"run,omitempty"`
|
||||
// a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*)
|
||||
Step *StepRun `json:"step,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
// StepEnded is a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at.
|
||||
type StepEnded struct {
|
||||
Artifact string `json:"artifact"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the packages not run because the ask's kept results held them
|
||||
Carried []KeptResult `json:"carried,omitempty"`
|
||||
Commit string `json:"commit"`
|
||||
Ended *time.Time `json:"ended,omitempty"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the ask's id
|
||||
ID string `json:"id"`
|
||||
// the packages that passed at their digest, for the runner to keep
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
// the node that ran it, as in the subject
|
||||
Node string `json:"node"`
|
||||
// never passed for a step that ran nothing
|
||||
Outcome string `json:"outcome"`
|
||||
// the step's output when it fits the message
|
||||
Output string `json:"output,omitempty"`
|
||||
// the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16)
|
||||
OutputObject string `json:"output-object,omitempty"`
|
||||
Pipeline string `json:"pipeline"`
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// why it failed or could not run, naming the part not heard
|
||||
Said string `json:"said,omitempty"`
|
||||
Started *time.Time `json:"started,omitempty"`
|
||||
Step string `json:"step"`
|
||||
Tests *TestCounts `json:"tests,omitempty"`
|
||||
// the layout version
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepEnded's outcome.
|
||||
const (
|
||||
StepEndedOutcomePassed = "passed"
|
||||
StepEndedOutcomeFailed = "failed"
|
||||
StepEndedOutcomeNothingToRun = "nothing to run"
|
||||
StepEndedOutcomeCouldNotRun = "could not run"
|
||||
)
|
||||
|
||||
// The values of StepEnded's step.
|
||||
const (
|
||||
StepEndedStepLint = "lint"
|
||||
StepEndedStepUnit = "unit"
|
||||
StepEndedStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// StepNames is the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part.
|
||||
type StepNames struct {
|
||||
// every watched branch a registration names
|
||||
Branches []string `json:"branches"`
|
||||
// every module the registrations name
|
||||
Modules []string `json:"modules"`
|
||||
// every repository a registration's git origin names, as <owner>/<name>
|
||||
Repositories []string `json:"repositories"`
|
||||
}
|
||||
|
||||
// StepResult is what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five.
|
||||
type StepResult struct {
|
||||
Artifacts []BuiltArtifact `json:"artifacts,omitempty"`
|
||||
Built bool `json:"built,omitempty"`
|
||||
@@ -573,7 +739,9 @@ type StepResult struct {
|
||||
Exit int64 `json:"exit,omitempty"`
|
||||
Fetch *FetchAnswer `json:"fetch,omitempty"`
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored
|
||||
Kept string `json:"kept,omitempty"`
|
||||
Key string `json:"key,omitempty"`
|
||||
// what the holder's node lacks of it
|
||||
Lacks []string `json:"lacks,omitempty"`
|
||||
Levels []LevelAnswer `json:"levels,omitempty"`
|
||||
@@ -589,6 +757,42 @@ type StepResult struct {
|
||||
Verdict any `json:"verdict,omitempty"`
|
||||
}
|
||||
|
||||
// StepRun is one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip.
|
||||
type StepRun struct {
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
// the watched branch, or the branch of a run on request
|
||||
Branch string `json:"branch,omitempty"`
|
||||
// for a rerun, the caller the runtime proved
|
||||
By string `json:"by,omitempty"`
|
||||
// the commit the step runs at
|
||||
Commit string `json:"commit"`
|
||||
// where the step reads the change's heads
|
||||
Fetch Fetch `json:"fetch"`
|
||||
// the artifact's build-input fingerprint at the commit
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
// the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*)
|
||||
Kept []KeptResult `json:"kept,omitempty"`
|
||||
Module string `json:"module"`
|
||||
Names StepNames `json:"names"`
|
||||
// the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is
|
||||
Pipeline string `json:"pipeline"`
|
||||
// the step is asked again by the runner's rerun
|
||||
Rerun bool `json:"rerun,omitempty"`
|
||||
// the source revision of the watched branch the pipeline runs for; absent for a run on request
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
// the pipeline step
|
||||
Step string `json:"step"`
|
||||
Toolchain *ToolchainUsed `json:"toolchain,omitempty"`
|
||||
}
|
||||
|
||||
// The values of StepRun's step.
|
||||
const (
|
||||
StepRunStepLint = "lint"
|
||||
StepRunStepUnit = "unit"
|
||||
StepRunStepIntegration = "integration"
|
||||
)
|
||||
|
||||
// TakenVersion is of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said.
|
||||
type TakenVersion struct {
|
||||
Asked string `json:"asked"`
|
||||
@@ -600,6 +804,12 @@ type TakenVersion struct {
|
||||
Sum string `json:"sum,omitempty"`
|
||||
}
|
||||
|
||||
// TestCounts is how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget).
|
||||
type TestCounts struct {
|
||||
Integration int64 `json:"integration,omitempty"`
|
||||
Unit int64 `json:"unit,omitempty"`
|
||||
}
|
||||
|
||||
// Toolchain is the toolchain a node reports.
|
||||
type Toolchain struct {
|
||||
// when (RFC 3339 time)
|
||||
@@ -653,15 +863,80 @@ type DropInput struct {
|
||||
// DropAnswer is what drop answers.
|
||||
type DropAnswer = map[string]any
|
||||
|
||||
// KeptArtifactInput is what kept-artifact takes.
|
||||
type KeptArtifactInput struct {
|
||||
// the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it
|
||||
Digest string `json:"digest"`
|
||||
// its build's fingerprint
|
||||
Fp string `json:"fp"`
|
||||
// the module, the holder of oci-artifact-registry
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// KeptArtifactAnswer is what kept-artifact answers.
|
||||
type KeptArtifactAnswer struct {
|
||||
// the digest of the bytes kept
|
||||
Digest string `json:"digest,omitempty"`
|
||||
// why it could not answer
|
||||
Error string `json:"error,omitempty"`
|
||||
// the fingerprint asked
|
||||
Fp string `json:"fp"`
|
||||
// the module asked
|
||||
Module string `json:"module"`
|
||||
// the object's name in it: the digest
|
||||
Object string `json:"object,omitempty"`
|
||||
// why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest
|
||||
Refused string `json:"refused,omitempty"`
|
||||
// bytes
|
||||
Size int64 `json:"size,omitempty"`
|
||||
// the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus
|
||||
Store string `json:"store,omitempty"`
|
||||
// the refusal in words, naming the module
|
||||
Words string `json:"words,omitempty"`
|
||||
}
|
||||
|
||||
// The values of KeptArtifactAnswer's refused.
|
||||
const (
|
||||
KeptArtifactAnswerRefusedClaimsNoOciArtifactRegistry = "claims no oci-artifact-registry"
|
||||
KeptArtifactAnswerRefusedNotKept = "not kept"
|
||||
KeptArtifactAnswerRefusedDigestDiffers = "digest differs"
|
||||
)
|
||||
|
||||
// StepsInput is what steps takes.
|
||||
type StepsInput struct {
|
||||
// find them anew, not from the kept answer
|
||||
Again bool `json:"again,omitempty"`
|
||||
// the artifact reference, <module>:<artifact>
|
||||
Artifact string `json:"artifact"`
|
||||
Fetch Fetch `json:"fetch"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Module string `json:"module"`
|
||||
}
|
||||
|
||||
// StepsAnswer is what steps answers.
|
||||
type StepsAnswer struct {
|
||||
Artifact string `json:"artifact"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
// answered from the kept answer
|
||||
Kept bool `json:"kept,omitempty"`
|
||||
Steps []DetectedStep `json:"steps"`
|
||||
}
|
||||
|
||||
// DeliveryAccept is the body of delivery.
|
||||
type DeliveryAccept = StepAsk
|
||||
|
||||
// CheckAccept is the body of check.
|
||||
type CheckAccept = StepAsk
|
||||
|
||||
// StepAccept is the body of step.
|
||||
type StepAccept = StepAsk
|
||||
|
||||
// RecheckAccept is the body of recheck.
|
||||
type RecheckAccept = StepAsk
|
||||
|
||||
// StepEndedEvent is the body of the event step-ended.
|
||||
type StepEndedEvent = StepEnded
|
||||
|
||||
// StepsByNodeIDValue is one value of the state steps under the key <node>.<id>.
|
||||
type StepsByNodeIDValue = Step
|
||||
|
||||
@@ -676,3 +951,6 @@ type PausesByCapacityNodeValue = Capacity
|
||||
|
||||
// ToolchainsByNodeLanguageValue is one value of the state toolchains under the key <node>.<language>.
|
||||
type ToolchainsByNodeLanguageValue = Toolchain
|
||||
|
||||
// DetectedStepsByModuleArtifactValue is one value of the state detected-steps under the key <module>.<artifact>.
|
||||
type DetectedStepsByModuleArtifactValue = DetectedSteps
|
||||
|
||||
@@ -17,6 +17,10 @@ func TestFixtures(t *testing.T) {
|
||||
decode func([]byte) (any, error)
|
||||
subjectIs *regexp.Regexp
|
||||
}{
|
||||
{name: "a unit step ended passed on its node, with its counts and what it carried", subject: "mesh.seat.node-build-node.event.step-ended.ace", given: "{\"artifact\":\"nats:program\",\"carried\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\"}],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"kept\":[{\"digest\":\"sha256:cccc\",\"level\":\"unit\",\"package\":\"./modules/nats/b\"}],\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"unit\",\"tests\":{\"unit\":14},\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"carried\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\"}],\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"ended\":\"2026-11-10T10:02:00Z\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5e\",\"kept\":[{\"digest\":\"sha256:cccc\",\"level\":\"unit\",\"package\":\"./modules/nats/b\"}],\"module\":\"nats\",\"node\":\"ace\",\"outcome\":\"passed\",\"pipeline\":\"main.12.nats\",\"started\":\"2026-11-10T10:00:00Z\",\"step\":\"unit\",\"tests\":{\"unit\":14},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{name: "an integration step that could not run, naming the part not heard", subject: "mesh.seat.node-build-node.event.step-ended.g14", given: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"integration\",\"v\":1}", wire: "{\"artifact\":\"nats:program\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fingerprint\":\"fp-0123\",\"id\":\"m2kx9a1b3c4d5f\",\"module\":\"nats\",\"node\":\"g14\",\"outcome\":\"could not run\",\"output-object\":\"mesh-build-go_sent-objects/m2kx9a1b3c4d5f\",\"pipeline\":\"main.12.nats\",\"said\":\"the sandbox could not fetch novox/mesh-sdk\",\"step\":\"integration\",\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepEndedEvent; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.event\\.step-ended\\.[^.*> ]+$")},
|
||||
{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}",
|
||||
@@ -47,8 +51,32 @@ func TestFixtures(t *testing.T) {
|
||||
decode: func(b []byte) (any, error) { var v StepsByNodeIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "an ask dropped by the caller that no longer waits", subject: "", given: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"at\":\"2026-11-05T10:00:00Z\",\"by\":\"mesh-delivery-builder\",\"v\":1,\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v PausesByDroppedIDValue; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "a step ask of the runner with the names and kept results", subject: "mesh.seat.node-build-node.accept.step", given: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}", wire: "{\"asker\":\"mesh-delivery-pipeline\",\"at\":\"2026-11-10T10:00:00Z\",\"id\":\"m2kx9a1b3c4d5e\",\"kind\":\"step\",\"language\":\"typescript\",\"step\":{\"artifact\":\"nats:program\",\"branch\":\"main\",\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"kept\":[{\"digest\":\"sha256:bbbb\",\"level\":\"unit\",\"package\":\"./modules/nats/a\",\"pipeline\":\"main.11.nats\"}],\"module\":\"nats\",\"names\":{\"branches\":[\"main\"],\"modules\":[\"nats\",\"mesh-sdk\"],\"repositories\":[\"novox/mesh-catalog\",\"novox/mesh-sdk\"]},\"pipeline\":\"main.12.nats\",\"revision\":12,\"step\":\"unit\"},\"v\":1}",
|
||||
decode: func(b []byte) (any, error) { var v StepAccept; err := json.Unmarshal(b, &v); return v, err }, subjectIs: regexp.MustCompile("^mesh\\.seat\\.node-build-node\\.accept\\.step$")},
|
||||
{name: "an artifact's detected steps", subject: "", given: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}", wire: "{\"at\":\"2026-11-10T10:00:00Z\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats/a\"],\"step\":\"unit\"}],\"v\":1}",
|
||||
decode: func(b []byte) (any, error) {
|
||||
var v DetectedStepsByModuleArtifactValue
|
||||
err := json.Unmarshal(b, &v)
|
||||
return v, err
|
||||
}, subjectIs: nil},
|
||||
{name: "drop names the ask and why", subject: "", given: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}", wire: "{\"by\":\"mesh-delivery-builder\",\"id\":\"a1b2\",\"why\":\"a newer fingerprint supersedes it\"}",
|
||||
decode: func(b []byte) (any, error) { var v DropInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact asks", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers where the bytes are", subject: "", given: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}", wire: "{\"digest\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"object\":\"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"size\":18874368,\"store\":\"mesh-build-go-kept\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a module that is claims no oci-artifact-registry", subject: "", given: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}", wire: "{\"fp\":\"src2:aaaaaaaa\",\"module\":\"mesh-delivery-gate\",\"refused\":\"claims no oci-artifact-registry\",\"words\":\"mesh-delivery-gate claims no oci-artifact-registry: its build is fetched from the store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build it no longer keeps", subject: "", given: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}", wire: "{\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"not kept\",\"words\":\"this node keeps no build of artifact-store at src2:1480985e\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact refuses a build kept under another digest", subject: "", given: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}", wire: "{\"digest\":\"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\",\"refused\":\"digest differs\",\"words\":\"artifact-store at src2:1480985e is kept as eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "kept-artifact answers an error, never none", subject: "", given: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}", wire: "{\"error\":\"the kept builds could not be read\",\"fp\":\"src2:1480985e\",\"module\":\"artifact-store\"}",
|
||||
decode: func(b []byte) (any, error) { var v KeptArtifactAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps asks an artifact's pipeline steps at a commit", subject: "", given: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}", wire: "{\"artifact\":\"nats:program\",\"fetch\":{\"commit\":\"0123456789abcdef0123456789abcdef01234567\",\"repository\":\"novox/mesh-catalog\"},\"fingerprint\":\"fp-0123\",\"module\":\"nats\"}",
|
||||
decode: func(b []byte) (any, error) { var v StepsInput; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
{name: "steps answers lint and unit tests", subject: "", given: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}", wire: "{\"artifact\":\"nats:program\",\"fingerprint\":\"fp-0123\",\"steps\":[{\"step\":\"lint\"},{\"packages\":[\"./modules/nats\"],\"step\":\"unit\"}]}",
|
||||
decode: func(b []byte) (any, error) { var v StepsAnswer; err := json.Unmarshal(b, &v); return v, err }, subjectIs: nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := c.decode([]byte(c.given))
|
||||
|
||||
@@ -314,6 +314,66 @@
|
||||
"go/clients/meshwantsclient"
|
||||
],
|
||||
"series": "0.1"
|
||||
},
|
||||
{
|
||||
"name": "go-meshbuilds",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/meshbuilds"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-meshpipelinerunner",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/meshpipelinerunner"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-meshbuilds",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/meshbuilds"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-meshpipelinerunner",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/meshpipelinerunner"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "go-git",
|
||||
"kind": "package",
|
||||
"language": "go",
|
||||
"paths": [
|
||||
"go/seats/git"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
},
|
||||
{
|
||||
"name": "ts-git",
|
||||
"kind": "package",
|
||||
"language": "typescript",
|
||||
"paths": [
|
||||
"ts/seats/git"
|
||||
],
|
||||
"series": "0.1",
|
||||
"generated-from": "."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
"events": [
|
||||
{
|
||||
"name": "package-published",
|
||||
"subject": "package-published",
|
||||
"keep": {
|
||||
"max-age-days": 90,
|
||||
"max-mib": 128
|
||||
@@ -86,7 +85,6 @@
|
||||
},
|
||||
{
|
||||
"name": "toolchain-agreed",
|
||||
"subject": "toolchain-agreed",
|
||||
"keep": {
|
||||
"max-age-days": 90,
|
||||
"max-mib": 16
|
||||
|
||||
+35
-61
@@ -4,85 +4,59 @@
|
||||
|
||||
import type * as registry from "./parts/registry.js";
|
||||
|
||||
export const seat = "container-image-registry";
|
||||
export declare const seat: "container-image-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
mirror: "mirror",
|
||||
tags: "tags",
|
||||
hold: "hold",
|
||||
release: "release",
|
||||
list: "list",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
readonly mirror: "mirror";
|
||||
readonly tags: "tags";
|
||||
readonly hold: "hold";
|
||||
readonly release: "release";
|
||||
readonly list: "list";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
held: "held",
|
||||
released: "released",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
readonly held: "held";
|
||||
readonly released: "released";
|
||||
};
|
||||
|
||||
export const family = { name: "container-image-registry.events", maxAgeDays: 7 } as const;
|
||||
export declare const family: { readonly name: "container-image-registry.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.container-image-registry.event.published";
|
||||
export declare const publishedSubject: "mesh.seat.container-image-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.container-image-registry.event.refused";
|
||||
export declare const refusedSubject: "mesh.seat.container-image-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.container-image-registry.event.removed";
|
||||
export declare const removedSubject: "mesh.seat.container-image-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.container-image-registry.event.kept";
|
||||
export declare const keptSubject: "mesh.seat.container-image-registry.event.kept";
|
||||
|
||||
export const heldSubject = "mesh.seat.container-image-registry.event.held";
|
||||
export declare const heldSubject: "mesh.seat.container-image-registry.event.held";
|
||||
|
||||
export const releasedSubject = "mesh.seat.container-image-registry.event.released";
|
||||
export declare const releasedSubject: "mesh.seat.container-image-registry.event.released";
|
||||
|
||||
export const states = {
|
||||
holds: "holds",
|
||||
windows: "windows",
|
||||
} as const;
|
||||
export declare const states: {
|
||||
readonly holds: "holds";
|
||||
readonly windows: "windows";
|
||||
};
|
||||
|
||||
/** The key of one value of the state holds under the form "<seat>.<name>.<digest>". */
|
||||
export function holdsBySeatNameDigestKey(seat: string, name: string, digest: string): string {
|
||||
return seat + "." + name + "." + digest;
|
||||
}
|
||||
export declare function holdsBySeatNameDigestKey(seat: string, name: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "<seat>.<name>.<digest>", or undefined for a key of another form. */
|
||||
export function parseHoldsBySeatNameDigestKey(_key: string): { seat: string; name: string; digest: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const seat = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const name = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { seat, name, digest };
|
||||
}
|
||||
export declare function parseHoldsBySeatNameDigestKey(_key: string): { seat: string; name: string; digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state windows under the form "<caller>". */
|
||||
export function windowsByCallerKey(caller: string): string {
|
||||
return caller;
|
||||
}
|
||||
export declare function windowsByCallerKey(caller: string): string;
|
||||
|
||||
/** The parts of a key of the form "<caller>", or undefined for a key of another form. */
|
||||
export function parseWindowsByCallerKey(_key: string): { caller: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const caller = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { caller };
|
||||
}
|
||||
export declare function parseWindowsByCallerKey(_key: string): { caller: string } | undefined;
|
||||
|
||||
export type Artifact = registry.Artifact;
|
||||
export type KeptEvent = registry.KeptEvent;
|
||||
@@ -0,0 +1,84 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "container-image-registry", defined whole (seats/container-image-registry/seat.json): The mesh's container images, in the one artifact store: the OCI distribution protocol's read side, an image's tags and mirroring an outside image.
|
||||
|
||||
export const seat = "container-image-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
mirror: "mirror",
|
||||
tags: "tags",
|
||||
hold: "hold",
|
||||
release: "release",
|
||||
list: "list",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
held: "held",
|
||||
released: "released",
|
||||
};
|
||||
|
||||
export const family = { name: "container-image-registry.events", maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.container-image-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.container-image-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.container-image-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.container-image-registry.event.kept";
|
||||
|
||||
export const heldSubject = "mesh.seat.container-image-registry.event.held";
|
||||
|
||||
export const releasedSubject = "mesh.seat.container-image-registry.event.released";
|
||||
|
||||
export const states = {
|
||||
holds: "holds",
|
||||
windows: "windows",
|
||||
};
|
||||
|
||||
/** The key of one value of the state holds under the form "<seat>.<name>.<digest>". */
|
||||
export function holdsBySeatNameDigestKey(seat, name, digest) {
|
||||
return seat + "." + name + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<seat>.<name>.<digest>", or undefined for a key of another form. */
|
||||
export function parseHoldsBySeatNameDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const seat = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const name = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { seat, name, digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state windows under the form "<caller>". */
|
||||
export function windowsByCallerKey(caller) {
|
||||
return caller;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<caller>", or undefined for a key of another form. */
|
||||
export function parseWindowsByCallerKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const caller = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { caller };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat container-image-registry, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-container-image-registry",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+12
-12
@@ -2,19 +2,19 @@
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
/** one published thing, as every registry event and answer names it */
|
||||
export interface Artifact {
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export {};
|
||||
Vendored
+651
@@ -0,0 +1,651 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "git", defined whole (seats/git/seat.json): The forge: every read and act a delivery part makes of the mesh's git repositories, and what the forge says happened (design 47 *The seat git*, ADR 0596 §1, §2). A failed read answers an error, never an empty answer. The act verbs are the forge bridge's alone.
|
||||
|
||||
export declare const seat: "git";
|
||||
|
||||
export declare const verbs: {
|
||||
readonly pull: "pull";
|
||||
readonly branch: "branch";
|
||||
readonly openPulls: "open-pulls";
|
||||
readonly tags: "tags";
|
||||
readonly trees: "trees";
|
||||
readonly file: "file";
|
||||
readonly contains: "contains";
|
||||
readonly statuses: "statuses";
|
||||
readonly status: "status";
|
||||
readonly comment: "comment";
|
||||
readonly view: "view";
|
||||
readonly note: "note";
|
||||
readonly mergePull: "merge-pull";
|
||||
readonly tag: "tag";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly pullUpdated: "pull-updated";
|
||||
readonly pullMerged: "pull-merged";
|
||||
readonly pullClosed: "pull-closed";
|
||||
readonly forgePull: "forge-pull";
|
||||
readonly forgeStatus: "forge-status";
|
||||
readonly forgeDelete: "forge-delete";
|
||||
readonly repoWritable: "repo-writable";
|
||||
readonly branchMoved: "branch-moved";
|
||||
};
|
||||
|
||||
export declare const family: { readonly name: "git.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export declare const pullUpdatedSubject: "mesh.seat.git.event.pull-updated";
|
||||
|
||||
export declare const pullMergedSubject: "mesh.seat.git.event.pull-merged";
|
||||
|
||||
export declare const pullClosedSubject: "mesh.seat.git.event.pull-closed";
|
||||
|
||||
export declare const forgePullSubject: "mesh.seat.git.event.forge-pull";
|
||||
|
||||
export declare const forgeStatusSubject: "mesh.seat.git.event.forge-status";
|
||||
|
||||
export declare const forgeDeleteSubject: "mesh.seat.git.event.forge-delete";
|
||||
|
||||
export declare const repoWritableSubject: "mesh.seat.git.event.repo-writable";
|
||||
|
||||
export declare const branchMovedStream: "SEAT_git_branch-moved";
|
||||
|
||||
export declare const branchMovedSubject: "mesh.seat.git.event.branch-moved";
|
||||
|
||||
export declare const states: {
|
||||
readonly failedSteps: "failed-steps";
|
||||
};
|
||||
|
||||
/** The key of one value of the state failed-steps under the form "<module>.<fingerprint>.<step>". */
|
||||
export declare function failedStepsByModuleFingerprintStepKey(module: string, fingerprint: string, step: string): string;
|
||||
|
||||
/** The parts of a key of the form "<module>.<fingerprint>.<step>", or undefined for a key of another form. */
|
||||
export declare function parseFailedStepsByModuleFingerprintStepKey(_key: string): { module: string; fingerprint: string; step: string } | undefined;
|
||||
|
||||
/** what a pull request changed */
|
||||
export interface Change {
|
||||
/** the changed directories that hold a module at its head; absent when they could not be read */
|
||||
"module-dirs"?: string[];
|
||||
/** the paths it changed */
|
||||
"paths": string[];
|
||||
/** the forge cut the list */
|
||||
"paths-truncated"?: boolean;
|
||||
/** which of them it deleted */
|
||||
"removed"?: string[];
|
||||
}
|
||||
|
||||
/** which kind of error, set with error alone: refused, the forge or the holder refused and error says why in the forge's own words; not-found, the forge said that what was asked about (a repository, a commit, a pull request, a branch or a tag) does not exist, so a caller never reads it out of error's words; failed, the forge failed or could not be reached, so the act or read could not be performed */
|
||||
export type ErrorKind = "refused" | "not-found" | "failed";
|
||||
|
||||
/** a failed required step at a build-input fingerprint, with the commits it was seen at and the run that failed it (design 47 *Judged from its own state, never by a call*); cleared by a later passing rerun of that step whose proved caller is the operator or a healer */
|
||||
export interface FailedStep {
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact"?: string;
|
||||
"at"?: string;
|
||||
/** every commit it was seen at */
|
||||
"commits": string[];
|
||||
/** the build-input fingerprint the step failed at */
|
||||
"fingerprint": string;
|
||||
"module": string;
|
||||
/** the run that failed it: the runner's pipeline key */
|
||||
"run": string;
|
||||
/** why it failed, as the runner's step-ended said */
|
||||
"said"?: string;
|
||||
"step": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** what the forge would merge now, for an open pull request (issues 1275, 1945; ADR 0441 §1): answered whole or not at all, and a read the forge could not make answers the verb's error, never a guess; absent for a merged or closed one */
|
||||
export interface Merging {
|
||||
/** the forge's own word on whether it merges into its base now: false while it is in conflict with its base, or while the forge works that out after the base moved */
|
||||
"mergeable": boolean;
|
||||
/** whether a protection rule guards its base branch */
|
||||
"protected": boolean;
|
||||
/** the status contexts the base branch's protection requires; none when it requires none */
|
||||
"required": string[];
|
||||
/** whether the forge's merging account may write the repository: false, its statuses and its merge are refused */
|
||||
"writes": boolean;
|
||||
}
|
||||
|
||||
/** an open pull request, with the statuses its base requires and those its head has */
|
||||
export interface OpenPull {
|
||||
/** the head's statuses by context, the newest of each */
|
||||
"checks": Record<string, Status>;
|
||||
"pull": Pull;
|
||||
/** the contexts the base branch's protection requires; none when it requires none */
|
||||
"required": string[];
|
||||
}
|
||||
|
||||
/** one pull request as the forge holds it; never its description (ADR 0659 §1) */
|
||||
export interface Pull {
|
||||
/** who opened it, the forge's login */
|
||||
"author"?: string;
|
||||
/** the branch it merges into */
|
||||
"base": string;
|
||||
/** its head branch: what a delivery group is named by */
|
||||
"branch": string;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"head": string;
|
||||
/** the merge commit, once merged */
|
||||
"merge-commit"?: string;
|
||||
/** when it merged */
|
||||
"merged-at"?: string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** open, merged or closed */
|
||||
"state": "open" | "merged" | "closed";
|
||||
/** its title */
|
||||
"title"?: string;
|
||||
/** its page on the forge */
|
||||
"url"?: string;
|
||||
}
|
||||
|
||||
/** the newest status of one context on a commit */
|
||||
export interface Status {
|
||||
/** when it was set */
|
||||
"at"?: string;
|
||||
/** who set it */
|
||||
"by"?: string;
|
||||
/** the status's context, such as mesh/check */
|
||||
"context": string;
|
||||
/** what it says */
|
||||
"description"?: string;
|
||||
/** pending, success, failure, error or warning */
|
||||
"state": string;
|
||||
/** the page it links to */
|
||||
"target"?: string;
|
||||
}
|
||||
|
||||
/** is what pull takes. */
|
||||
export interface PullInput {
|
||||
/** instead of the number: the merge commit it made */
|
||||
"merge-commit"?: string;
|
||||
/** its number */
|
||||
"number"?: number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what pull answers. */
|
||||
export interface PullAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
"merging"?: Merging;
|
||||
"pull"?: Pull;
|
||||
}
|
||||
|
||||
/** is what branch takes. */
|
||||
export interface BranchInput {
|
||||
"branch": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what branch answers. */
|
||||
export interface BranchAnswer {
|
||||
"branch"?: string;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"head"?: string;
|
||||
/** a protection rule refuses a direct push and admits only merges */
|
||||
"protected"?: boolean;
|
||||
"repository"?: string;
|
||||
}
|
||||
|
||||
/** is what open-pulls takes. */
|
||||
export interface OpenPullsInput {
|
||||
}
|
||||
|
||||
/** is what open-pulls answers. */
|
||||
export interface OpenPullsAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** every open pull request; said empty when none is open, so an answer that lacks it is never read as none */
|
||||
"pulls": OpenPull[];
|
||||
}
|
||||
|
||||
/** is what tags takes. */
|
||||
export interface TagsInput {
|
||||
/** the page, from 1 */
|
||||
"page"?: number;
|
||||
/** only tags starting with it */
|
||||
"prefix"?: string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what tags answers. */
|
||||
export interface TagsAnswer {
|
||||
/** how many tags a page holds */
|
||||
"bound"?: number;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** another page exists */
|
||||
"more"?: boolean;
|
||||
/** the page */
|
||||
"page"?: number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository"?: string;
|
||||
/** the tags of this page */
|
||||
"tags"?: string[];
|
||||
}
|
||||
|
||||
/** is what trees takes. */
|
||||
export interface TreesInput {
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit": string;
|
||||
/** directories whose every blob is answered; the root is the empty name */
|
||||
"files"?: string[];
|
||||
/** {directory: [path relative to it]}; the root is the empty name */
|
||||
"paths"?: Record<string, string[]>;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what trees answers. */
|
||||
export interface TreesAnswer {
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit"?: string;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** directory to {path: blob id} */
|
||||
"files"?: Record<string, Record<string, string>>;
|
||||
/** directory to {path: object id} */
|
||||
"paths"?: Record<string, Record<string, string>>;
|
||||
/** the root tree's hash */
|
||||
"root"?: string;
|
||||
/** directory to its tree's hash, the root as the empty name */
|
||||
"trees"?: Record<string, string>;
|
||||
}
|
||||
|
||||
/** is what file takes. */
|
||||
export interface FileInput {
|
||||
/** the file's path from the repository's root */
|
||||
"path": string;
|
||||
/** a commit, branch or tag; the default branch when absent */
|
||||
"ref"?: string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what file answers. */
|
||||
export interface FileAnswer {
|
||||
/** the forge holds no such file there */
|
||||
"absent"?: boolean;
|
||||
/** the file's git blob id */
|
||||
"blob"?: string;
|
||||
/** its content */
|
||||
"content"?: string;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the path */
|
||||
"path"?: string;
|
||||
/** what was read */
|
||||
"ref"?: string;
|
||||
/** its size in bytes */
|
||||
"size"?: number;
|
||||
}
|
||||
|
||||
/** is what contains takes. */
|
||||
export interface ContainsInput {
|
||||
/** the commit asked about */
|
||||
"commit": string;
|
||||
/** the commit it may be contained in */
|
||||
"in": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what contains answers. */
|
||||
export interface ContainsAnswer {
|
||||
/** how many commits commit is ahead of in */
|
||||
"ahead"?: number;
|
||||
/** the commit */
|
||||
"commit"?: string;
|
||||
/** in contains commit */
|
||||
"contains"?: boolean;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the other */
|
||||
"in"?: string;
|
||||
}
|
||||
|
||||
/** is what statuses takes. */
|
||||
export interface StatusesInput {
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what statuses answers. */
|
||||
export interface StatusesAnswer {
|
||||
/** the forge's combined state */
|
||||
"combined"?: string;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit"?: string;
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the newest of each context */
|
||||
"statuses"?: Status[];
|
||||
}
|
||||
|
||||
/** is what status takes. */
|
||||
export interface StatusInput {
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit": string;
|
||||
/** the context, such as mesh/check */
|
||||
"context": string;
|
||||
/** what it says */
|
||||
"description"?: string;
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** the state */
|
||||
"state": "pending" | "success" | "failure" | "error" | "warning";
|
||||
/** the page it links to */
|
||||
"target"?: string;
|
||||
}
|
||||
|
||||
/** is what status answers. */
|
||||
export interface StatusAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the id was already held on the pull request or the note, so nothing was done again */
|
||||
"held"?: boolean;
|
||||
/** the act's id, as the caller gave it */
|
||||
"id"?: string;
|
||||
/** the forge holds the act now */
|
||||
"performed"?: boolean;
|
||||
}
|
||||
|
||||
/** is what comment takes. */
|
||||
export interface CommentInput {
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** the comment, markdown */
|
||||
"text": string;
|
||||
}
|
||||
|
||||
/** is what comment answers. */
|
||||
export interface CommentAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the id was already held on the pull request or the note, so nothing was done again */
|
||||
"held"?: boolean;
|
||||
/** the act's id, as the caller gave it */
|
||||
"id"?: string;
|
||||
/** the forge holds the act now */
|
||||
"performed"?: boolean;
|
||||
}
|
||||
|
||||
/** is what view takes. */
|
||||
export interface ViewInput {
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** the view, markdown */
|
||||
"text": string;
|
||||
}
|
||||
|
||||
/** is what view answers. */
|
||||
export interface ViewAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the id was already held on the pull request or the note, so nothing was done again */
|
||||
"held"?: boolean;
|
||||
/** the act's id, as the caller gave it */
|
||||
"id"?: string;
|
||||
/** the forge holds the act now */
|
||||
"performed"?: boolean;
|
||||
}
|
||||
|
||||
/** is what note takes. */
|
||||
export interface NoteInput {
|
||||
/** a commit, its full 40-hex sha */
|
||||
"commit": string;
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the line, one line */
|
||||
"line": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what note answers. */
|
||||
export interface NoteAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the id was already held on the pull request or the note, so nothing was done again */
|
||||
"held"?: boolean;
|
||||
/** the act's id, as the caller gave it */
|
||||
"id"?: string;
|
||||
/** the forge holds the act now */
|
||||
"performed"?: boolean;
|
||||
}
|
||||
|
||||
/** is what merge-pull takes. */
|
||||
export interface MergePullInput {
|
||||
/** the head the caller names */
|
||||
"head": string;
|
||||
/** the act's id */
|
||||
"id": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what merge-pull answers. */
|
||||
export interface MergePullAnswer {
|
||||
/** why the forge could not answer, or refused: set alone with error-kind, and a caller reads it as a failure, never as none */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the id was already held on the pull request or the note, so nothing was done again */
|
||||
"held"?: boolean;
|
||||
/** the act's id, as the caller gave it */
|
||||
"id"?: string;
|
||||
/** the merge commit */
|
||||
"merge-commit"?: string;
|
||||
/** for policy-failed, the module */
|
||||
"module"?: string;
|
||||
/** the forge holds the act now */
|
||||
"performed"?: boolean;
|
||||
/** why the forge or the holder refused the merge; the act is not performed */
|
||||
"refused"?: string;
|
||||
/** which refusal, set with refused: head-moved, the pull request's head is not the one named; unprotected, the base branch's protection does not refuse a direct push; policy-failed, a run at the head's fingerprint failed a required step (run, module and step name it); no-registrations, no registration-changed heard yet (ADR 0667 section 10); git-refused, git refused the merge */
|
||||
"refused-kind"?: "head-moved" | "unprotected" | "policy-failed" | "no-registrations" | "git-refused";
|
||||
/** for policy-failed, the run that failed the step: the runner's pipeline key */
|
||||
"run"?: string;
|
||||
/** for policy-failed, the step */
|
||||
"step"?: string;
|
||||
}
|
||||
|
||||
/** is what tag takes. */
|
||||
export interface TagInput {
|
||||
/** the commit it is written at */
|
||||
"commit": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** the tag */
|
||||
"tag": string;
|
||||
}
|
||||
|
||||
/** is what tag answers. */
|
||||
export interface TagAnswer {
|
||||
/** why the forge could not write it: set alone with error-kind */
|
||||
"error"?: string;
|
||||
"error-kind"?: ErrorKind;
|
||||
/** the forge holds the tag at that commit now */
|
||||
"performed"?: boolean;
|
||||
/** the tag, as asked */
|
||||
"tag"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event pull-updated. */
|
||||
export interface PullUpdatedEvent {
|
||||
/** who opened it */
|
||||
"author"?: string;
|
||||
/** the branch it merges into */
|
||||
"base": string;
|
||||
/** the base branch's head as the head was announced; absent when it could not be read */
|
||||
"base-head"?: string;
|
||||
/** its head branch */
|
||||
"branch": string;
|
||||
"change"?: Change;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"head": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** its title */
|
||||
"title"?: string;
|
||||
/** its page */
|
||||
"url"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event pull-merged. */
|
||||
export interface PullMergedEvent {
|
||||
/** who opened it */
|
||||
"author"?: string;
|
||||
/** the branch it merges into */
|
||||
"base": string;
|
||||
/** its head branch */
|
||||
"branch": string;
|
||||
"change"?: Change;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"head": string;
|
||||
/** the head's statuses by context, their states; absent when they could not be read */
|
||||
"head-checks"?: Record<string, string>;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"merge-commit": string;
|
||||
/** when */
|
||||
"merged-at"?: string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** its title */
|
||||
"title"?: string;
|
||||
/** its page */
|
||||
"url"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event pull-closed. */
|
||||
export interface PullClosedEvent {
|
||||
/** who opened it */
|
||||
"author"?: string;
|
||||
/** the branch it merges into */
|
||||
"base": string;
|
||||
/** its head branch */
|
||||
"branch": string;
|
||||
/** a commit, its full 40-hex sha */
|
||||
"head": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** its title */
|
||||
"title"?: string;
|
||||
/** its page */
|
||||
"url"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event forge-pull. */
|
||||
export interface ForgePullEvent {
|
||||
/** what the forge said: opened, reopened, synchronized, edited, closed, merged */
|
||||
"action": string;
|
||||
/** who opened it */
|
||||
"author"?: string;
|
||||
/** its base branch */
|
||||
"base"?: string;
|
||||
/** its head branch */
|
||||
"branch"?: string;
|
||||
/** its head commit */
|
||||
"head"?: string;
|
||||
/** the merge commit */
|
||||
"merge-commit"?: string;
|
||||
/** merged */
|
||||
"merged"?: boolean;
|
||||
/** its number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** who acted */
|
||||
"sender"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event forge-status. */
|
||||
export interface ForgeStatusEvent {
|
||||
/** the commit */
|
||||
"commit": string;
|
||||
/** the context */
|
||||
"context": string;
|
||||
/** what it says */
|
||||
"description"?: string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** who set it */
|
||||
"sender"?: string;
|
||||
/** the state */
|
||||
"state": string;
|
||||
}
|
||||
|
||||
/** is the body of the event forge-delete. */
|
||||
export interface ForgeDeleteEvent {
|
||||
/** the deleted branch or tag */
|
||||
"ref": string;
|
||||
/** branch or tag */
|
||||
"ref-type"?: string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** who deleted it */
|
||||
"sender"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event repo-writable. */
|
||||
export interface RepoWritableEvent {
|
||||
/** the account that writes it now */
|
||||
"account": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is the body of the event branch-moved. */
|
||||
export interface BranchMovedEvent {
|
||||
"at"?: string;
|
||||
"branch": string;
|
||||
/** the head the webhook said, a commit's full 40-hex sha; read again by branch */
|
||||
"head"?: string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is one value of the state failed-steps under the key <module>.<fingerprint>.<step>. */
|
||||
export type FailedStepsByModuleFingerprintStepValue = FailedStep;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "git", defined whole (seats/git/seat.json): The forge: every read and act a delivery part makes of the mesh's git repositories, and what the forge says happened (design 47 *The seat git*, ADR 0596 §1, §2). A failed read answers an error, never an empty answer. The act verbs are the forge bridge's alone.
|
||||
|
||||
export const seat = "git";
|
||||
|
||||
export const verbs = {
|
||||
pull: "pull",
|
||||
branch: "branch",
|
||||
openPulls: "open-pulls",
|
||||
tags: "tags",
|
||||
trees: "trees",
|
||||
file: "file",
|
||||
contains: "contains",
|
||||
statuses: "statuses",
|
||||
status: "status",
|
||||
comment: "comment",
|
||||
view: "view",
|
||||
note: "note",
|
||||
mergePull: "merge-pull",
|
||||
tag: "tag",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
pullUpdated: "pull-updated",
|
||||
pullMerged: "pull-merged",
|
||||
pullClosed: "pull-closed",
|
||||
forgePull: "forge-pull",
|
||||
forgeStatus: "forge-status",
|
||||
forgeDelete: "forge-delete",
|
||||
repoWritable: "repo-writable",
|
||||
branchMoved: "branch-moved",
|
||||
};
|
||||
|
||||
export const family = { name: "git.events", maxAgeDays: 7 };
|
||||
|
||||
export const pullUpdatedSubject = "mesh.seat.git.event.pull-updated";
|
||||
|
||||
export const pullMergedSubject = "mesh.seat.git.event.pull-merged";
|
||||
|
||||
export const pullClosedSubject = "mesh.seat.git.event.pull-closed";
|
||||
|
||||
export const forgePullSubject = "mesh.seat.git.event.forge-pull";
|
||||
|
||||
export const forgeStatusSubject = "mesh.seat.git.event.forge-status";
|
||||
|
||||
export const forgeDeleteSubject = "mesh.seat.git.event.forge-delete";
|
||||
|
||||
export const repoWritableSubject = "mesh.seat.git.event.repo-writable";
|
||||
|
||||
export const branchMovedStream = "SEAT_git_branch-moved";
|
||||
|
||||
export const branchMovedSubject = "mesh.seat.git.event.branch-moved";
|
||||
|
||||
export const states = {
|
||||
failedSteps: "failed-steps",
|
||||
};
|
||||
|
||||
/** The key of one value of the state failed-steps under the form "<module>.<fingerprint>.<step>". */
|
||||
export function failedStepsByModuleFingerprintStepKey(module, fingerprint, step) {
|
||||
return module + "." + fingerprint + "." + step;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<fingerprint>.<step>", or undefined for a key of another form. */
|
||||
export function parseFailedStepsByModuleFingerprintStepKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const fingerprint = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const step = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, fingerprint, step };
|
||||
}
|
||||
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-git",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-git",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat git, generated from its definition.",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-git",
|
||||
"type": "module",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
Vendored
+18
-18
@@ -4,31 +4,31 @@
|
||||
|
||||
import type * as registry from "./parts/registry.js";
|
||||
|
||||
export const seat = "go-package-registry";
|
||||
export declare const seat: "go-package-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
export const family = { name: "go-package-registry.events", maxAgeDays: 7 } as const;
|
||||
export declare const family: { readonly name: "go-package-registry.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.go-package-registry.event.published";
|
||||
export declare const publishedSubject: "mesh.seat.go-package-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.go-package-registry.event.refused";
|
||||
export declare const refusedSubject: "mesh.seat.go-package-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.go-package-registry.event.removed";
|
||||
export declare const removedSubject: "mesh.seat.go-package-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.go-package-registry.event.kept";
|
||||
export declare const keptSubject: "mesh.seat.go-package-registry.event.kept";
|
||||
|
||||
export type Artifact = registry.Artifact;
|
||||
export type KeptEvent = registry.KeptEvent;
|
||||
@@ -0,0 +1,30 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "go-package-registry", defined whole (seats/go-package-registry/seat.json): The mesh's Go modules: Go's module proxy protocol's read side, and publishing over the bus.
|
||||
|
||||
export const seat = "go-package-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export const family = { name: "go-package-registry.events", maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.go-package-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.go-package-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.go-package-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.go-package-registry.event.kept";
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat go-package-registry, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-go-package-registry",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+12
-12
@@ -2,19 +2,19 @@
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
/** one published thing, as every registry event and answer names it */
|
||||
export interface Artifact {
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export {};
|
||||
Vendored
+13
-13
@@ -2,23 +2,23 @@
|
||||
|
||||
// The contract of the seat "mesh-artifact-sweep", defined whole (seats/mesh-artifact-sweep/seat.json): no description.
|
||||
|
||||
export const seat = "mesh-artifact-sweep";
|
||||
export declare const seat: "mesh-artifact-sweep";
|
||||
|
||||
export const verbs = {
|
||||
artifacts: "artifacts",
|
||||
held: "held",
|
||||
collect: "collect",
|
||||
mirrors: "mirrors",
|
||||
images: "images",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly artifacts: "artifacts";
|
||||
readonly held: "held";
|
||||
readonly collect: "collect";
|
||||
readonly mirrors: "mirrors";
|
||||
readonly images: "images";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
artifactsGone: "artifacts-gone",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly artifactsGone: "artifacts-gone";
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-artifact-sweep.events", maxAgeDays: 7 } as const;
|
||||
export declare const family: { readonly name: "mesh-artifact-sweep.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const artifactsGoneSubject = "mesh.seat.mesh-artifact-sweep.event.artifacts-gone";
|
||||
export declare const artifactsGoneSubject: "mesh.seat.mesh-artifact-sweep.event.artifacts-gone";
|
||||
|
||||
/** the body of artifacts-gone */
|
||||
export interface ArtifactsGone {
|
||||
@@ -0,0 +1,22 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-artifact-sweep", defined whole (seats/mesh-artifact-sweep/seat.json): no description.
|
||||
|
||||
export const seat = "mesh-artifact-sweep";
|
||||
|
||||
export const verbs = {
|
||||
artifacts: "artifacts",
|
||||
held: "held",
|
||||
collect: "collect",
|
||||
mirrors: "mirrors",
|
||||
images: "images",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
artifactsGone: "artifacts-gone",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-artifact-sweep.events", maxAgeDays: 7 };
|
||||
|
||||
export const artifactsGoneSubject = "mesh.seat.mesh-artifact-sweep.event.artifacts-gone";
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-artifact-sweep, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-artifact-sweep",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-builds", defined whole (seats/mesh-builds/seat.json): The builder's seat: it says each artifact it published and each agreed toolchain, and answers a module's reserved version. Held once for the mesh (design 47 G section 52, section 307).
|
||||
|
||||
export declare const seat: "mesh-builds";
|
||||
|
||||
export declare const verbs: {
|
||||
readonly reserved: "reserved";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly packagePublished: "package-published";
|
||||
readonly toolchainAgreed: "toolchain-agreed";
|
||||
};
|
||||
|
||||
export declare const family: { readonly name: "mesh-builds.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export declare const packagePublishedStream: "SEAT_mesh-builds_package-published";
|
||||
|
||||
export declare const packagePublishedSubject: "mesh.seat.mesh-builds.event.package-published";
|
||||
|
||||
export declare const toolchainAgreedStream: "SEAT_mesh-builds_toolchain-agreed";
|
||||
|
||||
export declare const toolchainAgreedSubject: "mesh.seat.mesh-builds.event.toolchain-agreed";
|
||||
|
||||
/** a dependency the build resolved, named by the build module in its step key and carried by the builder (design 47 G section 374) */
|
||||
export interface Dependency {
|
||||
/** the dependency's artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
/** the digest of the part, as the build used it */
|
||||
"digest": string;
|
||||
/** 1 an imported package, 3 the build toolchain (design 47 G section 374) */
|
||||
"kind": number;
|
||||
/** the version of the dependency the build resolved */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** one artifact published at the module's reserved version (design 47 G section 52, section 334) */
|
||||
export interface PackagePublished {
|
||||
/** the package's artifact reference, <module>:<artifact>, from the catalog entry */
|
||||
"artifact": string;
|
||||
"at"?: string;
|
||||
/** the watched branch the build was made from */
|
||||
"branch": string;
|
||||
/** each dependency the build resolved, with its version and digest */
|
||||
"dependencies"?: Dependency[];
|
||||
/** the published artifact's digest */
|
||||
"digest": string;
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the source revision of that branch the build was made from */
|
||||
"source": number;
|
||||
"v": number;
|
||||
/** the version the build reserved, MAJOR.MINOR.PATCH */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** the agreed toolchain of a language changed (design 47 G section 376, ADR 0584 section 1) */
|
||||
export interface ToolchainAgreed {
|
||||
"at"?: string;
|
||||
/** the toolchain part's digest */
|
||||
"digest": string;
|
||||
/** the language whose agreed toolchain changed */
|
||||
"language": string;
|
||||
"v": number;
|
||||
/** the agreed toolchain's version */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what reserved takes. */
|
||||
export interface ReservedInput {
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the version, when asked for a particular one */
|
||||
"version"?: string;
|
||||
}
|
||||
|
||||
export interface ReservedAnswerArtifactsItem {
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
/** its digest once built; empty before */
|
||||
"digest"?: string;
|
||||
}
|
||||
|
||||
/** is what reserved answers. */
|
||||
export interface ReservedAnswer {
|
||||
"artifacts": ReservedAnswerArtifactsItem[];
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the reserved version, MAJOR.MINOR.PATCH */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is the body of the event package-published. */
|
||||
export type PackagePublishedEvent = PackagePublished;
|
||||
|
||||
/** is the body of the event toolchain-agreed. */
|
||||
export type ToolchainAgreedEvent = ToolchainAgreed;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-builds", defined whole (seats/mesh-builds/seat.json): The builder's seat: it says each artifact it published and each agreed toolchain, and answers a module's reserved version. Held once for the mesh (design 47 G section 52, section 307).
|
||||
|
||||
export const seat = "mesh-builds";
|
||||
|
||||
export const verbs = {
|
||||
reserved: "reserved",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
packagePublished: "package-published",
|
||||
toolchainAgreed: "toolchain-agreed",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-builds.events", maxAgeDays: 7 };
|
||||
|
||||
export const packagePublishedStream = "SEAT_mesh-builds_package-published";
|
||||
|
||||
export const packagePublishedSubject = "mesh.seat.mesh-builds.event.package-published";
|
||||
|
||||
export const toolchainAgreedStream = "SEAT_mesh-builds_toolchain-agreed";
|
||||
|
||||
export const toolchainAgreedSubject = "mesh.seat.mesh-builds.event.toolchain-agreed";
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-builds",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-builds",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-builds, generated from its definition.",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-builds",
|
||||
"type": "module",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
+1095
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,359 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-catalog", defined whole (seats/mesh-catalog/seat.json): The catalog of the mesh: every module the trunk holds with its manifest, fingerprint and verdict, the packages published, and the seat list (ADR 0636 §1, §4).
|
||||
|
||||
export const seat = "mesh-catalog";
|
||||
|
||||
export const verbs = {
|
||||
modules: "modules",
|
||||
module: "module",
|
||||
provides: "provides",
|
||||
dependents: "dependents",
|
||||
seatDefinitions: "seat-definitions",
|
||||
revision: "revision",
|
||||
registrations: "registrations",
|
||||
register: "register",
|
||||
policy: "policy",
|
||||
watch: "watch",
|
||||
unwatch: "unwatch",
|
||||
versions: "versions",
|
||||
outdated: "outdated",
|
||||
input: "input",
|
||||
entry: "entry",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
seatDefinitionChanged: "seat-definition-changed",
|
||||
seatDefinitionRemoved: "seat-definition-removed",
|
||||
manifestAccepted: "manifest-accepted",
|
||||
manifestRefused: "manifest-refused",
|
||||
catalogRevision: "catalog-revision",
|
||||
filling: "filling",
|
||||
full: "full",
|
||||
room: "room",
|
||||
registrationChanged: "registration-changed",
|
||||
versionReleased: "version-released",
|
||||
versionsFilled: "versions-filled",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-catalog.events", maxAgeDays: 7 };
|
||||
|
||||
export const seatDefinitionChangedSubject = "mesh.seat.mesh-catalog.event.seat-definition-changed";
|
||||
|
||||
export const seatDefinitionRemovedSubject = "mesh.seat.mesh-catalog.event.seat-definition-removed";
|
||||
|
||||
export const manifestAcceptedSubject = "mesh.seat.mesh-catalog.event.manifest-accepted";
|
||||
|
||||
export const manifestRefusedSubject = "mesh.seat.mesh-catalog.event.manifest-refused";
|
||||
|
||||
export function catalogRevisionSubject(branch) {
|
||||
return "mesh.seat.mesh-catalog.event.catalog-revision." + branch;
|
||||
}
|
||||
|
||||
export const catalogRevisionSubjectAll = "mesh.seat.mesh-catalog.event.catalog-revision.*";
|
||||
|
||||
export const fillingSubject = "mesh.seat.mesh-catalog.event.filling";
|
||||
|
||||
export const fullSubject = "mesh.seat.mesh-catalog.event.full";
|
||||
|
||||
export const roomSubject = "mesh.seat.mesh-catalog.event.room";
|
||||
|
||||
export const registrationChangedStream = "SEAT_mesh-catalog_registration-changed";
|
||||
|
||||
export const registrationChangedSubject = "mesh.seat.mesh-catalog.event.registration-changed";
|
||||
|
||||
export const versionReleasedStream = "SEAT_mesh-catalog_version-released";
|
||||
|
||||
export const versionReleasedSubject = "mesh.seat.mesh-catalog.event.version-released";
|
||||
|
||||
export const versionsFilledStream = "SEAT_mesh-catalog_versions-filled";
|
||||
|
||||
export const versionsFilledSubject = "mesh.seat.mesh-catalog.event.versions-filled";
|
||||
|
||||
export const states = {
|
||||
manifests: "manifests",
|
||||
modules: "modules",
|
||||
candidates: "candidates",
|
||||
verdicts: "verdicts",
|
||||
predefined: "predefined",
|
||||
configCandidates: "config-candidates",
|
||||
packages: "packages",
|
||||
catalogRevisions: "catalog-revisions",
|
||||
registrations: "registrations",
|
||||
registrationHistory: "registration-history",
|
||||
versions: "versions",
|
||||
buildEdges: "build-edges",
|
||||
inputs: "inputs",
|
||||
};
|
||||
|
||||
/** The key of one value of the state manifests under the form "<digest>". */
|
||||
export function manifestsByDigestKey(digest) {
|
||||
return digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<digest>", or undefined for a key of another form. */
|
||||
export function parseManifestsByDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state modules under the form "<module>". */
|
||||
export function modulesByModuleKey(module) {
|
||||
return module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>", or undefined for a key of another form. */
|
||||
export function parseModulesByModuleKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state candidates under the form "<group>". */
|
||||
export function candidatesByGroupKey(group) {
|
||||
return group;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>", or undefined for a key of another form. */
|
||||
export function parseCandidatesByGroupKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const group = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group };
|
||||
}
|
||||
|
||||
/** The key of one value of the state verdicts under the form "<digest>". */
|
||||
export function verdictsByDigestKey(digest) {
|
||||
return digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<digest>", or undefined for a key of another form. */
|
||||
export function parseVerdictsByDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state predefined under the form "list". */
|
||||
export function predefinedByListKey() {
|
||||
return "list";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "list", or undefined for a key of another form. */
|
||||
export function parsePredefinedByListKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("list")) return undefined;
|
||||
_rest = _rest.slice(4);
|
||||
if (_rest !== "") return undefined;
|
||||
return { };
|
||||
}
|
||||
|
||||
/** The key of one value of the state config-candidates under the form "<pull>". */
|
||||
export function configCandidatesByPullKey(pull) {
|
||||
return pull;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<pull>", or undefined for a key of another form. */
|
||||
export function parseConfigCandidatesByPullKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const pull = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { pull };
|
||||
}
|
||||
|
||||
/** The key of one value of the state packages under the form "<module>". */
|
||||
export function packagesByModuleKey(module) {
|
||||
return module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>", or undefined for a key of another form. */
|
||||
export function parsePackagesByModuleKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state packages under the form "<package>.<series>". */
|
||||
export function packagesByPackageSeriesKey(packagePart, series) {
|
||||
return packagePart + "." + series;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<package>.<series>", or undefined for a key of another form. */
|
||||
export function parsePackagesByPackageSeriesKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const packagePart = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const series = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { packagePart, series };
|
||||
}
|
||||
|
||||
/** The key of one value of the state catalog-revisions under the form "<branch>.<revision>". */
|
||||
export function catalogRevisionsByBranchRevisionKey(branch, revision) {
|
||||
return branch + "." + revision;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<branch>.<revision>", or undefined for a key of another form. */
|
||||
export function parseCatalogRevisionsByBranchRevisionKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const branch = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const revision = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { branch, revision };
|
||||
}
|
||||
|
||||
/** The key of one value of the state catalog-revisions under the form "candidate.<group>.<heads>". */
|
||||
export function catalogRevisionsByCandidateGroupHeadsKey(group, heads) {
|
||||
return "candidate." + group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "candidate.<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseCatalogRevisionsByCandidateGroupHeadsKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("candidate.")) return undefined;
|
||||
_rest = _rest.slice(10);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** The key of one value of the state catalog-revisions under the form "entry.<digest>". */
|
||||
export function catalogRevisionsByEntryDigestKey(digest) {
|
||||
return "entry." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "entry.<digest>", or undefined for a key of another form. */
|
||||
export function parseCatalogRevisionsByEntryDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("entry.")) return undefined;
|
||||
_rest = _rest.slice(6);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state registrations under the form "<module>". */
|
||||
export function registrationsByModuleKey(module) {
|
||||
return module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>", or undefined for a key of another form. */
|
||||
export function parseRegistrationsByModuleKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state registration-history under the form "<module>.<version>". */
|
||||
export function registrationHistoryByModuleVersionKey(module, version) {
|
||||
return module + "." + version;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<version>", or undefined for a key of another form. */
|
||||
export function parseRegistrationHistoryByModuleVersionKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const version = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, version };
|
||||
}
|
||||
|
||||
/** The key of one value of the state versions under the form "<module>.<version>". */
|
||||
export function versionsByModuleVersionKey(module, version) {
|
||||
return module + "." + version;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<version>", or undefined for a key of another form. */
|
||||
export function parseVersionsByModuleVersionKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const version = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, version };
|
||||
}
|
||||
|
||||
/** The key of one value of the state build-edges under the form "<module>.<branch>". */
|
||||
export function buildEdgesByModuleBranchKey(module, branch) {
|
||||
return module + "." + branch;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<branch>", or undefined for a key of another form. */
|
||||
export function parseBuildEdgesByModuleBranchKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const branch = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, branch };
|
||||
}
|
||||
|
||||
/** The key of one value of the state inputs under the form "<time>.<digest>". */
|
||||
export function inputsByTimeDigestKey(time, digest) {
|
||||
return time + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<time>.<digest>", or undefined for a key of another form. */
|
||||
export function parseInputsByTimeDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const time = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { time, digest };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-catalog, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-catalog",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
@@ -1,545 +0,0 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-catalog", defined whole (seats/mesh-catalog/seat.json): The catalog of the mesh: every module the trunk holds with its manifest, fingerprint and verdict, the packages published, and the seat list (ADR 0636 §1, §4).
|
||||
|
||||
export const seat = "mesh-catalog";
|
||||
|
||||
export const verbs = {
|
||||
modules: "modules",
|
||||
module: "module",
|
||||
provides: "provides",
|
||||
dependents: "dependents",
|
||||
seatDefinitions: "seat-definitions",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
seatDefinitionChanged: "seat-definition-changed",
|
||||
seatDefinitionRemoved: "seat-definition-removed",
|
||||
manifestAccepted: "manifest-accepted",
|
||||
manifestRefused: "manifest-refused",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-catalog.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const seatDefinitionChangedSubject = "mesh.seat.mesh-catalog.event.seat-definition-changed";
|
||||
|
||||
export const seatDefinitionRemovedSubject = "mesh.seat.mesh-catalog.event.seat-definition-removed";
|
||||
|
||||
export const manifestAcceptedSubject = "mesh.seat.mesh-catalog.event.manifest-accepted";
|
||||
|
||||
export const manifestRefusedSubject = "mesh.seat.mesh-catalog.event.manifest-refused";
|
||||
|
||||
export const states = {
|
||||
manifests: "manifests",
|
||||
modules: "modules",
|
||||
candidates: "candidates",
|
||||
verdicts: "verdicts",
|
||||
predefined: "predefined",
|
||||
configCandidates: "config-candidates",
|
||||
packages: "packages",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state manifests under the form "<digest>". */
|
||||
export function manifestsByDigestKey(digest: string): string {
|
||||
return digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<digest>", or undefined for a key of another form. */
|
||||
export function parseManifestsByDigestKey(_key: string): { digest: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state modules under the form "<module>". */
|
||||
export function modulesByModuleKey(module: string): string {
|
||||
return module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>", or undefined for a key of another form. */
|
||||
export function parseModulesByModuleKey(_key: string): { module: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state candidates under the form "<group>". */
|
||||
export function candidatesByGroupKey(group: string): string {
|
||||
return group;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>", or undefined for a key of another form. */
|
||||
export function parseCandidatesByGroupKey(_key: string): { group: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const group = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group };
|
||||
}
|
||||
|
||||
/** The key of one value of the state verdicts under the form "<digest>". */
|
||||
export function verdictsByDigestKey(digest: string): string {
|
||||
return digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<digest>", or undefined for a key of another form. */
|
||||
export function parseVerdictsByDigestKey(_key: string): { digest: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state predefined under the form "list". */
|
||||
export function predefinedByListKey(): string {
|
||||
return "list";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "list", or undefined for a key of another form. */
|
||||
export function parsePredefinedByListKey(_key: string): { } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("list")) return undefined;
|
||||
_rest = _rest.slice(4);
|
||||
if (_rest !== "") return undefined;
|
||||
return { };
|
||||
}
|
||||
|
||||
/** The key of one value of the state config-candidates under the form "<pull>". */
|
||||
export function configCandidatesByPullKey(pull: string): string {
|
||||
return pull;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<pull>", or undefined for a key of another form. */
|
||||
export function parseConfigCandidatesByPullKey(_key: string): { pull: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const pull = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { pull };
|
||||
}
|
||||
|
||||
/** The key of one value of the state packages under the form "<module>". */
|
||||
export function packagesByModuleKey(module: string): string {
|
||||
return module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>", or undefined for a key of another form. */
|
||||
export function parsePackagesByModuleKey(_key: string): { module: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state packages under the form "<package>.<series>". */
|
||||
export function packagesByPackageSeriesKey(packagePart: string, series: string): string {
|
||||
return packagePart + "." + series;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<package>.<series>", or undefined for a key of another form. */
|
||||
export function parsePackagesByPackageSeriesKey(_key: string): { packagePart: string; series: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const packagePart = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const series = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { packagePart, series };
|
||||
}
|
||||
|
||||
/** a toolchain a fingerprint was computed with (ADR 0405 clause 7) */
|
||||
export interface ToolchainUsed {
|
||||
"language": string;
|
||||
/** the build module's recipe version */
|
||||
"recipe": string;
|
||||
/** the installed toolchain's version */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what modules takes. */
|
||||
export interface ModulesInput {
|
||||
}
|
||||
|
||||
export interface ModulesAnswerModulesItem {
|
||||
/** the merge commit it was last changed at */
|
||||
"commit": string;
|
||||
/** its fingerprint (src2: and 64 hex digits); absent when it has none */
|
||||
"fp"?: string;
|
||||
"module": string;
|
||||
/** why it has none */
|
||||
"none"?: string;
|
||||
/** the module's directory in its repository, '.' for a root */
|
||||
"path"?: string;
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what modules answers. */
|
||||
export interface ModulesAnswer {
|
||||
"modules": ModulesAnswerModulesItem[];
|
||||
}
|
||||
|
||||
/** is what module takes. */
|
||||
export interface ModuleInput {
|
||||
/** the module's name */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
export interface ModuleAnswerModule {
|
||||
/** the merge commit it was last changed at */
|
||||
"commit": string;
|
||||
/** its fingerprint (src2: and 64 hex digits); absent when it has none */
|
||||
"fp"?: string;
|
||||
/** the module's manifest as the trunk holds it */
|
||||
"manifest"?: Record<string, unknown>;
|
||||
"module": string;
|
||||
/** why it has none */
|
||||
"none"?: string;
|
||||
/** the module's directory in its repository, '.' for a root */
|
||||
"path"?: string;
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what module answers. */
|
||||
export interface ModuleAnswer {
|
||||
"module": ModuleAnswerModule;
|
||||
}
|
||||
|
||||
/** is what provides takes. */
|
||||
export interface ProvidesInput {
|
||||
/** the provision, such as postgres-database */
|
||||
"provision": string;
|
||||
}
|
||||
|
||||
/** is what provides answers. */
|
||||
export type ProvidesAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what dependents takes. */
|
||||
export interface DependentsInput {
|
||||
/** the module's name */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what dependents answers. */
|
||||
export type DependentsAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what seat-definitions takes. */
|
||||
export interface SeatDefinitionsInput {
|
||||
/** the seat's name; none lists every trunk seat */
|
||||
"seat"?: string;
|
||||
}
|
||||
|
||||
export interface SeatDefinitionsAnswerEntry {
|
||||
/** the definition, resolved with the parts it includes */
|
||||
"definition"?: Record<string, unknown>;
|
||||
"digest": string;
|
||||
"seat": string;
|
||||
/** trunk */
|
||||
"source": string;
|
||||
/** why the definition could not be read, when it could not */
|
||||
"unparsed"?: string;
|
||||
}
|
||||
|
||||
export interface SeatDefinitionsAnswerSeatsItem {
|
||||
"digest": string;
|
||||
"seat": string;
|
||||
/** trunk */
|
||||
"source": string;
|
||||
}
|
||||
|
||||
/** is what seat-definitions answers. */
|
||||
export interface SeatDefinitionsAnswer {
|
||||
"entry"?: SeatDefinitionsAnswerEntry;
|
||||
"found"?: boolean;
|
||||
"revision"?: number;
|
||||
"seat"?: string;
|
||||
"seats"?: SeatDefinitionsAnswerSeatsItem[];
|
||||
}
|
||||
|
||||
/** is the body of the event seat-definition-changed. */
|
||||
export interface SeatDefinitionChangedEvent {
|
||||
"digest": string;
|
||||
"seat": string;
|
||||
/** trunk */
|
||||
"source": string;
|
||||
}
|
||||
|
||||
/** is the body of the event seat-definition-removed. */
|
||||
export interface SeatDefinitionRemovedEvent {
|
||||
"seat": string;
|
||||
}
|
||||
|
||||
export interface ManifestAcceptedEventBusStateItem {
|
||||
"configuration"?: Record<string, unknown>;
|
||||
"name": string;
|
||||
"options"?: Record<string, unknown>;
|
||||
"storage": string;
|
||||
"template"?: string;
|
||||
"types"?: Record<string, unknown>[];
|
||||
}
|
||||
|
||||
/** is the body of the event manifest-accepted. */
|
||||
export interface ManifestAcceptedEvent {
|
||||
"bus-state": ManifestAcceptedEventBusStateItem[];
|
||||
"digest": string;
|
||||
"judge": string;
|
||||
"module": string;
|
||||
/** the indexer's revision of the verdict it says; a reader asks its first view again on a gap in it; zero from an indexer that does not say it */
|
||||
"revision"?: number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is the body of the event manifest-refused. */
|
||||
export interface ManifestRefusedEvent {
|
||||
"digest": string;
|
||||
"judge": string;
|
||||
"module": string;
|
||||
"problems": string[];
|
||||
/** the indexer's revision of the verdict it says; a reader asks its first view again on a gap in it; zero from an indexer that does not say it */
|
||||
"revision"?: number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is one value of the state manifests under the key <digest>. */
|
||||
export interface ManifestsByDigestValue {
|
||||
/** the manifest, UTF-8 JSON text */
|
||||
"manifest": string;
|
||||
"module": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface ModulesByModuleValueInputs2 {
|
||||
"bases"?: string[];
|
||||
"builder"?: string;
|
||||
"contexts"?: Record<string, string>;
|
||||
"import-form"?: string;
|
||||
"imports"?: string[];
|
||||
"locks"?: Record<string, string>;
|
||||
"packages"?: string[];
|
||||
"paths"?: Record<string, string>;
|
||||
"tree": string;
|
||||
}
|
||||
|
||||
/** is one value of the state modules under the key <module>. */
|
||||
export interface ModulesByModuleValue {
|
||||
"commit": string;
|
||||
/** the old-form fingerprint */
|
||||
"fp"?: string;
|
||||
"fp-src"?: number;
|
||||
/** src2: fingerprint */
|
||||
"fp2"?: string;
|
||||
"inputs2"?: ModulesByModuleValueInputs2;
|
||||
/** manifest digest */
|
||||
"manifest"?: string;
|
||||
"needs"?: string[];
|
||||
"none"?: string;
|
||||
/** why it has none */
|
||||
"none2"?: string;
|
||||
"packages"?: Record<string, string>;
|
||||
"path"?: string;
|
||||
"paths"?: Record<string, string[]>;
|
||||
"problems"?: string[];
|
||||
"repository": string;
|
||||
/** the source revision */
|
||||
"src"?: number;
|
||||
/** by language: the toolchain FP2 was computed with */
|
||||
"toolchains"?: Record<string, ToolchainUsed>;
|
||||
"unknown"?: string[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"verdict"?: string;
|
||||
"warnings"?: string[];
|
||||
}
|
||||
|
||||
export interface CandidatesByGroupValuePullsItemFpsValue {
|
||||
"fp2"?: string;
|
||||
"manifest"?: string;
|
||||
"none2"?: string;
|
||||
"packages"?: Record<string, string>;
|
||||
"paths"?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface CandidatesByGroupValuePullsItem {
|
||||
"fps"?: Record<string, CandidatesByGroupValuePullsItemFpsValue>;
|
||||
"head": string;
|
||||
"modules": string[];
|
||||
"number": number;
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is one value of the state candidates under the key <group>. */
|
||||
export interface CandidatesByGroupValue {
|
||||
/** the source revision it is read on */
|
||||
"base": number;
|
||||
"fpset"?: string;
|
||||
"group": string;
|
||||
"heads": string;
|
||||
"pulls": CandidatesByGroupValuePullsItem[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state verdicts under the key <digest>. */
|
||||
export interface VerdictsByDigestValue {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"judge"?: string;
|
||||
"module": string;
|
||||
"problems"?: string[];
|
||||
"state": string;
|
||||
"unknown"?: string[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"warnings"?: string[];
|
||||
}
|
||||
|
||||
/** is one value of the state predefined under the key list. */
|
||||
export interface PredefinedByListValue {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"commit": string;
|
||||
/** the foundation's predefined list as kept */
|
||||
"list": unknown;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface ConfigCandidatesByPullValueDeclaresValueValue {
|
||||
/** the default */
|
||||
"default": unknown;
|
||||
"description"?: string;
|
||||
/** the allowed values */
|
||||
"enum"?: unknown;
|
||||
"kind": string;
|
||||
/** a declared bound; 0 is a bound, absent is none */
|
||||
"maximum"?: number | null;
|
||||
/** a declared bound; 0 is a bound, absent is none */
|
||||
"minimum"?: number | null;
|
||||
"pattern"?: string;
|
||||
"predefined"?: string;
|
||||
"required"?: boolean;
|
||||
"runtime"?: boolean;
|
||||
"trusted"?: boolean;
|
||||
"type"?: string;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is one value of the state config-candidates under the key <pull>. */
|
||||
export interface ConfigCandidatesByPullValue {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
/** module to key to declaration */
|
||||
"declares": Record<string, Record<string, ConfigCandidatesByPullValueDeclaresValueValue>>;
|
||||
"head": string;
|
||||
"pull": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface PackagesByModuleValuePackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
/** is one value of the state packages under the key <module>. */
|
||||
export interface PackagesByModuleValue {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"commit": string;
|
||||
"dir"?: string;
|
||||
/** the Go module path */
|
||||
"module": string;
|
||||
"packages": PackagesByModuleValuePackagesItem[];
|
||||
"repository": string;
|
||||
/** digest of go.mod and go.sum */
|
||||
"requires"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNewestContentsPackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNewestContents {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"commit": string;
|
||||
"dir"?: string;
|
||||
/** the Go module path */
|
||||
"module": string;
|
||||
"packages": PackagesByPackageSeriesValueNewestContentsPackagesItem[];
|
||||
"repository": string;
|
||||
/** digest of go.mod and go.sum */
|
||||
"requires"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNewest {
|
||||
"commit"?: string;
|
||||
"contents"?: PackagesByPackageSeriesValueNewestContents;
|
||||
"digest"?: string;
|
||||
"fingerprint"?: string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNumberedContentsPackagesItem {
|
||||
"digest": string;
|
||||
"package": string;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNumberedContents {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"commit": string;
|
||||
"dir"?: string;
|
||||
/** the Go module path */
|
||||
"module": string;
|
||||
"packages": PackagesByPackageSeriesValueNumberedContentsPackagesItem[];
|
||||
"repository": string;
|
||||
/** digest of go.mod and go.sum */
|
||||
"requires"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface PackagesByPackageSeriesValueNumbered {
|
||||
"commit"?: string;
|
||||
"contents"?: PackagesByPackageSeriesValueNumberedContents;
|
||||
"digest"?: string;
|
||||
"fingerprint"?: string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is one value of the state packages under the key <package>.<series>. */
|
||||
export interface PackagesByPackageSeriesValue {
|
||||
/** when (RFC 3339 time) */
|
||||
"at"?: string;
|
||||
"go-module"?: string;
|
||||
"name": string;
|
||||
"newest"?: PackagesByPackageSeriesValueNewest;
|
||||
"numbered"?: PackagesByPackageSeriesValueNumbered;
|
||||
"package"?: string;
|
||||
"seat"?: string;
|
||||
"series": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-delivery", defined whole (seats/mesh-delivery/seat.json): The delivery gate: reads and steers deliveries, merges and the checks that decide them; the merge is made on the operator's Approve once both checks passed.
|
||||
|
||||
export declare const seat: "mesh-delivery";
|
||||
|
||||
export declare const verbs: {
|
||||
readonly deliveries: "deliveries";
|
||||
readonly show: "show";
|
||||
readonly groups: "groups";
|
||||
readonly source: "source";
|
||||
readonly stalled: "stalled";
|
||||
readonly recovery: "recovery";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly owed: "owed";
|
||||
readonly pinned: "pinned";
|
||||
readonly freed: "freed";
|
||||
readonly headsReplaced: "heads-replaced";
|
||||
readonly recordOpened: "record-opened";
|
||||
readonly recordEnded: "record-ended";
|
||||
readonly filling: "filling";
|
||||
readonly full: "full";
|
||||
readonly room: "room";
|
||||
readonly sourceMoved: "source-moved";
|
||||
readonly recoveryMerged: "recovery-merged";
|
||||
};
|
||||
|
||||
export declare const family: { readonly name: "mesh-delivery.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export declare const owedStream: "SEAT_mesh-delivery_owed";
|
||||
|
||||
export declare function owedSubject(repository: string, number: string): string;
|
||||
|
||||
export declare const owedSubjectAll: "mesh.seat.mesh-delivery.event.owed.*.*";
|
||||
|
||||
export declare const pinnedSubject: "mesh.seat.mesh-delivery.event.pinned";
|
||||
|
||||
export declare const freedSubject: "mesh.seat.mesh-delivery.event.freed";
|
||||
|
||||
export declare const headsReplacedSubject: "mesh.seat.mesh-delivery.event.heads-replaced";
|
||||
|
||||
export declare const recordOpenedSubject: "mesh.seat.mesh-delivery.event.record-opened";
|
||||
|
||||
export declare const recordEndedSubject: "mesh.seat.mesh-delivery.event.record-ended";
|
||||
|
||||
export declare const fillingSubject: "mesh.seat.mesh-delivery.event.filling";
|
||||
|
||||
export declare const fullSubject: "mesh.seat.mesh-delivery.event.full";
|
||||
|
||||
export declare const roomSubject: "mesh.seat.mesh-delivery.event.room";
|
||||
|
||||
export declare function sourceMovedSubject(branch: string): string;
|
||||
|
||||
export declare const sourceMovedSubjectAll: "mesh.seat.mesh-delivery.event.source-moved.*";
|
||||
|
||||
export declare const recoveryMergedSubject: "mesh.seat.mesh-delivery.event.recovery-merged";
|
||||
|
||||
export declare const states: {
|
||||
readonly source: "source";
|
||||
readonly merges: "merges";
|
||||
readonly owed: "owed";
|
||||
};
|
||||
|
||||
/** The key of one value of the state source under the form "<branch>". */
|
||||
export declare function sourceByBranchKey(branch: string): string;
|
||||
|
||||
/** The parts of a key of the form "<branch>", or undefined for a key of another form. */
|
||||
export declare function parseSourceByBranchKey(_key: string): { branch: string } | undefined;
|
||||
|
||||
/** The key of one value of the state merges under the form "<group>". */
|
||||
export declare function mergesByGroupKey(group: string): string;
|
||||
|
||||
/** The parts of a key of the form "<group>", or undefined for a key of another form. */
|
||||
export declare function parseMergesByGroupKey(_key: string): { group: string } | undefined;
|
||||
|
||||
/** The key of one value of the state owed under the form "<repository>.<number>.<head>.<act>". */
|
||||
export declare function owedByRepositoryNumberHeadActKey(repository: string, number: string, head: string, act: string): string;
|
||||
|
||||
/** The parts of a key of the form "<repository>.<number>.<head>.<act>", or undefined for a key of another form. */
|
||||
export declare function parseOwedByRepositoryNumberHeadActKey(_key: string): { repository: string; number: string; head: string; act: string } | undefined;
|
||||
|
||||
/** an act the gate said for a group, with its recorded outcome once the forge bridge said one */
|
||||
export interface Act {
|
||||
/** when the outcome was recorded */
|
||||
"at"?: string;
|
||||
/** the outcome the forge bridge said as owed.ended and the gate recorded; absent while unanswered */
|
||||
"outcome"?: "performed" | "refused" | "could not be performed" | "undecodable" | "dropped";
|
||||
"owed": Owed;
|
||||
/** the forge's own words for a refusal, the error for an act that could not be performed, why one is undecodable or dropped */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** the one Approve ask of a milestone (ADR 0493 §9), said apart from each delivery's transition */
|
||||
export interface Ask {
|
||||
/** on answered: approve or decline */
|
||||
"answer"?: string;
|
||||
/** the ask's id */
|
||||
"ask": string;
|
||||
/** when */
|
||||
"at"?: string;
|
||||
/** on answered: who answered */
|
||||
"by"?: string;
|
||||
/** its delivery group */
|
||||
"group": string;
|
||||
/** repository to the head asked */
|
||||
"heads"?: Record<string, string>;
|
||||
/** the milestone */
|
||||
"milestone": string;
|
||||
/** on withdrawn: why, such as a new head of a member */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** the delivery records' ledger's fill against its cap */
|
||||
export interface Fill {
|
||||
/** when */
|
||||
"at"?: string;
|
||||
"bytes": number;
|
||||
/** bytes */
|
||||
"cap": number;
|
||||
/** what full refuses, such as the next record */
|
||||
"refused"?: string;
|
||||
/** the kept data, by its name in the holder's manifest */
|
||||
"store": string;
|
||||
}
|
||||
|
||||
/** one delivery group: its members, its derived state and the acts the gate said for it */
|
||||
export interface Group {
|
||||
/** the acts the gate said for it, each with its id and its recorded outcome; an id said and not answered is the forge bridge's to perform */
|
||||
"acts": Act[];
|
||||
/** the group's check: its verdict, or asked as <id> */
|
||||
"check"?: string;
|
||||
/** the group's id, its branch */
|
||||
"id": string;
|
||||
/** its members in merge order */
|
||||
"members": Member[];
|
||||
/** its state, derived from its members */
|
||||
"state": string;
|
||||
/** why it is in that state */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** one member of a group: a pull request */
|
||||
export interface Member {
|
||||
/** the branch it merges into */
|
||||
"base"?: string;
|
||||
/** its head */
|
||||
"head": string;
|
||||
/** the member's delivery id */
|
||||
"id": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the pull request is open: not merged, closed or final */
|
||||
"open"?: boolean;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** the member's delivery state */
|
||||
"state": string;
|
||||
}
|
||||
|
||||
/** one act the gate owes the forge, said once under its id and safe to repeat at the forge (design 47 *What the gate owes the forge*); the forge bridge performs it through the seat git's verb of the same act */
|
||||
export interface Owed {
|
||||
/** the act: merge (the seat git's merge-pull), status, view, comment or note */
|
||||
"act": "merge" | "status" | "view" | "comment" | "note";
|
||||
/** the operator's ask that approved the heads, for a merge */
|
||||
"ask"?: string;
|
||||
/** the commit a status or a note line is on; the head when absent */
|
||||
"commit"?: string;
|
||||
/** a status: its context, such as mesh/merge-gate */
|
||||
"context"?: string;
|
||||
/** a status: what it says */
|
||||
"description"?: string;
|
||||
/** the delivery group the pull request is a member of, for a merge */
|
||||
"group"?: string;
|
||||
/** the pull request's head the act is for */
|
||||
"head": string;
|
||||
/** the act's id, the same each time it is said again; a comment and a note line carry it, so the forge holds it once */
|
||||
"id": string;
|
||||
/** a note line: the one line */
|
||||
"line"?: string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** when the gate first said it */
|
||||
"said"?: string;
|
||||
/** a status: its state, pending, success, failure or error */
|
||||
"state"?: string;
|
||||
/** a status: the page it links to */
|
||||
"target"?: string;
|
||||
/** a comment or the view: the text, markdown */
|
||||
"text"?: string;
|
||||
}
|
||||
|
||||
/** the graph revisions a delivery record starts or stops pointing at */
|
||||
export interface Pins {
|
||||
/** assignment graph revisions, by their number on the seat mesh-wants */
|
||||
"assignment"?: number[];
|
||||
/** catalog graph revisions, by their number on the seat mesh-catalog */
|
||||
"catalog"?: number[];
|
||||
/** the record's milestone */
|
||||
"milestone": string;
|
||||
/** the record's id */
|
||||
"record": string;
|
||||
/** on freed: the record ended past its retention, or was removed by hand */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** one repository of the source revision: its trunk branch and that trunk's head */
|
||||
export interface SourceHead {
|
||||
/** the trunk's head the source revision names */
|
||||
"head": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** its trunk branch, such as main */
|
||||
"trunk": string;
|
||||
}
|
||||
|
||||
/** is what deliveries takes. */
|
||||
export interface DeliveriesInput {
|
||||
/** "true": the final ones of the last thirty days too */
|
||||
"all"?: "true" | "false";
|
||||
/** a group's id (its branch name) */
|
||||
"group"?: string;
|
||||
/** owner/repository */
|
||||
"repository"?: string;
|
||||
/** one state, e.g. delivering or held */
|
||||
"state"?: string;
|
||||
}
|
||||
|
||||
/** is what deliveries answers. */
|
||||
export type DeliveriesAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what show takes. */
|
||||
export interface ShowInput {
|
||||
/** a delivery's id, or a group's */
|
||||
"id": string;
|
||||
}
|
||||
|
||||
/** is what show answers. */
|
||||
export type ShowAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what groups takes. */
|
||||
export interface GroupsInput {
|
||||
/** "true": the groups that ended too */
|
||||
"all"?: "true" | "false";
|
||||
/** one group's id: that group alone, ended or not */
|
||||
"group"?: string;
|
||||
}
|
||||
|
||||
/** is what groups answers. */
|
||||
export interface GroupsAnswer {
|
||||
/** why it could not answer at all; a group it does not know is answered with no groups, never an error */
|
||||
"error"?: string;
|
||||
"groups"?: Group[];
|
||||
}
|
||||
|
||||
/** is what source takes. */
|
||||
export interface SourceInput {
|
||||
/** the watched branch, escaped as a key name is */
|
||||
"branch": string;
|
||||
}
|
||||
|
||||
/** is what source answers. */
|
||||
export interface SourceAnswer {
|
||||
/** the watched branch the source revision is of */
|
||||
"branch"?: string;
|
||||
/** why it could not be read */
|
||||
"error"?: string;
|
||||
/** the group that moved the source revision last; absent before the first */
|
||||
"group"?: string;
|
||||
/** every repository the source revision names, by name */
|
||||
"repositories"?: SourceHead[];
|
||||
/** the source revision's number on the bus; 0 before the first */
|
||||
"revision"?: number;
|
||||
}
|
||||
|
||||
/** is what stalled takes. */
|
||||
export interface StalledInput {
|
||||
}
|
||||
|
||||
/** is what stalled answers. */
|
||||
export type StalledAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what recovery takes. */
|
||||
export interface RecoveryInput {
|
||||
/** the merge commit */
|
||||
"commit": string;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** why the merge is a recovery */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what recovery answers. */
|
||||
export interface RecoveryAnswer {
|
||||
/** the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the merge commit */
|
||||
"commit": string;
|
||||
"recovery": boolean;
|
||||
/** the repository */
|
||||
"repository"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event owed. */
|
||||
export type OwedEvent = Owed;
|
||||
|
||||
/** is the body of the event pinned. */
|
||||
export type PinnedEvent = Pins;
|
||||
|
||||
/** is the body of the event freed. */
|
||||
export type FreedEvent = Pins;
|
||||
|
||||
/** is the body of the event heads-replaced. */
|
||||
export interface HeadsReplacedEvent {
|
||||
/** when */
|
||||
"at"?: string;
|
||||
/** the pull request closed */
|
||||
"closed"?: boolean;
|
||||
/** the group */
|
||||
"group": string;
|
||||
/** its new head; absent when it closed */
|
||||
"head"?: string;
|
||||
/** the candidate's heads, 12 hex digits, as its revisions are keyed */
|
||||
"heads": string;
|
||||
/** its pull request's number */
|
||||
"number": number;
|
||||
/** the member whose head moved or which closed */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is the body of the event record-opened. */
|
||||
export interface RecordOpenedEvent {
|
||||
/** when */
|
||||
"at"?: string;
|
||||
/** a merge made at the forge, with no Approve */
|
||||
"forge-made"?: boolean;
|
||||
/** its milestone */
|
||||
"milestone": string;
|
||||
/** the record's id */
|
||||
"record": string;
|
||||
}
|
||||
|
||||
export interface RecordEndedEventAwayItem {
|
||||
/** a node away */
|
||||
"node": string;
|
||||
/** since when */
|
||||
"since"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event record-ended. */
|
||||
export interface RecordEndedEvent {
|
||||
/** when */
|
||||
"at"?: string;
|
||||
/** the nodes away, each with since when; it ends without them */
|
||||
"away"?: RecordEndedEventAwayItem[];
|
||||
/** a merge made at the forge, with no Approve */
|
||||
"forge-made"?: boolean;
|
||||
/** its milestone */
|
||||
"milestone": string;
|
||||
/** the record's id */
|
||||
"record": string;
|
||||
}
|
||||
|
||||
/** is the body of the event filling. */
|
||||
export type FillingEvent = Fill;
|
||||
|
||||
/** is the body of the event full. */
|
||||
export type FullEvent = Fill;
|
||||
|
||||
/** is the body of the event room. */
|
||||
export type RoomEvent = Fill;
|
||||
|
||||
/** is the body of the event source-moved. */
|
||||
export interface SourceMovedEvent {
|
||||
"at"?: string;
|
||||
"branch": string;
|
||||
/** the group that moved it, when one did */
|
||||
"group"?: string;
|
||||
"revision": number;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is the body of the event recovery-merged. */
|
||||
export interface RecoveryMergedEvent {
|
||||
"at"?: string;
|
||||
/** the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the merge commit */
|
||||
"commit": string;
|
||||
/** the repository */
|
||||
"repository": string;
|
||||
"v": number;
|
||||
/** why */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is one value of the state source under the key <branch>. */
|
||||
export interface SourceByBranchValue {
|
||||
/** the group that moved it */
|
||||
"group": string;
|
||||
/** repository to the merged head, a full commit */
|
||||
"heads": Record<string, string>;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface MergesByGroupValuePullsItem {
|
||||
"commit"?: string;
|
||||
"head": string;
|
||||
"number": number;
|
||||
"repository": string;
|
||||
/** merging, merged or refused */
|
||||
"state": string;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state merges under the key <group>. */
|
||||
export interface MergesByGroupValue {
|
||||
/** <repository>@<number> to the approved head */
|
||||
"approved"?: Record<string, string>;
|
||||
/** the ask key */
|
||||
"ask": string;
|
||||
"group": string;
|
||||
"pulls": MergesByGroupValuePullsItem[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state owed under the key <repository>.<number>.<head>.<act>. */
|
||||
export interface OwedByRepositoryNumberHeadActValue {
|
||||
/** status=<context>, view, note or comment.<seq> */
|
||||
"act": string;
|
||||
"context"?: string;
|
||||
"ref"?: string;
|
||||
"state"?: string;
|
||||
"target"?: string;
|
||||
"text"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-delivery", defined whole (seats/mesh-delivery/seat.json): The delivery gate: reads and steers deliveries, merges and the checks that decide them; the merge is made on the operator's Approve once both checks passed.
|
||||
|
||||
export const seat = "mesh-delivery";
|
||||
|
||||
export const verbs = {
|
||||
deliveries: "deliveries",
|
||||
show: "show",
|
||||
groups: "groups",
|
||||
source: "source",
|
||||
stalled: "stalled",
|
||||
recovery: "recovery",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
owed: "owed",
|
||||
pinned: "pinned",
|
||||
freed: "freed",
|
||||
headsReplaced: "heads-replaced",
|
||||
recordOpened: "record-opened",
|
||||
recordEnded: "record-ended",
|
||||
filling: "filling",
|
||||
full: "full",
|
||||
room: "room",
|
||||
sourceMoved: "source-moved",
|
||||
recoveryMerged: "recovery-merged",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-delivery.events", maxAgeDays: 7 };
|
||||
|
||||
export const owedStream = "SEAT_mesh-delivery_owed";
|
||||
|
||||
export function owedSubject(repository, number) {
|
||||
return "mesh.seat.mesh-delivery.event.owed." + repository + "." + number;
|
||||
}
|
||||
|
||||
export const owedSubjectAll = "mesh.seat.mesh-delivery.event.owed.*.*";
|
||||
|
||||
export const pinnedSubject = "mesh.seat.mesh-delivery.event.pinned";
|
||||
|
||||
export const freedSubject = "mesh.seat.mesh-delivery.event.freed";
|
||||
|
||||
export const headsReplacedSubject = "mesh.seat.mesh-delivery.event.heads-replaced";
|
||||
|
||||
export const recordOpenedSubject = "mesh.seat.mesh-delivery.event.record-opened";
|
||||
|
||||
export const recordEndedSubject = "mesh.seat.mesh-delivery.event.record-ended";
|
||||
|
||||
export const fillingSubject = "mesh.seat.mesh-delivery.event.filling";
|
||||
|
||||
export const fullSubject = "mesh.seat.mesh-delivery.event.full";
|
||||
|
||||
export const roomSubject = "mesh.seat.mesh-delivery.event.room";
|
||||
|
||||
export function sourceMovedSubject(branch) {
|
||||
return "mesh.seat.mesh-delivery.event.source-moved." + branch;
|
||||
}
|
||||
|
||||
export const sourceMovedSubjectAll = "mesh.seat.mesh-delivery.event.source-moved.*";
|
||||
|
||||
export const recoveryMergedSubject = "mesh.seat.mesh-delivery.event.recovery-merged";
|
||||
|
||||
export const states = {
|
||||
source: "source",
|
||||
merges: "merges",
|
||||
owed: "owed",
|
||||
};
|
||||
|
||||
/** The key of one value of the state source under the form "<branch>". */
|
||||
export function sourceByBranchKey(branch) {
|
||||
return branch;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<branch>", or undefined for a key of another form. */
|
||||
export function parseSourceByBranchKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const branch = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { branch };
|
||||
}
|
||||
|
||||
/** The key of one value of the state merges under the form "<group>". */
|
||||
export function mergesByGroupKey(group) {
|
||||
return group;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>", or undefined for a key of another form. */
|
||||
export function parseMergesByGroupKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const group = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group };
|
||||
}
|
||||
|
||||
/** The key of one value of the state owed under the form "<repository>.<number>.<head>.<act>". */
|
||||
export function owedByRepositoryNumberHeadActKey(repository, number, head, act) {
|
||||
return repository + "." + number + "." + head + "." + act;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<repository>.<number>.<head>.<act>", or undefined for a key of another form. */
|
||||
export function parseOwedByRepositoryNumberHeadActKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const number = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
const _at4 = _rest.indexOf(".");
|
||||
if (_at4 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at4);
|
||||
_rest = _rest.slice(_at4 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const act = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, number, head, act };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-delivery, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-delivery",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-delivery", defined whole (seats/mesh-delivery/seat.json): The delivery gate: reads and steers deliveries, merges and the checks that decide them; the merge is made on the operator's Approve once both checks passed.
|
||||
|
||||
export const seat = "mesh-delivery";
|
||||
|
||||
export const verbs = {
|
||||
deliveries: "deliveries",
|
||||
times: "times",
|
||||
show: "show",
|
||||
groups: "groups",
|
||||
whatIf: "what-if",
|
||||
checks: "checks",
|
||||
table: "table",
|
||||
stalled: "stalled",
|
||||
recheck: "recheck",
|
||||
release: "release",
|
||||
stop: "stop",
|
||||
close: "close",
|
||||
retireHistory: "retire-history",
|
||||
settle: "settle",
|
||||
} as const;
|
||||
|
||||
export const states = {
|
||||
source: "source",
|
||||
merges: "merges",
|
||||
asks: "asks",
|
||||
owed: "owed",
|
||||
turns: "turns",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state source under the form "main". */
|
||||
export function sourceByMainKey(): string {
|
||||
return "main";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "main", or undefined for a key of another form. */
|
||||
export function parseSourceByMainKey(_key: string): { } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("main")) return undefined;
|
||||
_rest = _rest.slice(4);
|
||||
if (_rest !== "") return undefined;
|
||||
return { };
|
||||
}
|
||||
|
||||
/** The key of one value of the state merges under the form "<group>". */
|
||||
export function mergesByGroupKey(group: string): string {
|
||||
return group;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>", or undefined for a key of another form. */
|
||||
export function parseMergesByGroupKey(_key: string): { group: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const group = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group };
|
||||
}
|
||||
|
||||
/** The key of one value of the state asks under the form "merge.<group>.<heads>". */
|
||||
export function asksByMergeGroupHeadsKey(group: string, heads: string): string {
|
||||
return "merge." + group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "merge.<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseAsksByMergeGroupHeadsKey(_key: string): { group: string; heads: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("merge.")) return undefined;
|
||||
_rest = _rest.slice(6);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** The key of one value of the state owed under the form "<repository>.<number>.<head>.<act>". */
|
||||
export function owedByRepositoryNumberHeadActKey(repository: string, number: string, head: string, act: string): string {
|
||||
return repository + "." + number + "." + head + "." + act;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<repository>.<number>.<head>.<act>", or undefined for a key of another form. */
|
||||
export function parseOwedByRepositoryNumberHeadActKey(_key: string): { repository: string; number: string; head: string; act: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const number = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
const _at4 = _rest.indexOf(".");
|
||||
if (_at4 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at4);
|
||||
_rest = _rest.slice(_at4 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const act = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, number, head, act };
|
||||
}
|
||||
|
||||
/** The key of one value of the state turns under the form "<repository>". */
|
||||
export function turnsByRepositoryKey(repository: string): string {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<repository>", or undefined for a key of another form. */
|
||||
export function parseTurnsByRepositoryKey(_key: string): { repository: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const repository = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository };
|
||||
}
|
||||
|
||||
/** is what deliveries takes. */
|
||||
export interface DeliveriesInput {
|
||||
/** "true": the final ones of the last thirty days too */
|
||||
"all"?: "true" | "false";
|
||||
/** a group's id (its branch name) */
|
||||
"group"?: string;
|
||||
/** owner/repository */
|
||||
"repository"?: string;
|
||||
/** one state, e.g. delivering or held */
|
||||
"state"?: string;
|
||||
}
|
||||
|
||||
/** is what deliveries answers. */
|
||||
export type DeliveriesAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what times takes. */
|
||||
export interface TimesInput {
|
||||
}
|
||||
|
||||
/** is what times answers. */
|
||||
export type TimesAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what show takes. */
|
||||
export interface ShowInput {
|
||||
/** a delivery's id, or a group's */
|
||||
"id": string;
|
||||
}
|
||||
|
||||
/** is what show answers. */
|
||||
export type ShowAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what groups takes. */
|
||||
export interface GroupsInput {
|
||||
/** "true": the groups that ended too */
|
||||
"all"?: "true" | "false";
|
||||
}
|
||||
|
||||
/** is what groups answers. */
|
||||
export type GroupsAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what what-if takes. */
|
||||
export interface WhatIfInput {
|
||||
}
|
||||
|
||||
/** is what what-if answers. */
|
||||
export type WhatIfAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what checks takes. */
|
||||
export interface ChecksInput {
|
||||
/** a commit's sha, or the start of one, instead of a pull request */
|
||||
"commit"?: string;
|
||||
/** a pull request's number: its head is read */
|
||||
"number"?: string;
|
||||
/** owner/repository */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is what checks answers. */
|
||||
export type ChecksAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what table takes. */
|
||||
export interface TableInput {
|
||||
}
|
||||
|
||||
/** is what table answers. */
|
||||
export type TableAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what stalled takes. */
|
||||
export interface StalledInput {
|
||||
}
|
||||
|
||||
/** is what stalled answers. */
|
||||
export type StalledAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what recheck takes. */
|
||||
export interface RecheckInput {
|
||||
/** the delivery's id */
|
||||
"id": string;
|
||||
/** why, kept with the transition */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what recheck answers. */
|
||||
export type RecheckAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what release takes. */
|
||||
export interface ReleaseInput {
|
||||
}
|
||||
|
||||
/** is what release answers. */
|
||||
export type ReleaseAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what stop takes. */
|
||||
export interface StopInput {
|
||||
}
|
||||
|
||||
/** is what stop answers. */
|
||||
export type StopAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what close takes. */
|
||||
export interface CloseInput {
|
||||
/** the delivery's id */
|
||||
"id": string;
|
||||
/** the condition it answers */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what close answers. */
|
||||
export type CloseAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what retire-history takes. */
|
||||
export interface RetireHistoryInput {
|
||||
}
|
||||
|
||||
/** is what retire-history answers. */
|
||||
export type RetireHistoryAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what settle takes. */
|
||||
export interface SettleInput {
|
||||
/** the held deliveries' ids (owner/repository@commit) */
|
||||
"ids": string[];
|
||||
/** why they may be settled, shown to the operator */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what settle answers. */
|
||||
export type SettleAnswer = Record<string, unknown>;
|
||||
|
||||
/** is one value of the state source under the key main. */
|
||||
export interface SourceByMainValue {
|
||||
/** the group that moved it */
|
||||
"group": string;
|
||||
/** repository to the merged head, a full commit */
|
||||
"heads": Record<string, string>;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface MergesByGroupValuePullsItem {
|
||||
"commit"?: string;
|
||||
"head": string;
|
||||
"number": number;
|
||||
"repository": string;
|
||||
/** merging, merged or refused */
|
||||
"state": string;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state merges under the key <group>. */
|
||||
export interface MergesByGroupValue {
|
||||
/** <repository>@<number> to the approved head */
|
||||
"approved"?: Record<string, string>;
|
||||
/** the ask key */
|
||||
"ask": string;
|
||||
"group": string;
|
||||
"pulls": MergesByGroupValuePullsItem[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface AsksByMergeGroupHeadsValueHeadsItem {
|
||||
/** the full commit */
|
||||
"head": string;
|
||||
"number": number;
|
||||
/** <owner>/<name> */
|
||||
"repository": string;
|
||||
}
|
||||
|
||||
/** is one value of the state asks under the key merge.<group>.<heads>. */
|
||||
export interface AsksByMergeGroupHeadsValue {
|
||||
/** the operator-channel ask as raised */
|
||||
"ask": unknown;
|
||||
/** the number of times it was asked */
|
||||
"asking"?: number;
|
||||
"group": string;
|
||||
"heads": AsksByMergeGroupHeadsValueHeadsItem[];
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state owed under the key <repository>.<number>.<head>.<act>. */
|
||||
export interface OwedByRepositoryNumberHeadActValue {
|
||||
/** status=<context>, view, note or comment.<seq> */
|
||||
"act": string;
|
||||
"context"?: string;
|
||||
"ref"?: string;
|
||||
"state"?: string;
|
||||
"target"?: string;
|
||||
"text"?: string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface TurnsByRepositoryValueWaitingItem {
|
||||
/** when (RFC 3339 time) */
|
||||
"approved": string;
|
||||
"ask"?: string;
|
||||
"group": string;
|
||||
"heads": string;
|
||||
/** when (RFC 3339 time) */
|
||||
"since": string;
|
||||
"step"?: string;
|
||||
"waits-for"?: string;
|
||||
/** when (RFC 3339 time) */
|
||||
"waits-since"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state turns under the key <repository>. */
|
||||
export interface TurnsByRepositoryValue {
|
||||
"repository": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
"waiting": TurnsByRepositoryValueWaitingItem[];
|
||||
}
|
||||
|
||||
+101
-99
@@ -1,127 +1,106 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-delivery-checker", defined whole (seats/mesh-delivery-checker/seat.json): The merge check's tries: start one, read one, end one. The checker's own events stay under its own subjects (ADR 0620 §2).
|
||||
// The contract of the seat "mesh-delivery-checker", defined whole (seats/mesh-delivery-checker/seat.json): The merge check's tries: start one, read one, end one. The seat says each check's end as checked and what the checker owes the forge as owed; the checker's other events stay under its own subjects (ADR 0620 §2).
|
||||
|
||||
export const seat = "mesh-delivery-checker";
|
||||
export declare const seat: "mesh-delivery-checker";
|
||||
|
||||
export const verbs = {
|
||||
try: "try",
|
||||
tryRead: "try-read",
|
||||
tryEnd: "try-end",
|
||||
input: "input",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly try: "try";
|
||||
readonly tryRead: "try-read";
|
||||
readonly tryEnd: "try-end";
|
||||
readonly input: "input";
|
||||
};
|
||||
|
||||
export const holderEvents = {
|
||||
verdict: "verdict",
|
||||
tagWanted: "tag-wanted",
|
||||
previewWritten: "preview.written",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly checked: "checked";
|
||||
readonly owed: "owed";
|
||||
};
|
||||
|
||||
export function verdictHolderSubject(holder: string): string {
|
||||
return "mesh.stream." + holder + ".event.verdict";
|
||||
}
|
||||
export declare const family: { readonly name: "mesh-delivery-checker.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export function tagWantedHolderSubject(holder: string): string {
|
||||
return "mesh.stream." + holder + ".event.tag-wanted";
|
||||
}
|
||||
export declare const checkedSubject: "mesh.seat.mesh-delivery-checker.event.checked";
|
||||
|
||||
export function previewWrittenHolderSubject(holder: string): string {
|
||||
return "mesh.stream." + holder + ".event.preview.written";
|
||||
}
|
||||
export declare const owedStream: "SEAT_mesh-delivery-checker_owed";
|
||||
|
||||
export const states = {
|
||||
verdicts: "verdicts",
|
||||
kept: "kept",
|
||||
owed: "owed",
|
||||
previews: "previews",
|
||||
} as const;
|
||||
export declare function owedSubject(repository: string, number: string): string;
|
||||
|
||||
export declare const owedSubjectAll: "mesh.seat.mesh-delivery-checker.event.owed.*.*";
|
||||
|
||||
export declare const holderEvents: {
|
||||
readonly verdict: "verdict";
|
||||
readonly tagWanted: "tag-wanted";
|
||||
readonly previewWritten: "preview.written";
|
||||
};
|
||||
|
||||
export declare function verdictHolderSubject(holder: string): string;
|
||||
|
||||
export declare function tagWantedHolderSubject(holder: string): string;
|
||||
|
||||
export declare function previewWrittenHolderSubject(holder: string): string;
|
||||
|
||||
export declare const states: {
|
||||
readonly verdicts: "verdicts";
|
||||
readonly kept: "kept";
|
||||
readonly owed: "owed";
|
||||
readonly previews: "previews";
|
||||
};
|
||||
|
||||
/** The key of one value of the state verdicts under the form "<group>.<heads>". */
|
||||
export function verdictsByGroupHeadsKey(group: string, heads: string): string {
|
||||
return group + "." + heads;
|
||||
}
|
||||
export declare function verdictsByGroupHeadsKey(group: string, heads: string): string;
|
||||
|
||||
/** The parts of a key of the form "<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseVerdictsByGroupHeadsKey(_key: string): { group: string; heads: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
export declare function parseVerdictsByGroupHeadsKey(_key: string): { group: string; heads: string } | undefined;
|
||||
|
||||
/** The key of one value of the state kept under the form "<level>.<digest>". */
|
||||
export function keptByLevelDigestKey(level: string, digest: string): string {
|
||||
return level + "." + digest;
|
||||
}
|
||||
export declare function keptByLevelDigestKey(level: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "<level>.<digest>", or undefined for a key of another form. */
|
||||
export function parseKeptByLevelDigestKey(_key: string): { level: string; digest: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const level = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { level, digest };
|
||||
}
|
||||
export declare function parseKeptByLevelDigestKey(_key: string): { level: string; digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state owed under the form "<repository>.<number>.<head>.<act>". */
|
||||
export function owedByRepositoryNumberHeadActKey(repository: string, number: string, head: string, act: string): string {
|
||||
return repository + "." + number + "." + head + "." + act;
|
||||
}
|
||||
export declare function owedByRepositoryNumberHeadActKey(repository: string, number: string, head: string, act: string): string;
|
||||
|
||||
/** The parts of a key of the form "<repository>.<number>.<head>.<act>", or undefined for a key of another form. */
|
||||
export function parseOwedByRepositoryNumberHeadActKey(_key: string): { repository: string; number: string; head: string; act: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const number = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
const _at4 = _rest.indexOf(".");
|
||||
if (_at4 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at4);
|
||||
_rest = _rest.slice(_at4 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const act = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, number, head, act };
|
||||
}
|
||||
export declare function parseOwedByRepositoryNumberHeadActKey(_key: string): { repository: string; number: string; head: string; act: string } | undefined;
|
||||
|
||||
/** The key of one value of the state previews under the form "<repository>.<head>.<trunk>". */
|
||||
export function previewsByRepositoryHeadTrunkKey(repository: string, head: string, trunk: string): string {
|
||||
return repository + "." + head + "." + trunk;
|
||||
}
|
||||
export declare function previewsByRepositoryHeadTrunkKey(repository: string, head: string, trunk: string): string;
|
||||
|
||||
/** The parts of a key of the form "<repository>.<head>.<trunk>", or undefined for a key of another form. */
|
||||
export function parsePreviewsByRepositoryHeadTrunkKey(_key: string): { repository: string; head: string; trunk: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const trunk = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, head, trunk };
|
||||
export declare function parsePreviewsByRepositoryHeadTrunkKey(_key: string): { repository: string; head: string; trunk: string } | undefined;
|
||||
|
||||
/** one entry of the candidate checked: a module at its fingerprint */
|
||||
export interface CheckedEntry {
|
||||
/** the entry's fingerprint */
|
||||
"fp": string;
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the node it was composed for, when the check composed it on one */
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
/** the status the checker owes the forge for a head, said under its id and safe to repeat (a status replaces what stands); the forge bridge performs it through the seat git's verb status (design 47 *What the gate owes the forge*) */
|
||||
export interface Owed {
|
||||
/** the act: always status */
|
||||
"act": "status";
|
||||
/** its context, mesh/check */
|
||||
"context": string;
|
||||
/** what it says */
|
||||
"description"?: string;
|
||||
/** the pull request's head the status is on */
|
||||
"head": string;
|
||||
/** the act's id, the same each time it is said again */
|
||||
"id": string;
|
||||
/** the pull request's number */
|
||||
"number": number;
|
||||
/** the repository, <owner>/<name> */
|
||||
"repository": string;
|
||||
/** when the checker first said it */
|
||||
"said"?: string;
|
||||
/** pending, success, failure or error */
|
||||
"state": string;
|
||||
/** the page it links to */
|
||||
"target"?: string;
|
||||
}
|
||||
|
||||
export interface TryInputMembersItem {
|
||||
@@ -196,6 +175,29 @@ export interface InputAnswer {
|
||||
"input": string;
|
||||
}
|
||||
|
||||
/** is the body of the event checked. */
|
||||
export interface CheckedEvent {
|
||||
/** when */
|
||||
"at"?: string;
|
||||
/** the candidate's catalog graph revision judged, by its number on the seat mesh-catalog */
|
||||
"catalog"?: number;
|
||||
/** the entries checked */
|
||||
"entries"?: CheckedEntry[];
|
||||
/** the group, its branch */
|
||||
"group": string;
|
||||
/** the heads checked, 12 hex digits, as the candidate's revisions are keyed */
|
||||
"heads": string;
|
||||
/** the source revision the heads are merged onto */
|
||||
"source"?: number;
|
||||
/** pass, fail, or could not run when a part the check needs did not answer */
|
||||
"verdict": "pass" | "fail" | "could not run";
|
||||
/** what failed first, or the part not heard */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is the body of the event owed. */
|
||||
export type OwedEvent = Owed;
|
||||
|
||||
export interface VerdictHolderEventSeriesItem {
|
||||
/** its artifact, or the package's ecosystem name as the module's packages name it */
|
||||
"artifact": string;
|
||||
@@ -0,0 +1,143 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-delivery-checker", defined whole (seats/mesh-delivery-checker/seat.json): The merge check's tries: start one, read one, end one. The seat says each check's end as checked and what the checker owes the forge as owed; the checker's other events stay under its own subjects (ADR 0620 §2).
|
||||
|
||||
export const seat = "mesh-delivery-checker";
|
||||
|
||||
export const verbs = {
|
||||
try: "try",
|
||||
tryRead: "try-read",
|
||||
tryEnd: "try-end",
|
||||
input: "input",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
checked: "checked",
|
||||
owed: "owed",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-delivery-checker.events", maxAgeDays: 7 };
|
||||
|
||||
export const checkedSubject = "mesh.seat.mesh-delivery-checker.event.checked";
|
||||
|
||||
export const owedStream = "SEAT_mesh-delivery-checker_owed";
|
||||
|
||||
export function owedSubject(repository, number) {
|
||||
return "mesh.seat.mesh-delivery-checker.event.owed." + repository + "." + number;
|
||||
}
|
||||
|
||||
export const owedSubjectAll = "mesh.seat.mesh-delivery-checker.event.owed.*.*";
|
||||
|
||||
export const holderEvents = {
|
||||
verdict: "verdict",
|
||||
tagWanted: "tag-wanted",
|
||||
previewWritten: "preview.written",
|
||||
};
|
||||
|
||||
export function verdictHolderSubject(holder) {
|
||||
return "mesh.stream." + holder + ".event.verdict";
|
||||
}
|
||||
|
||||
export function tagWantedHolderSubject(holder) {
|
||||
return "mesh.stream." + holder + ".event.tag-wanted";
|
||||
}
|
||||
|
||||
export function previewWrittenHolderSubject(holder) {
|
||||
return "mesh.stream." + holder + ".event.preview.written";
|
||||
}
|
||||
|
||||
export const states = {
|
||||
verdicts: "verdicts",
|
||||
kept: "kept",
|
||||
owed: "owed",
|
||||
previews: "previews",
|
||||
};
|
||||
|
||||
/** The key of one value of the state verdicts under the form "<group>.<heads>". */
|
||||
export function verdictsByGroupHeadsKey(group, heads) {
|
||||
return group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseVerdictsByGroupHeadsKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** The key of one value of the state kept under the form "<level>.<digest>". */
|
||||
export function keptByLevelDigestKey(level, digest) {
|
||||
return level + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<level>.<digest>", or undefined for a key of another form. */
|
||||
export function parseKeptByLevelDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const level = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { level, digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state owed under the form "<repository>.<number>.<head>.<act>". */
|
||||
export function owedByRepositoryNumberHeadActKey(repository, number, head, act) {
|
||||
return repository + "." + number + "." + head + "." + act;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<repository>.<number>.<head>.<act>", or undefined for a key of another form. */
|
||||
export function parseOwedByRepositoryNumberHeadActKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const number = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
const _at4 = _rest.indexOf(".");
|
||||
if (_at4 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at4);
|
||||
_rest = _rest.slice(_at4 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const act = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, number, head, act };
|
||||
}
|
||||
|
||||
/** The key of one value of the state previews under the form "<repository>.<head>.<trunk>". */
|
||||
export function previewsByRepositoryHeadTrunkKey(repository, head, trunk) {
|
||||
return repository + "." + head + "." + trunk;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<repository>.<head>.<trunk>", or undefined for a key of another form. */
|
||||
export function parsePreviewsByRepositoryHeadTrunkKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const repository = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const head = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const trunk = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { repository, head, trunk };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-delivery-checker, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-delivery-checker",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+598
@@ -0,0 +1,598 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-pipeline-runner", defined whole (seats/mesh-pipeline-runner/seat.json): The pipeline runner: it runs each module's pipeline on each of its watched branches, asking each step of the seat that serves it and hearing its end, and says each pipeline's and each step's start and end (design 47 *Pipelines per module*). Held once for the mesh; a foundation part.
|
||||
|
||||
export declare const seat: "mesh-pipeline-runner";
|
||||
|
||||
export declare const verbs: {
|
||||
readonly run: "run";
|
||||
readonly start: "start";
|
||||
readonly show: "show";
|
||||
readonly list: "list";
|
||||
readonly stands: "stands";
|
||||
readonly whyCarried: "why-carried";
|
||||
readonly kept: "kept";
|
||||
readonly review: "review";
|
||||
readonly rerun: "rerun";
|
||||
readonly accept: "accept";
|
||||
readonly cancel: "cancel";
|
||||
readonly askAgain: "ask-again";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly pipelineStarted: "pipeline-started";
|
||||
readonly pipelineEnded: "pipeline-ended";
|
||||
readonly groupEnded: "group-ended";
|
||||
readonly runStarted: "run-started";
|
||||
readonly stepStarted: "step-started";
|
||||
readonly stepEnded: "step-ended";
|
||||
readonly waitHeld: "wait-held";
|
||||
readonly waitEnded: "wait-ended";
|
||||
};
|
||||
|
||||
export declare const family: { readonly name: "mesh-pipeline-runner.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export declare const pipelineStartedStream: "SEAT_mesh-pipeline-runner_pipeline-started";
|
||||
|
||||
export declare function pipelineStartedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const pipelineStartedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.pipeline-started.*.*.*";
|
||||
|
||||
export declare const pipelineEndedStream: "SEAT_mesh-pipeline-runner_pipeline-ended";
|
||||
|
||||
export declare function pipelineEndedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const pipelineEndedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.*.*.*";
|
||||
|
||||
export declare const groupEndedStream: "SEAT_mesh-pipeline-runner_group-ended";
|
||||
|
||||
export declare function groupEndedSubject(branch: string, group: string): string;
|
||||
|
||||
export declare const groupEndedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.group-ended.*.*";
|
||||
|
||||
export declare const runStartedStream: "SEAT_mesh-pipeline-runner_run-started";
|
||||
|
||||
export declare function runStartedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const runStartedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.run-started.*.*.*";
|
||||
|
||||
export declare const stepStartedStream: "SEAT_mesh-pipeline-runner_step-started";
|
||||
|
||||
export declare function stepStartedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const stepStartedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.step-started.*.*.*";
|
||||
|
||||
export declare const stepEndedStream: "SEAT_mesh-pipeline-runner_step-ended";
|
||||
|
||||
export declare function stepEndedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const stepEndedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.step-ended.*.*.*";
|
||||
|
||||
export declare const waitHeldStream: "SEAT_mesh-pipeline-runner_wait-held";
|
||||
|
||||
export declare function waitHeldSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const waitHeldSubjectAll: "mesh.seat.mesh-pipeline-runner.event.wait-held.*.*.*";
|
||||
|
||||
export declare const waitEndedStream: "SEAT_mesh-pipeline-runner_wait-ended";
|
||||
|
||||
export declare function waitEndedSubject(module: string, branch: string, commitOrGroup: string): string;
|
||||
|
||||
export declare const waitEndedSubjectAll: "mesh.seat.mesh-pipeline-runner.event.wait-ended.*.*.*";
|
||||
|
||||
export declare const states: {
|
||||
readonly pipelines: "pipelines";
|
||||
readonly kept: "kept";
|
||||
readonly stepLog: "step-log";
|
||||
readonly stepOutputs: "step-outputs";
|
||||
};
|
||||
|
||||
/** The key of one value of the state pipelines under the form "<branch>.<revision>.<module>". */
|
||||
export declare function pipelinesByBranchRevisionModuleKey(branch: string, revision: string, module: string): string;
|
||||
|
||||
/** The parts of a key of the form "<branch>.<revision>.<module>", or undefined for a key of another form. */
|
||||
export declare function parsePipelinesByBranchRevisionModuleKey(_key: string): { branch: string; revision: string; module: string } | undefined;
|
||||
|
||||
/** The key of one value of the state kept under the form "<level>.<digest>". */
|
||||
export declare function keptByLevelDigestKey(level: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "<level>.<digest>", or undefined for a key of another form. */
|
||||
export declare function parseKeptByLevelDigestKey(_key: string): { level: string; digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state step-log under the form "<pipeline>". */
|
||||
export declare function stepLogByPipelineKey(pipeline: string): string;
|
||||
|
||||
/** The parts of a key of the form "<pipeline>", or undefined for a key of another form. */
|
||||
export declare function parseStepLogByPipelineKey(_key: string): { pipeline: string } | undefined;
|
||||
|
||||
/** The key of one value of the state step-outputs under the form "<pipeline>.<step>.<artifact>". */
|
||||
export declare function stepOutputsByPipelineStepArtifactKey(pipeline: string, step: string, artifact: string): string;
|
||||
|
||||
/** The parts of a key of the form "<pipeline>.<step>.<artifact>", or undefined for a key of another form. */
|
||||
export declare function parseStepOutputsByPipelineStepArtifactKey(_key: string): { pipeline: string; step: string; artifact: string } | undefined;
|
||||
|
||||
/** a failed optional step a person accepted, recorded in the hand-act log */
|
||||
export interface Accepted {
|
||||
"at"?: string;
|
||||
/** who accepted it, as the runtime proved the caller */
|
||||
"by": string;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** a store's fill against its cap */
|
||||
export interface Fill {
|
||||
"at"?: string;
|
||||
"bytes": number;
|
||||
/** bytes */
|
||||
"cap": number;
|
||||
/** the kept data, by its name in the holder's manifest */
|
||||
"store": string;
|
||||
}
|
||||
|
||||
/** a group's one pipeline's end on a watched branch, said once every member's modules have ended; a group's wants are written on it alone (ADR 0666 section 9) */
|
||||
export interface GroupEnded {
|
||||
"branch": string;
|
||||
"ended"?: string;
|
||||
"group": string;
|
||||
"outcome": "running" | "passed" | "failed" | "refused" | "superseded" | "cancelled";
|
||||
/** every member module's pipeline, each ended */
|
||||
"pipelines": PipelineEnded[];
|
||||
"revision"?: number;
|
||||
/** the group's one source revision of the watched branch */
|
||||
"source"?: number;
|
||||
"v": number;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8) */
|
||||
export interface KeptResult {
|
||||
/** sha256:<hex> of what the package's tests read */
|
||||
"digest": string;
|
||||
/** unit or integration */
|
||||
"level": string;
|
||||
"package": string;
|
||||
/** the pipeline whose step kept it */
|
||||
"pipeline"?: string;
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
/** one entry of the step log */
|
||||
export interface LogEntry {
|
||||
"artifact"?: string;
|
||||
"at": string;
|
||||
"outcome"?: "running" | "waiting" | "passed" | "failed" | "nothing to run" | "bypassed" | "carried" | "could not run" | "waiting for a build node" | "did not build" | "accepted" | "declined" | "superseded" | "cancelled";
|
||||
/** the output's name in step-outputs */
|
||||
"output"?: string;
|
||||
"pipeline": string;
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
"what": "started" | "ended";
|
||||
}
|
||||
|
||||
/** a module at a named commit */
|
||||
export interface Member {
|
||||
/** the branch the commit is on */
|
||||
"branch"?: string;
|
||||
"commit": string;
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** one pipeline as the runner keeps it in its state pipelines, by compare-and-set (design 47 *The runner's kept data*) */
|
||||
export interface Pipeline {
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** the commit the module's entry was last changed at */
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fp"?: string;
|
||||
/** the gathered group, when the pipeline is its */
|
||||
"group"?: string;
|
||||
"module": string;
|
||||
"outcome": "running" | "passed" | "failed" | "refused" | "superseded" | "cancelled";
|
||||
/** yes when the module is over its test budget (design 47 G section 419) */
|
||||
"over-budget"?: boolean;
|
||||
/** the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline"?: string;
|
||||
"repository"?: string;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id, for a pipeline of a run; such a pipeline delivers nothing */
|
||||
"run"?: string;
|
||||
/** the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9) */
|
||||
"source"?: number;
|
||||
"started"?: string;
|
||||
/** every step, approval last */
|
||||
"steps": StepResult[];
|
||||
"tests"?: TestCounts;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
/** for a pipeline that did not pass, the steps that held it */
|
||||
"why"?: string;
|
||||
"widens"?: Widening[];
|
||||
}
|
||||
|
||||
/** a pipeline's end with every step's result, its test counts, the source revision and widens (design 47 *Health and going back*); the assigner writes a want only from one whose every required step passed */
|
||||
export interface PipelineEnded {
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** the commit the module's entry was last changed at */
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fp"?: string;
|
||||
/** the gathered group, when the pipeline is its */
|
||||
"group"?: string;
|
||||
"module": string;
|
||||
"outcome": "running" | "passed" | "failed" | "refused" | "superseded" | "cancelled";
|
||||
/** yes when the module is over its test budget (500 unit or 50 integration tests; design 47 G section 419) */
|
||||
"over-budget"?: boolean;
|
||||
/** the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id, for a pipeline of a run; such a pipeline delivers nothing */
|
||||
"run"?: string;
|
||||
/** the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9) */
|
||||
"source"?: number;
|
||||
"started"?: string;
|
||||
"steps": StepResult[];
|
||||
"tests"?: TestCounts;
|
||||
"v": number;
|
||||
"why"?: string;
|
||||
"widens"?: Widening[];
|
||||
}
|
||||
|
||||
export interface PipelineStartedStepsItem {
|
||||
"artifact"?: string;
|
||||
"status": "required" | "optional" | "bypass";
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
}
|
||||
|
||||
/** a pipeline's start */
|
||||
export interface PipelineStarted {
|
||||
"at"?: string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** the commit the module's entry was last changed at */
|
||||
"commit": string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fp"?: string;
|
||||
/** the gathered group, when the pipeline is its */
|
||||
"group"?: string;
|
||||
"module": string;
|
||||
/** the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id, for a pipeline of a run; such a pipeline delivers nothing */
|
||||
"run"?: string;
|
||||
/** the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9) */
|
||||
"source"?: number;
|
||||
/** the steps the policy gives it */
|
||||
"steps"?: PipelineStartedStepsItem[];
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** a run on request's start, with its members at their commits (ADR 0666 section 18) */
|
||||
export interface RunStarted {
|
||||
"at"?: string;
|
||||
/** the caller the runtime proved */
|
||||
"by": string;
|
||||
"members": Member[];
|
||||
"run": string;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** a step's start or end: the step, its status, its outcome, its fingerprint, its test counts, what a carried result was carried from, and for a rerun that it is one and its proved caller; a bypassed step too */
|
||||
export interface StepEvent {
|
||||
"at"?: string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** the commit the module's entry was last changed at */
|
||||
"commit": string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fp"?: string;
|
||||
/** the gathered group, when the pipeline is its */
|
||||
"group"?: string;
|
||||
"module": string;
|
||||
/** the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
"result": StepResult;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id, for a pipeline of a run; such a pipeline delivers nothing */
|
||||
"run"?: string;
|
||||
/** the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9) */
|
||||
"source"?: number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** one step of a pipeline: its status in the policy and its outcome (design 47 *Pipeline steps and the policy*) */
|
||||
export interface StepResult {
|
||||
"accepted"?: Accepted;
|
||||
/** the artifact reference, <module>:<artifact>; absent for a step of the whole module (review, approval) */
|
||||
"artifact"?: string;
|
||||
/** the step's ask on the serving seat's work queue */
|
||||
"ask"?: string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** for a carried result, the pipeline it was carried from */
|
||||
"carried-from"?: string;
|
||||
"ended"?: string;
|
||||
/** the artifact's build-input fingerprint the step ran at */
|
||||
"fingerprint"?: string;
|
||||
/** the node whose holder ended it */
|
||||
"node"?: string;
|
||||
/** for a waiting step, who or what it waits on: a person, a build node, the revision view */
|
||||
"on"?: string;
|
||||
/** never passed for a step that ran nothing (design 47 *Pipeline steps and the policy*) */
|
||||
"outcome": "running" | "waiting" | "passed" | "failed" | "nothing to run" | "bypassed" | "carried" | "could not run" | "waiting for a build node" | "did not build" | "accepted" | "declined" | "superseded" | "cancelled";
|
||||
/** the step's output, by its name in the runner's objects step-outputs */
|
||||
"output"?: string;
|
||||
/** the step was asked again by the runner's rerun */
|
||||
"rerun"?: boolean;
|
||||
/** the seat that serves the step, whose holder alone may end it (ADR 0666 section 21) */
|
||||
"seat"?: string;
|
||||
"started"?: string;
|
||||
/** the step's status in the module's policy */
|
||||
"status": "required" | "optional" | "bypass";
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
"tests"?: TestCounts;
|
||||
/** what the outcome rests on: the part not heard, the seat with no holder, what a waiting step waits on */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** how many tests a step ran and carried, per level (ADR 0666 section 8) */
|
||||
export interface TestCounts {
|
||||
"integration"?: number;
|
||||
"unit"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a build was made with: the language, the installed version and the build module's recipe */
|
||||
export interface ToolchainUsed {
|
||||
"language": string;
|
||||
"recipe": string;
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** a step's wait, held and ended; a wait on a person is said as waiting on that person, never a stall (ADR 0283) */
|
||||
export interface Wait {
|
||||
"artifact"?: string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** the commit the module's entry was last changed at */
|
||||
"commit"?: string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fp"?: string;
|
||||
/** the gathered group, when the pipeline is its */
|
||||
"group"?: string;
|
||||
/** for its end, how it ended: answered, ran, released, superseded */
|
||||
"how"?: string;
|
||||
"module": string;
|
||||
/** what the step waits on (design 47 *Health and going back*) */
|
||||
"on": "person" | "build node" | "revision view";
|
||||
/** the pipeline's key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id, for a pipeline of a run; such a pipeline delivers nothing */
|
||||
"run"?: string;
|
||||
"since": string;
|
||||
/** the source revision of the watched branch; the pipeline is keyed by it (ADR 0666 section 9) */
|
||||
"source"?: number;
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
"v": number;
|
||||
/** for a wait on a person, who: the operator, a reviewer */
|
||||
"who"?: string;
|
||||
}
|
||||
|
||||
/** a part serving a step the change alters, or an acting rule, a grant or a credential it widens, computed by the running runner (ADR 0666 section 23) */
|
||||
export interface Widening {
|
||||
/** the part, rule, grant or credential */
|
||||
"name": string;
|
||||
/** what the change alters in it; for "could not run" the grants part did not answer grants-for (design 47 G section 441) */
|
||||
"said"?: string;
|
||||
"what": "serving part" | "acting rule" | "grant" | "credential" | "could not run";
|
||||
}
|
||||
|
||||
/** is what run takes. */
|
||||
export interface RunInput {
|
||||
"members": Member[];
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what run answers. */
|
||||
export interface RunAnswer {
|
||||
/** the pipelines' keys */
|
||||
"pipelines"?: string[];
|
||||
"run": string;
|
||||
}
|
||||
|
||||
/** is what start takes. */
|
||||
export interface StartInput {
|
||||
"branch": string;
|
||||
"module": string;
|
||||
/** why, written with the caller the runtime proves in the hand-act log */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what start answers. */
|
||||
export interface StartAnswer {
|
||||
"pipeline": string;
|
||||
}
|
||||
|
||||
/** is what show takes. */
|
||||
export interface ShowInput {
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
}
|
||||
|
||||
/** is what show answers. */
|
||||
export interface ShowAnswer {
|
||||
"fill"?: Fill[];
|
||||
"log"?: LogEntry[];
|
||||
/** the outputs' names in step-outputs */
|
||||
"outputs"?: string[];
|
||||
"pipeline": Pipeline;
|
||||
}
|
||||
|
||||
/** is what list takes. */
|
||||
export interface ListInput {
|
||||
"branch"?: string;
|
||||
"commit"?: string;
|
||||
"limit"?: number;
|
||||
"module"?: string;
|
||||
"run"?: string;
|
||||
}
|
||||
|
||||
/** is what list answers. */
|
||||
export interface ListAnswer {
|
||||
"fill"?: Fill;
|
||||
"pipelines": Pipeline[];
|
||||
}
|
||||
|
||||
/** is what stands takes. */
|
||||
export interface StandsInput {
|
||||
}
|
||||
|
||||
/** is what stands answers. */
|
||||
export interface StandsAnswer {
|
||||
"stands": Wait[];
|
||||
}
|
||||
|
||||
/** is what why-carried takes. */
|
||||
export interface WhyCarriedInput {
|
||||
"artifact"?: string;
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
}
|
||||
|
||||
/** is what why-carried answers. */
|
||||
export interface WhyCarriedAnswer {
|
||||
"carried-from"?: string;
|
||||
"kept"?: KeptResult[];
|
||||
}
|
||||
|
||||
/** is what kept takes. */
|
||||
export interface KeptInput {
|
||||
"digest"?: string;
|
||||
"level"?: string;
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
/** is what kept answers. */
|
||||
export interface KeptAnswer {
|
||||
"fill"?: Fill;
|
||||
"kept": KeptResult[];
|
||||
}
|
||||
|
||||
/** is what review takes. */
|
||||
export interface ReviewInput {
|
||||
"commit": string;
|
||||
"fingerprint": string;
|
||||
"module": string;
|
||||
"outcome": "passed" | "failed";
|
||||
/** what the review found */
|
||||
"said"?: string;
|
||||
}
|
||||
|
||||
/** is what review answers. */
|
||||
export interface ReviewAnswer {
|
||||
"pipeline"?: string;
|
||||
"result": StepResult;
|
||||
}
|
||||
|
||||
/** is what rerun takes. */
|
||||
export interface RerunInput {
|
||||
"artifact"?: string;
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
/** why, written with the caller the runtime proves in the hand-act log */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what rerun answers. */
|
||||
export interface RerunAnswer {
|
||||
"pipeline": string;
|
||||
"result"?: StepResult;
|
||||
}
|
||||
|
||||
/** is what accept takes. */
|
||||
export interface AcceptInput {
|
||||
"artifact"?: string;
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
"step": "lint" | "unit" | "integration" | "composition" | "review" | "approval";
|
||||
/** why, written with the caller the runtime proves in the hand-act log */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what accept answers. */
|
||||
export interface AcceptAnswer {
|
||||
"result": StepResult;
|
||||
}
|
||||
|
||||
/** is what cancel takes. */
|
||||
export interface CancelInput {
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
/** why, written with the caller the runtime proves in the hand-act log */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what cancel answers. */
|
||||
export interface CancelAnswer {
|
||||
"pipeline": Pipeline;
|
||||
}
|
||||
|
||||
/** is what ask-again takes. */
|
||||
export interface AskAgainInput {
|
||||
/** the pipeline's key */
|
||||
"pipeline": string;
|
||||
/** why, written with the caller the runtime proves in the hand-act log */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what ask-again answers. */
|
||||
export interface AskAgainAnswer {
|
||||
"result": StepResult;
|
||||
}
|
||||
|
||||
/** is the body of the event pipeline-started. */
|
||||
export type PipelineStartedEvent = PipelineStarted;
|
||||
|
||||
/** is the body of the event pipeline-ended. */
|
||||
export type PipelineEndedEvent = PipelineEnded;
|
||||
|
||||
/** is the body of the event group-ended. */
|
||||
export type GroupEndedEvent = GroupEnded;
|
||||
|
||||
/** is the body of the event run-started. */
|
||||
export type RunStartedEvent = RunStarted;
|
||||
|
||||
/** is the body of the event step-started. */
|
||||
export type StepStartedEvent = StepEvent;
|
||||
|
||||
/** is the body of the event step-ended. */
|
||||
export type StepEndedEvent = StepEvent;
|
||||
|
||||
/** is the body of the event wait-held. */
|
||||
export type WaitHeldEvent = Wait;
|
||||
|
||||
/** is the body of the event wait-ended. */
|
||||
export type WaitEndedEvent = Wait;
|
||||
|
||||
/** is one value of the state pipelines under the key <branch>.<revision>.<module>. */
|
||||
export type PipelinesByBranchRevisionModuleValue = Pipeline;
|
||||
|
||||
/** is one value of the state kept under the key <level>.<digest>. */
|
||||
export type KeptByLevelDigestValue = KeptResult;
|
||||
|
||||
/** is one value of the state step-log under the key <pipeline>. */
|
||||
export type StepLogByPipelineValue = LogEntry;
|
||||
|
||||
/** is one value of the state step-outputs under the key <pipeline>.<step>.<artifact>. */
|
||||
export type StepOutputsByPipelineStepArtifactValue = string;
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-pipeline-runner", defined whole (seats/mesh-pipeline-runner/seat.json): The pipeline runner: it runs each module's pipeline on each of its watched branches, asking each step of the seat that serves it and hearing its end, and says each pipeline's and each step's start and end (design 47 *Pipelines per module*). Held once for the mesh; a foundation part.
|
||||
|
||||
export const seat = "mesh-pipeline-runner";
|
||||
|
||||
export const verbs = {
|
||||
run: "run",
|
||||
start: "start",
|
||||
show: "show",
|
||||
list: "list",
|
||||
stands: "stands",
|
||||
whyCarried: "why-carried",
|
||||
kept: "kept",
|
||||
review: "review",
|
||||
rerun: "rerun",
|
||||
accept: "accept",
|
||||
cancel: "cancel",
|
||||
askAgain: "ask-again",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
pipelineStarted: "pipeline-started",
|
||||
pipelineEnded: "pipeline-ended",
|
||||
groupEnded: "group-ended",
|
||||
runStarted: "run-started",
|
||||
stepStarted: "step-started",
|
||||
stepEnded: "step-ended",
|
||||
waitHeld: "wait-held",
|
||||
waitEnded: "wait-ended",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-pipeline-runner.events", maxAgeDays: 7 };
|
||||
|
||||
export const pipelineStartedStream = "SEAT_mesh-pipeline-runner_pipeline-started";
|
||||
|
||||
export function pipelineStartedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.pipeline-started." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const pipelineStartedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.pipeline-started.*.*.*";
|
||||
|
||||
export const pipelineEndedStream = "SEAT_mesh-pipeline-runner_pipeline-ended";
|
||||
|
||||
export function pipelineEndedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.pipeline-ended." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const pipelineEndedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.pipeline-ended.*.*.*";
|
||||
|
||||
export const groupEndedStream = "SEAT_mesh-pipeline-runner_group-ended";
|
||||
|
||||
export function groupEndedSubject(branch, group) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.group-ended." + branch + "." + group;
|
||||
}
|
||||
|
||||
export const groupEndedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.group-ended.*.*";
|
||||
|
||||
export const runStartedStream = "SEAT_mesh-pipeline-runner_run-started";
|
||||
|
||||
export function runStartedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.run-started." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const runStartedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.run-started.*.*.*";
|
||||
|
||||
export const stepStartedStream = "SEAT_mesh-pipeline-runner_step-started";
|
||||
|
||||
export function stepStartedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.step-started." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const stepStartedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.step-started.*.*.*";
|
||||
|
||||
export const stepEndedStream = "SEAT_mesh-pipeline-runner_step-ended";
|
||||
|
||||
export function stepEndedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.step-ended." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const stepEndedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.step-ended.*.*.*";
|
||||
|
||||
export const waitHeldStream = "SEAT_mesh-pipeline-runner_wait-held";
|
||||
|
||||
export function waitHeldSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.wait-held." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const waitHeldSubjectAll = "mesh.seat.mesh-pipeline-runner.event.wait-held.*.*.*";
|
||||
|
||||
export const waitEndedStream = "SEAT_mesh-pipeline-runner_wait-ended";
|
||||
|
||||
export function waitEndedSubject(module, branch, commitOrGroup) {
|
||||
return "mesh.seat.mesh-pipeline-runner.event.wait-ended." + module + "." + branch + "." + commitOrGroup;
|
||||
}
|
||||
|
||||
export const waitEndedSubjectAll = "mesh.seat.mesh-pipeline-runner.event.wait-ended.*.*.*";
|
||||
|
||||
export const states = {
|
||||
pipelines: "pipelines",
|
||||
kept: "kept",
|
||||
stepLog: "step-log",
|
||||
stepOutputs: "step-outputs",
|
||||
};
|
||||
|
||||
/** The key of one value of the state pipelines under the form "<branch>.<revision>.<module>". */
|
||||
export function pipelinesByBranchRevisionModuleKey(branch, revision, module) {
|
||||
return branch + "." + revision + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<branch>.<revision>.<module>", or undefined for a key of another form. */
|
||||
export function parsePipelinesByBranchRevisionModuleKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const branch = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const revision = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { branch, revision, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state kept under the form "<level>.<digest>". */
|
||||
export function keptByLevelDigestKey(level, digest) {
|
||||
return level + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<level>.<digest>", or undefined for a key of another form. */
|
||||
export function parseKeptByLevelDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const level = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { level, digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state step-log under the form "<pipeline>". */
|
||||
export function stepLogByPipelineKey(pipeline) {
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<pipeline>", or undefined for a key of another form. */
|
||||
export function parseStepLogByPipelineKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const pipeline = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { pipeline };
|
||||
}
|
||||
|
||||
/** The key of one value of the state step-outputs under the form "<pipeline>.<step>.<artifact>". */
|
||||
export function stepOutputsByPipelineStepArtifactKey(pipeline, step, artifact) {
|
||||
return pipeline + "." + step + "." + artifact;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<pipeline>.<step>.<artifact>", or undefined for a key of another form. */
|
||||
export function parseStepOutputsByPipelineStepArtifactKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const pipeline = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const step = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const artifact = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { pipeline, step, artifact };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-pipeline-runner",
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-pipeline-runner",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
"requires": true,
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-pipeline-runner, generated from its definition.",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-pipeline-runner",
|
||||
"type": "module",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
+555
@@ -0,0 +1,555 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-wants", defined whole (seats/mesh-wants/seat.json): The seat that says what each node should run and whether each module's new builds wait for a person (ADR 0565, ADR 0539).
|
||||
|
||||
export declare const seat: "mesh-wants";
|
||||
|
||||
export declare const verbs: {
|
||||
readonly upgrade: "upgrade";
|
||||
readonly bus: "bus";
|
||||
readonly revision: "revision";
|
||||
readonly entry: "entry";
|
||||
readonly difference: "difference";
|
||||
readonly input: "input";
|
||||
};
|
||||
|
||||
export declare const accepts: {
|
||||
readonly step: "step";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly policyChanged: "policy-changed";
|
||||
readonly assignmentRevision: "assignment-revision";
|
||||
readonly difference: "difference";
|
||||
readonly wanted: "wanted";
|
||||
readonly waitHeld: "wait-held";
|
||||
readonly waitEnded: "wait-ended";
|
||||
readonly filling: "filling";
|
||||
readonly full: "full";
|
||||
readonly room: "room";
|
||||
readonly stepEnded: "step-ended";
|
||||
readonly versionDelivered: "version-delivered";
|
||||
};
|
||||
|
||||
export declare const family: { readonly name: "mesh-wants.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export declare const policyChangedSubject: "mesh.seat.mesh-wants.event.policy-changed";
|
||||
|
||||
export declare const assignmentRevisionSubject: "mesh.seat.mesh-wants.event.assignment-revision";
|
||||
|
||||
export declare const differenceSubject: "mesh.seat.mesh-wants.event.difference";
|
||||
|
||||
export declare const wantedSubject: "mesh.seat.mesh-wants.event.wanted";
|
||||
|
||||
export declare const waitHeldSubject: "mesh.seat.mesh-wants.event.wait-held";
|
||||
|
||||
export declare const waitEndedSubject: "mesh.seat.mesh-wants.event.wait-ended";
|
||||
|
||||
export declare const fillingSubject: "mesh.seat.mesh-wants.event.filling";
|
||||
|
||||
export declare const fullSubject: "mesh.seat.mesh-wants.event.full";
|
||||
|
||||
export declare const roomSubject: "mesh.seat.mesh-wants.event.room";
|
||||
|
||||
export declare const stepEndedStream: "SEAT_mesh-wants_step-ended";
|
||||
|
||||
export declare function stepEndedSubject(node: string): string;
|
||||
|
||||
export declare const stepEndedSubjectAll: "mesh.seat.mesh-wants.event.step-ended.*";
|
||||
|
||||
export declare const versionDeliveredStream: "SEAT_mesh-wants_version-delivered";
|
||||
|
||||
export declare const versionDeliveredSubject: "mesh.seat.mesh-wants.event.version-delivered";
|
||||
|
||||
export declare const stepSubject: "mesh.seat.mesh-wants.accept.step";
|
||||
|
||||
export declare const states: {
|
||||
readonly wants: "wants";
|
||||
readonly differences: "differences";
|
||||
readonly compositions: "compositions";
|
||||
readonly assignmentRevisions: "assignment-revisions";
|
||||
readonly inputs: "inputs";
|
||||
};
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.<module>". */
|
||||
export declare function wantsByWantNodeModuleKey(node: string, module: string): string;
|
||||
|
||||
/** The parts of a key of the form "want.<node>.<module>", or undefined for a key of another form. */
|
||||
export declare function parseWantsByWantNodeModuleKey(_key: string): { node: string; module: string } | undefined;
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.node". */
|
||||
export declare function wantsByWantNodeNodeKey(node: string): string;
|
||||
|
||||
/** The parts of a key of the form "want.<node>.node", or undefined for a key of another form. */
|
||||
export declare function parseWantsByWantNodeNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** The key of one value of the state wants under the form "held.<module>.<fingerprint>". */
|
||||
export declare function wantsByHeldModuleFingerprintKey(module: string, fingerprint: string): string;
|
||||
|
||||
/** The parts of a key of the form "held.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export declare function parseWantsByHeldModuleFingerprintKey(_key: string): { module: string; fingerprint: string } | undefined;
|
||||
|
||||
/** The key of one value of the state differences under the form "<node>.<module>". */
|
||||
export declare function differencesByNodeModuleKey(node: string, module: string): string;
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export declare function parseDifferencesByNodeModuleKey(_key: string): { node: string; module: string } | undefined;
|
||||
|
||||
/** The key of one value of the state compositions under the form "<group>.<heads>". */
|
||||
export declare function compositionsByGroupHeadsKey(group: string, heads: string): string;
|
||||
|
||||
/** The parts of a key of the form "<group>.<heads>", or undefined for a key of another form. */
|
||||
export declare function parseCompositionsByGroupHeadsKey(_key: string): { group: string; heads: string } | undefined;
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "trunk.<revision>". */
|
||||
export declare function assignmentRevisionsByTrunkRevisionKey(revision: string): string;
|
||||
|
||||
/** The parts of a key of the form "trunk.<revision>", or undefined for a key of another form. */
|
||||
export declare function parseAssignmentRevisionsByTrunkRevisionKey(_key: string): { revision: string } | undefined;
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "candidate.<group>.<heads>". */
|
||||
export declare function assignmentRevisionsByCandidateGroupHeadsKey(group: string, heads: string): string;
|
||||
|
||||
/** The parts of a key of the form "candidate.<group>.<heads>", or undefined for a key of another form. */
|
||||
export declare function parseAssignmentRevisionsByCandidateGroupHeadsKey(_key: string): { group: string; heads: string } | undefined;
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "entry.<digest>". */
|
||||
export declare function assignmentRevisionsByEntryDigestKey(digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "entry.<digest>", or undefined for a key of another form. */
|
||||
export declare function parseAssignmentRevisionsByEntryDigestKey(_key: string): { digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state inputs under the form "<time>.<digest>". */
|
||||
export declare function inputsByTimeDigestKey(time: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "<time>.<digest>", or undefined for a key of another form. */
|
||||
export declare function parseInputsByTimeDigestKey(_key: string): { time: string; digest: string } | undefined;
|
||||
|
||||
/** one module version on a node of an assignment graph revision, stored once by its digest (ADR 0656) */
|
||||
export interface AssignmentEntry {
|
||||
/** the watched branch its placement names, whose catalog graph the entry comes from (design 47 lines 523-525) */
|
||||
"branch": string;
|
||||
/** the digest of its catalog graph entry */
|
||||
"catalog": string;
|
||||
"edges"?: Edge[];
|
||||
/** the fingerprint it is to run */
|
||||
"fp": string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface AssignmentRevisionCapabilitiesItem {
|
||||
/** the digest of the node's capability reading */
|
||||
"digest": string;
|
||||
"node": string;
|
||||
}
|
||||
|
||||
/** an assignment graph revision: the list of its entries' digests and the inputs it was computed from, so it can be computed again and compared */
|
||||
export interface AssignmentRevision {
|
||||
"at"?: string;
|
||||
"capabilities"?: AssignmentRevisionCapabilitiesItem[];
|
||||
/** the catalog graph revision of each watched branch a placement names, which the entries come from */
|
||||
"catalogs": CatalogOf[];
|
||||
/** what made it: catalog-revision, placement-changed or capabilities-changed */
|
||||
"cause"?: string;
|
||||
"entries": NodeEntryRef[];
|
||||
"group"?: string;
|
||||
"heads"?: string;
|
||||
/** trunk or candidate */
|
||||
"kind": string;
|
||||
/** the digest of the placements it was computed from */
|
||||
"placements": string;
|
||||
/** counted by its holder */
|
||||
"revision": number;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** one catalog graph revision of a watched branch the revision was computed from (design 47 lines 1416-1418) */
|
||||
export interface CatalogOf {
|
||||
/** the watched branch */
|
||||
"branch": string;
|
||||
/** that branch's catalog graph revision */
|
||||
"revision": number;
|
||||
/** the source revision of that branch it carries */
|
||||
"source"?: number;
|
||||
}
|
||||
|
||||
/** one module on a node whose version differs between two revisions */
|
||||
export interface Change {
|
||||
/** the edges that moved */
|
||||
"edges"?: Edge[];
|
||||
/** the fingerprint before; absent when it is new there */
|
||||
"from"?: string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
/** the fingerprint after; absent when it goes */
|
||||
"to"?: string;
|
||||
}
|
||||
|
||||
export interface DifferenceRefusedItem {
|
||||
"module": string;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** two assignment graph revisions compared: a change's delivery, with its order read off the edges and no plan stored (ADR 0656) */
|
||||
export interface Difference {
|
||||
"changes": Change[];
|
||||
/** the revision compared from */
|
||||
"from": number;
|
||||
"group"?: string;
|
||||
"heads"?: string;
|
||||
/** the nodes it touches */
|
||||
"nodes"?: string[];
|
||||
/** a module whose fingerprint changed while the difference is empty, refused by name */
|
||||
"refused"?: DifferenceRefusedItem[];
|
||||
/** the order as a view: each tier the changes whose acting parts acted in the tiers before it (ADR 0603 §6 as ADR 0656 changes it) */
|
||||
"tiers"?: NodeEntryRef[][];
|
||||
/** the revision compared to */
|
||||
"to": number;
|
||||
}
|
||||
|
||||
/** an edge from one module version on a node to another: provisioning, contribution, or an acting part's version that is to act on it in a step (ADR 0656) */
|
||||
export interface Edge {
|
||||
/** for acting, how long the new version may take before it acts */
|
||||
"bound"?: string;
|
||||
/** the other end's fingerprint */
|
||||
"fp"?: string;
|
||||
/** provisioning, contribution or acting */
|
||||
"kind": string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
/** for provisioning, the provision */
|
||||
"provision"?: string;
|
||||
/** for contribution, the seat it contributes to; for acting, the seat whose rule gave the edge */
|
||||
"seat"?: string;
|
||||
/** for acting, the step: take-in, validate, check, build, compose, grant or place */
|
||||
"step"?: string;
|
||||
}
|
||||
|
||||
/** a store's fill against its cap */
|
||||
export interface Fill {
|
||||
"at"?: string;
|
||||
"bytes": number;
|
||||
/** bytes */
|
||||
"cap": number;
|
||||
/** what full refuses */
|
||||
"refused"?: string;
|
||||
/** the kept data, by its name in the holder's manifest */
|
||||
"store": string;
|
||||
}
|
||||
|
||||
export interface NodeEntryRef {
|
||||
/** the entry's digest, its object's name */
|
||||
"digest": string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
}
|
||||
|
||||
/** the composition step's end, said by the assigner on the node it runs on (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at */
|
||||
export interface StepEnded {
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
"fingerprint": string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
"module": string;
|
||||
/** the node the assigner ran it on, as in the subject */
|
||||
"node": string;
|
||||
/** never passed for a step that composed nothing */
|
||||
"outcome": "passed" | "failed" | "nothing to run" | "could not run";
|
||||
"pipeline": string;
|
||||
"rerun"?: boolean;
|
||||
/** why it failed or could not run: the two modules owning one path, the part not heard */
|
||||
"said"?: string;
|
||||
"started"?: string;
|
||||
"step": "composition";
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
/** a node asleep, passed with a warning (ADR 0593 section 9) */
|
||||
"warnings"?: string[];
|
||||
}
|
||||
|
||||
/** the composition step of one module's pipeline (design 47 *Pipeline steps and the policy*, *The pipeline makes the check*): the assigner composes each machine's declaration at the change's heads with the composer built from them, in the build seat's sandbox, and refuses a change in which two modules own one path */
|
||||
export interface StepRun {
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch": string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the commit the step runs at */
|
||||
"commit": string;
|
||||
/** the module's build-input fingerprint at the commit */
|
||||
"fingerprint": string;
|
||||
"module": string;
|
||||
/** the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the step is asked again by the runner's rerun */
|
||||
"rerun"?: boolean;
|
||||
/** the catalog graph revision of the branch the pipeline runs for */
|
||||
"revision"?: number;
|
||||
/** the run on request's id: its composition writes no want (ADR 0666 section 18) */
|
||||
"run"?: string;
|
||||
/** the source revision of the watched branch; absent for a run on request */
|
||||
"source"?: number;
|
||||
"step": "composition";
|
||||
}
|
||||
|
||||
/** a step's wait the assigner holds: placing, wanting or composing until an acting part's new version runs */
|
||||
export interface Wait {
|
||||
/** a duration such as 30m */
|
||||
"bound"?: string;
|
||||
/** on a release, who released it and why */
|
||||
"by"?: string;
|
||||
"fp"?: string;
|
||||
/** on wait-ended: ran or released */
|
||||
"how"?: string;
|
||||
/** the entry that waits */
|
||||
"module": string;
|
||||
"node"?: string;
|
||||
/** the acting part waited for */
|
||||
"part": string;
|
||||
"since": string;
|
||||
"step": string;
|
||||
/** its new version's fingerprint */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is what upgrade takes. */
|
||||
export interface UpgradeInput {
|
||||
/** "true": each node's own composition, by its digest, and the assigner's findings */
|
||||
"compare"?: "true" | "false";
|
||||
/** one module */
|
||||
"module"?: string;
|
||||
/** with module: roll, together, record, or default to take a person's choice back */
|
||||
"policy"?: string;
|
||||
/** with policy: why, required and kept */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what upgrade answers. */
|
||||
export type UpgradeAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what bus takes. */
|
||||
export interface BusInput {
|
||||
}
|
||||
|
||||
/** is what bus answers. */
|
||||
export type BusAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what revision takes. */
|
||||
export interface RevisionInput {
|
||||
/** a candidate's group */
|
||||
"group"?: string;
|
||||
/** a candidate's heads */
|
||||
"heads"?: string;
|
||||
/** a kept revision; absent: the newest of trunk, or of the candidate named */
|
||||
"revision"?: number;
|
||||
}
|
||||
|
||||
/** is what revision answers. */
|
||||
export interface RevisionAnswer {
|
||||
"revision": AssignmentRevision;
|
||||
}
|
||||
|
||||
/** is what entry takes. */
|
||||
export interface EntryInput {
|
||||
"digest"?: string;
|
||||
/** a candidate's group */
|
||||
"group"?: string;
|
||||
/** a candidate's heads */
|
||||
"heads"?: string;
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
/** a kept revision; absent: the newest of trunk, or of the candidate named */
|
||||
"revision"?: number;
|
||||
}
|
||||
|
||||
/** is what entry answers. */
|
||||
export interface EntryAnswer {
|
||||
"digest": string;
|
||||
"entry": AssignmentEntry;
|
||||
}
|
||||
|
||||
/** is what difference takes. */
|
||||
export interface DifferenceInput {
|
||||
"from"?: number;
|
||||
"group"?: string;
|
||||
"heads"?: string;
|
||||
"to"?: number;
|
||||
}
|
||||
|
||||
/** is what difference answers. */
|
||||
export type DifferenceAnswer = Difference;
|
||||
|
||||
/** is what input takes. */
|
||||
export interface InputInput {
|
||||
/** the input's sha256 */
|
||||
"digest": string;
|
||||
}
|
||||
|
||||
/** is what input answers. */
|
||||
export interface InputAnswer {
|
||||
/** the input's sha256 */
|
||||
"digest": string;
|
||||
/** the input's exact bytes, base64 */
|
||||
"input": string;
|
||||
}
|
||||
|
||||
/** is the body of step. */
|
||||
export type StepAccept = StepRun;
|
||||
|
||||
/** is the body of the event policy-changed. */
|
||||
export type PolicyChangedEvent = Record<string, unknown>;
|
||||
|
||||
/** is the body of the event assignment-revision. */
|
||||
export interface AssignmentRevisionEvent {
|
||||
"at"?: string;
|
||||
/** the catalog graph revision of each watched branch a placement names, which the entries come from */
|
||||
"catalogs": CatalogOf[];
|
||||
"cause"?: string;
|
||||
"group"?: string;
|
||||
"heads"?: string;
|
||||
"kind": string;
|
||||
"revision": number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is the body of the event difference. */
|
||||
export interface DifferenceEvent {
|
||||
/** how many module versions it changes */
|
||||
"changes"?: number;
|
||||
"from": number;
|
||||
"group"?: string;
|
||||
"heads"?: string;
|
||||
"nodes"?: string[];
|
||||
"source"?: number;
|
||||
"to": number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is the body of the event wanted. */
|
||||
export interface WantedEvent {
|
||||
"at"?: string;
|
||||
"fp": string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
"revision": number;
|
||||
"source"?: number;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** is the body of the event wait-held. */
|
||||
export type WaitHeldEvent = Wait;
|
||||
|
||||
/** is the body of the event wait-ended. */
|
||||
export type WaitEndedEvent = Wait;
|
||||
|
||||
/** is the body of the event filling. */
|
||||
export type FillingEvent = Fill;
|
||||
|
||||
/** is the body of the event full. */
|
||||
export type FullEvent = Fill;
|
||||
|
||||
/** is the body of the event room. */
|
||||
export type RoomEvent = Fill;
|
||||
|
||||
/** is the body of the event step-ended. */
|
||||
export type StepEndedEvent = StepEnded;
|
||||
|
||||
/** is the body of the event version-delivered. */
|
||||
export interface VersionDeliveredEvent {
|
||||
"at"?: string;
|
||||
/** the machines away when it was said */
|
||||
"away"?: string[];
|
||||
/** the module */
|
||||
"module": string;
|
||||
/** the digest of each of its parts, by artifact reference */
|
||||
"parts": Record<string, string>;
|
||||
"v": number;
|
||||
/** MAJOR.MINOR.PATCH */
|
||||
"version": string;
|
||||
}
|
||||
|
||||
/** is one value of the state wants under the key want.<node>.<module>. */
|
||||
export interface WantsByWantNodeModuleValue {
|
||||
/** again or skip */
|
||||
"backup"?: "again" | "skip";
|
||||
"composed"?: string;
|
||||
"fp"?: string;
|
||||
"hold"?: boolean;
|
||||
"newest"?: string;
|
||||
/** the digest of each of the module's parts, by artifact reference; the node-engine fetches and checks each part by it (design 47 G section 379) */
|
||||
"parts"?: Record<string, string>;
|
||||
"put"?: boolean;
|
||||
"release"?: string;
|
||||
"removed"?: boolean;
|
||||
/** the rule that holds the node back, 1 to 10 */
|
||||
"rule"?: number;
|
||||
"self"?: boolean;
|
||||
"v"?: number;
|
||||
/** the module's released version, for people; none for a build of another watched branch (design 47 G section 379) */
|
||||
"version"?: string;
|
||||
"words"?: string;
|
||||
"yes"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state wants under the key want.<node>.node. */
|
||||
export interface WantsByWantNodeNodeValue {
|
||||
"composed": string;
|
||||
"self"?: boolean;
|
||||
"v"?: number;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state wants under the key held.<module>.<fingerprint>. */
|
||||
export interface WantsByHeldModuleFingerprintValue {
|
||||
"node": string;
|
||||
"v"?: number;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state differences under the key <node>.<module>. */
|
||||
export interface DifferencesByNodeModuleValue {
|
||||
"rule"?: number;
|
||||
"sent"?: string;
|
||||
"sent-build"?: string;
|
||||
"unexplained"?: boolean;
|
||||
"v"?: number;
|
||||
"want"?: string;
|
||||
"want-removed"?: boolean;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state compositions under the key <group>.<heads>. */
|
||||
export interface CompositionsByGroupHeadsValue {
|
||||
"group": string;
|
||||
/** 12 lowercase hex digits */
|
||||
"heads": string;
|
||||
"machine"?: string;
|
||||
"machines"?: string[];
|
||||
"sdk"?: string;
|
||||
/** pass, fail or waits */
|
||||
"state": string;
|
||||
/** milliseconds */
|
||||
"took"?: number;
|
||||
"v"?: number;
|
||||
"warnings"?: string[];
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state assignment-revisions under the key trunk.<revision>. */
|
||||
export type AssignmentRevisionsByTrunkRevisionValue = AssignmentRevision;
|
||||
|
||||
/** is one value of the state assignment-revisions under the key candidate.<group>.<heads>. */
|
||||
export type AssignmentRevisionsByCandidateGroupHeadsValue = AssignmentRevision;
|
||||
|
||||
/** is one value of the state assignment-revisions under the key entry.<digest>. */
|
||||
export type AssignmentRevisionsByEntryDigestValue = AssignmentEntry;
|
||||
|
||||
/** is one value of the state inputs under the key <time>.<digest>. */
|
||||
export type InputsByTimeDigestValue = string;
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-wants", defined whole (seats/mesh-wants/seat.json): The seat that says what each node should run and whether each module's new builds wait for a person (ADR 0565, ADR 0539).
|
||||
|
||||
export const seat = "mesh-wants";
|
||||
|
||||
export const verbs = {
|
||||
upgrade: "upgrade",
|
||||
bus: "bus",
|
||||
revision: "revision",
|
||||
entry: "entry",
|
||||
difference: "difference",
|
||||
input: "input",
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
step: "step",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
policyChanged: "policy-changed",
|
||||
assignmentRevision: "assignment-revision",
|
||||
difference: "difference",
|
||||
wanted: "wanted",
|
||||
waitHeld: "wait-held",
|
||||
waitEnded: "wait-ended",
|
||||
filling: "filling",
|
||||
full: "full",
|
||||
room: "room",
|
||||
stepEnded: "step-ended",
|
||||
versionDelivered: "version-delivered",
|
||||
};
|
||||
|
||||
export const family = { name: "mesh-wants.events", maxAgeDays: 7 };
|
||||
|
||||
export const policyChangedSubject = "mesh.seat.mesh-wants.event.policy-changed";
|
||||
|
||||
export const assignmentRevisionSubject = "mesh.seat.mesh-wants.event.assignment-revision";
|
||||
|
||||
export const differenceSubject = "mesh.seat.mesh-wants.event.difference";
|
||||
|
||||
export const wantedSubject = "mesh.seat.mesh-wants.event.wanted";
|
||||
|
||||
export const waitHeldSubject = "mesh.seat.mesh-wants.event.wait-held";
|
||||
|
||||
export const waitEndedSubject = "mesh.seat.mesh-wants.event.wait-ended";
|
||||
|
||||
export const fillingSubject = "mesh.seat.mesh-wants.event.filling";
|
||||
|
||||
export const fullSubject = "mesh.seat.mesh-wants.event.full";
|
||||
|
||||
export const roomSubject = "mesh.seat.mesh-wants.event.room";
|
||||
|
||||
export const stepEndedStream = "SEAT_mesh-wants_step-ended";
|
||||
|
||||
export function stepEndedSubject(node) {
|
||||
return "mesh.seat.mesh-wants.event.step-ended." + node;
|
||||
}
|
||||
|
||||
export const stepEndedSubjectAll = "mesh.seat.mesh-wants.event.step-ended.*";
|
||||
|
||||
export const versionDeliveredStream = "SEAT_mesh-wants_version-delivered";
|
||||
|
||||
export const versionDeliveredSubject = "mesh.seat.mesh-wants.event.version-delivered";
|
||||
|
||||
export const stepSubject = "mesh.seat.mesh-wants.accept.step";
|
||||
|
||||
export const states = {
|
||||
wants: "wants",
|
||||
differences: "differences",
|
||||
compositions: "compositions",
|
||||
assignmentRevisions: "assignment-revisions",
|
||||
inputs: "inputs",
|
||||
};
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.<module>". */
|
||||
export function wantsByWantNodeModuleKey(node, module) {
|
||||
return "want." + node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "want.<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseWantsByWantNodeModuleKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("want.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.node". */
|
||||
export function wantsByWantNodeNodeKey(node) {
|
||||
return "want." + node + ".node";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "want.<node>.node", or undefined for a key of another form. */
|
||||
export function parseWantsByWantNodeNodeKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("want.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".node");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 5);
|
||||
if (_rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state wants under the form "held.<module>.<fingerprint>". */
|
||||
export function wantsByHeldModuleFingerprintKey(module, fingerprint) {
|
||||
return "held." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "held.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseWantsByHeldModuleFingerprintKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("held.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state differences under the form "<node>.<module>". */
|
||||
export function differencesByNodeModuleKey(node, module) {
|
||||
return node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseDifferencesByNodeModuleKey(_key) {
|
||||
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 module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state compositions under the form "<group>.<heads>". */
|
||||
export function compositionsByGroupHeadsKey(group, heads) {
|
||||
return group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseCompositionsByGroupHeadsKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "trunk.<revision>". */
|
||||
export function assignmentRevisionsByTrunkRevisionKey(revision) {
|
||||
return "trunk." + revision;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "trunk.<revision>", or undefined for a key of another form. */
|
||||
export function parseAssignmentRevisionsByTrunkRevisionKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("trunk.")) return undefined;
|
||||
_rest = _rest.slice(6);
|
||||
if (_rest === "") return undefined;
|
||||
const revision = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { revision };
|
||||
}
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "candidate.<group>.<heads>". */
|
||||
export function assignmentRevisionsByCandidateGroupHeadsKey(group, heads) {
|
||||
return "candidate." + group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "candidate.<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseAssignmentRevisionsByCandidateGroupHeadsKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("candidate.")) return undefined;
|
||||
_rest = _rest.slice(10);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** The key of one value of the state assignment-revisions under the form "entry.<digest>". */
|
||||
export function assignmentRevisionsByEntryDigestKey(digest) {
|
||||
return "entry." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "entry.<digest>", or undefined for a key of another form. */
|
||||
export function parseAssignmentRevisionsByEntryDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("entry.")) return undefined;
|
||||
_rest = _rest.slice(6);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state inputs under the form "<time>.<digest>". */
|
||||
export function inputsByTimeDigestKey(time, digest) {
|
||||
return time + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<time>.<digest>", or undefined for a key of another form. */
|
||||
export function parseInputsByTimeDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const time = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { time, digest };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-wants, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-mesh-wants",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-wants", defined whole (seats/mesh-wants/seat.json): The seat that says what each node should run and whether each module's new builds wait for a person (ADR 0565, ADR 0539).
|
||||
|
||||
export const seat = "mesh-wants";
|
||||
|
||||
export const verbs = {
|
||||
upgrade: "upgrade",
|
||||
bus: "bus",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
policyChanged: "policy-changed",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-wants.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const policyChangedSubject = "mesh.seat.mesh-wants.event.policy-changed";
|
||||
|
||||
export const states = {
|
||||
wants: "wants",
|
||||
differences: "differences",
|
||||
compositions: "compositions",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.<module>". */
|
||||
export function wantsByWantNodeModuleKey(node: string, module: string): string {
|
||||
return "want." + node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "want.<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseWantsByWantNodeModuleKey(_key: string): { node: string; module: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("want.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state wants under the form "want.<node>.node". */
|
||||
export function wantsByWantNodeNodeKey(node: string): string {
|
||||
return "want." + node + ".node";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "want.<node>.node", or undefined for a key of another form. */
|
||||
export function parseWantsByWantNodeNodeKey(_key: string): { node: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("want.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".node");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const node = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 5);
|
||||
if (_rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state wants under the form "held.<module>.<fingerprint>". */
|
||||
export function wantsByHeldModuleFingerprintKey(module: string, fingerprint: string): string {
|
||||
return "held." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "held.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseWantsByHeldModuleFingerprintKey(_key: string): { module: string; fingerprint: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("held.")) return undefined;
|
||||
_rest = _rest.slice(5);
|
||||
const _at1 = _rest.indexOf(".");
|
||||
if (_at1 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at1);
|
||||
_rest = _rest.slice(_at1 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const fingerprint = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state differences under the form "<node>.<module>". */
|
||||
export function differencesByNodeModuleKey(node: string, module: string): string {
|
||||
return node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseDifferencesByNodeModuleKey(_key: string): { node: string; module: 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 module = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state compositions under the form "<group>.<heads>". */
|
||||
export function compositionsByGroupHeadsKey(group: string, heads: string): string {
|
||||
return group + "." + heads;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<group>.<heads>", or undefined for a key of another form. */
|
||||
export function parseCompositionsByGroupHeadsKey(_key: string): { group: string; heads: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const group = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const heads = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { group, heads };
|
||||
}
|
||||
|
||||
/** is what upgrade takes. */
|
||||
export interface UpgradeInput {
|
||||
/** "true": each node's own composition, by its digest, and the assigner's findings */
|
||||
"compare"?: "true" | "false";
|
||||
/** one module */
|
||||
"module"?: string;
|
||||
/** with module: roll, together, record, or default to take a person's choice back */
|
||||
"policy"?: string;
|
||||
/** with policy: why, required and kept */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what upgrade answers. */
|
||||
export type UpgradeAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what bus takes. */
|
||||
export interface BusInput {
|
||||
}
|
||||
|
||||
/** is what bus answers. */
|
||||
export type BusAnswer = Record<string, unknown>;
|
||||
|
||||
/** is the body of the event policy-changed. */
|
||||
export type PolicyChangedEvent = Record<string, unknown>;
|
||||
|
||||
/** is one value of the state wants under the key want.<node>.<module>. */
|
||||
export interface WantsByWantNodeModuleValue {
|
||||
/** again or skip */
|
||||
"backup"?: "again" | "skip";
|
||||
"composed"?: string;
|
||||
"fp"?: string;
|
||||
"hold"?: boolean;
|
||||
"newest"?: string;
|
||||
"put"?: boolean;
|
||||
"release"?: string;
|
||||
"removed"?: boolean;
|
||||
/** the rule that holds the node back, 1 to 10 */
|
||||
"rule"?: number;
|
||||
"self"?: boolean;
|
||||
"v"?: number;
|
||||
"words"?: string;
|
||||
"yes"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state wants under the key want.<node>.node. */
|
||||
export interface WantsByWantNodeNodeValue {
|
||||
"composed": string;
|
||||
"self"?: boolean;
|
||||
"v"?: number;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state wants under the key held.<module>.<fingerprint>. */
|
||||
export interface WantsByHeldModuleFingerprintValue {
|
||||
"node": string;
|
||||
"v"?: number;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state differences under the key <node>.<module>. */
|
||||
export interface DifferencesByNodeModuleValue {
|
||||
"rule"?: number;
|
||||
"sent"?: string;
|
||||
"sent-build"?: string;
|
||||
"unexplained"?: boolean;
|
||||
"v"?: number;
|
||||
"want"?: string;
|
||||
"want-removed"?: boolean;
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state compositions under the key <group>.<heads>. */
|
||||
export interface CompositionsByGroupHeadsValue {
|
||||
"group": string;
|
||||
/** 12 lowercase hex digits */
|
||||
"heads": string;
|
||||
"machine"?: string;
|
||||
"machines"?: string[];
|
||||
"sdk"?: string;
|
||||
/** pass, fail or waits */
|
||||
"state": string;
|
||||
/** milliseconds */
|
||||
"took"?: number;
|
||||
"v"?: number;
|
||||
"warnings"?: string[];
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
+78
-89
@@ -4,121 +4,89 @@
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-go";
|
||||
export declare const seat: "node-build-go";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
export declare const accepts: {
|
||||
readonly delivery: "delivery";
|
||||
readonly check: "check";
|
||||
readonly step: "step";
|
||||
readonly recheck: "recheck";
|
||||
readonly run: "run";
|
||||
};
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-go.accept.delivery";
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-go.accept.check";
|
||||
export declare const family: { readonly name: "node-build-go.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-go.accept.recheck";
|
||||
export declare const stepEndedStream: "SEAT_node-build-go_step-ended";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
export declare function stepEndedSubject(node: string): string;
|
||||
|
||||
export declare const stepEndedSubjectAll: "mesh.seat.node-build-go.event.step-ended.*";
|
||||
|
||||
export declare const deliverySubject: "mesh.seat.node-build-go.accept.delivery";
|
||||
|
||||
export declare const checkSubject: "mesh.seat.node-build-go.accept.check";
|
||||
|
||||
export declare const stepSubject: "mesh.seat.node-build-go.accept.step";
|
||||
|
||||
export declare const recheckSubject: "mesh.seat.node-build-go.accept.recheck";
|
||||
|
||||
export declare const runSubject: "mesh.seat.node-build-go.accept.run";
|
||||
|
||||
export declare const states: {
|
||||
readonly steps: "steps";
|
||||
readonly pauses: "pauses";
|
||||
readonly toolchains: "toolchains";
|
||||
readonly detectedSteps: "detected-steps";
|
||||
};
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function stepsByNodeIDKey(node: string, id: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parseStepsByNodeIDKey(_key: string): { node: string; id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
export declare function pausesByPausedNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByPausedNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
export declare function pausesByDroppedIDKey(id: string): string;
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
export declare function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
export declare function pausesByCapacityNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByCapacityNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function toolchainsByNodeLanguageKey(node: string, language: string): string;
|
||||
|
||||
/** 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 declare function parseToolchainsByNodeLanguageKey(_key: string): { node: string; language: string } | undefined;
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export declare function detectedStepsByModuleArtifactKey(module: string, artifact: string): string;
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export declare function parseDetectedStepsByModuleArtifactKey(_key: string): { module: string; artifact: string } | undefined;
|
||||
|
||||
export type AskArtifact = buildStep.AskArtifact;
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
@@ -128,6 +96,8 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type DetectedStep = buildStep.DetectedStep;
|
||||
export type DetectedSteps = buildStep.DetectedSteps;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
@@ -136,6 +106,9 @@ export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
export type FetchPackage = buildStep.FetchPackage;
|
||||
export type FetchRefusal = buildStep.FetchRefusal;
|
||||
export type KeptArtifactAnswer = buildStep.KeptArtifactAnswer;
|
||||
export type KeptArtifactInput = buildStep.KeptArtifactInput;
|
||||
export type KeptResult = buildStep.KeptResult;
|
||||
export type LevelAnswer = buildStep.LevelAnswer;
|
||||
export type LevelAnswerDigest = buildStep.LevelAnswerDigest;
|
||||
export type LevelAnswerDigestNeedsItem = buildStep.LevelAnswerDigestNeedsItem;
|
||||
@@ -160,8 +133,15 @@ export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type StepEnded = buildStep.StepEnded;
|
||||
export type StepEndedEvent = buildStep.StepEndedEvent;
|
||||
export type StepNames = buildStep.StepNames;
|
||||
export type StepResult = buildStep.StepResult;
|
||||
export type StepRun = buildStep.StepRun;
|
||||
export type StepsAnswer = buildStep.StepsAnswer;
|
||||
export type StepsInput = buildStep.StepsInput;
|
||||
export type TakenVersion = buildStep.TakenVersion;
|
||||
export type TestCounts = buildStep.TestCounts;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
export type ToolchainUsed = buildStep.ToolchainUsed;
|
||||
|
||||
@@ -171,9 +151,15 @@ export type DeliveryAccept = StepAsk;
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of step. */
|
||||
export type StepAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
/** is the body of run. */
|
||||
export type RunAccept = StepAsk;
|
||||
|
||||
/** is one value of the state steps under the key <node>.<id>. */
|
||||
export type StepsByNodeIDValue = Step;
|
||||
|
||||
@@ -189,3 +175,6 @@ export type PausesByCapacityNodeValue = Capacity;
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
/** is one value of the state detected-steps under the key <module>.<artifact>. */
|
||||
export type DetectedStepsByModuleArtifactValue = DetectedSteps;
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// 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.
|
||||
|
||||
export const seat = "node-build-go";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
step: "step",
|
||||
recheck: "recheck",
|
||||
run: "run",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export const family = { name: "node-build-go.events", maxAgeDays: 7 };
|
||||
|
||||
export const stepEndedStream = "SEAT_node-build-go_step-ended";
|
||||
|
||||
export function stepEndedSubject(node) {
|
||||
return "mesh.seat.node-build-go.event.step-ended." + node;
|
||||
}
|
||||
|
||||
export const stepEndedSubjectAll = "mesh.seat.node-build-go.event.step-ended.*";
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-go.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-go.accept.check";
|
||||
|
||||
export const stepSubject = "mesh.seat.node-build-go.accept.step";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-go.accept.recheck";
|
||||
|
||||
export const runSubject = "mesh.seat.node-build-go.accept.run";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
detectedSteps: "detected-steps",
|
||||
};
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node, id) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id) {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node) {
|
||||
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) {
|
||||
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, language) {
|
||||
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) {
|
||||
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 };
|
||||
}
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export function detectedStepsByModuleArtifactKey(module, artifact) {
|
||||
return module + "." + artifact;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export function parseDetectedStepsByModuleArtifactKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const artifact = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, artifact };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-go, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-go",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+180
-8
@@ -2,12 +2,18 @@
|
||||
|
||||
// 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",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
export interface AskArtifact {
|
||||
@@ -20,6 +26,8 @@ export interface AskArtifact {
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuiltArtifact[];
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
@@ -63,6 +71,20 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
export interface DetectedStep {
|
||||
/** the packages the step runs, by the language's convention */
|
||||
"packages"?: string[];
|
||||
"step": "lint" | "unit" | "integration";
|
||||
}
|
||||
|
||||
/** the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326) */
|
||||
export interface DetectedSteps {
|
||||
"at"?: string;
|
||||
"fingerprint": string;
|
||||
"steps": DetectedStep[];
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -133,6 +155,18 @@ export interface FetchRefusal {
|
||||
"reason": string;
|
||||
}
|
||||
|
||||
/** a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names */
|
||||
export interface KeptResult {
|
||||
/** sha256:<hex> of what the package's tests read */
|
||||
"digest": string;
|
||||
/** unit or integration */
|
||||
"level": string;
|
||||
"package": string;
|
||||
/** the pipeline whose step kept it */
|
||||
"pipeline"?: string;
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
export interface LevelAnswerDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
@@ -323,7 +357,7 @@ export interface StepAsk {
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
/** build, check, compose or step */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
@@ -332,11 +366,57 @@ export interface StepAsk {
|
||||
"packages"?: Record<string, string>;
|
||||
/** a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose */
|
||||
"run"?: RunJob;
|
||||
/** a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*) */
|
||||
"step"?: StepRun;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
/** a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at */
|
||||
export interface StepEnded {
|
||||
"artifact": string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the packages not run because the ask's kept results held them */
|
||||
"carried"?: KeptResult[];
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
"fingerprint": string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** the packages that passed at their digest, for the runner to keep */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
/** the node that ran it, as in the subject */
|
||||
"node": string;
|
||||
/** never passed for a step that ran nothing */
|
||||
"outcome": "passed" | "failed" | "nothing to run" | "could not run";
|
||||
/** the step's output when it fits the message */
|
||||
"output"?: string;
|
||||
/** the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16) */
|
||||
"output-object"?: string;
|
||||
"pipeline": string;
|
||||
"rerun"?: boolean;
|
||||
/** why it failed or could not run, naming the part not heard */
|
||||
"said"?: string;
|
||||
"started"?: string;
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"tests"?: TestCounts;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part */
|
||||
export interface StepNames {
|
||||
/** every watched branch a registration names */
|
||||
"branches": string[];
|
||||
/** every module the registrations name */
|
||||
"modules": string[];
|
||||
/** every repository a registration's git origin names, as <owner>/<name> */
|
||||
"repositories": string[];
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
export interface StepResult {
|
||||
"artifacts"?: BuiltArtifact[];
|
||||
"built"?: boolean;
|
||||
@@ -346,6 +426,8 @@ export interface StepResult {
|
||||
"exit"?: number;
|
||||
"fetch"?: FetchAnswer;
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"key"?: string;
|
||||
/** what the holder's node lacks of it */
|
||||
"lacks"?: string[];
|
||||
@@ -362,6 +444,35 @@ export interface StepResult {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip */
|
||||
export interface StepRun {
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch"?: string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the commit the step runs at */
|
||||
"commit": string;
|
||||
/** where the step reads the change's heads */
|
||||
"fetch": Fetch;
|
||||
/** the artifact's build-input fingerprint at the commit */
|
||||
"fingerprint": string;
|
||||
/** the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*) */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
"names": StepNames;
|
||||
/** the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the step is asked again by the runner's rerun */
|
||||
"rerun"?: boolean;
|
||||
/** the source revision of the watched branch the pipeline runs for; absent for a run on request */
|
||||
"revision"?: number;
|
||||
/** the pipeline step */
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
/** of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said */
|
||||
export interface TakenVersion {
|
||||
"asked": string;
|
||||
@@ -373,6 +484,12 @@ export interface TakenVersion {
|
||||
"sum"?: string;
|
||||
}
|
||||
|
||||
/** how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget) */
|
||||
export interface TestCounts {
|
||||
"integration"?: number;
|
||||
"unit"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -426,3 +543,58 @@ export interface DropInput {
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what kept-artifact takes. */
|
||||
export interface KeptArtifactInput {
|
||||
/** the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it */
|
||||
"digest": string;
|
||||
/** its build's fingerprint */
|
||||
"fp": string;
|
||||
/** the module, the holder of oci-artifact-registry */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what kept-artifact answers. */
|
||||
export interface KeptArtifactAnswer {
|
||||
/** the digest of the bytes kept */
|
||||
"digest"?: string;
|
||||
/** why it could not answer */
|
||||
"error"?: string;
|
||||
/** the fingerprint asked */
|
||||
"fp": string;
|
||||
/** the module asked */
|
||||
"module": string;
|
||||
/** the object's name in it: the digest */
|
||||
"object"?: string;
|
||||
/** why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest */
|
||||
"refused"?: "claims no oci-artifact-registry" | "not kept" | "digest differs";
|
||||
/** bytes */
|
||||
"size"?: number;
|
||||
/** the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus */
|
||||
"store"?: string;
|
||||
/** the refusal in words, naming the module */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is what steps takes. */
|
||||
export interface StepsInput {
|
||||
/** find them anew, not from the kept answer */
|
||||
"again"?: boolean;
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
"fetch": Fetch;
|
||||
"fingerprint"?: string;
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what steps answers. */
|
||||
export interface StepsAnswer {
|
||||
"artifact": string;
|
||||
"fingerprint"?: string;
|
||||
/** answered from the kept answer */
|
||||
"kept"?: boolean;
|
||||
"steps": DetectedStep[];
|
||||
}
|
||||
|
||||
/** is the body of the event step-ended. */
|
||||
export type StepEndedEvent = StepEnded;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export {};
|
||||
Vendored
+72
-89
@@ -4,121 +4,86 @@
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-image";
|
||||
export declare const seat: "node-build-image";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
export declare const accepts: {
|
||||
readonly delivery: "delivery";
|
||||
readonly check: "check";
|
||||
readonly step: "step";
|
||||
readonly recheck: "recheck";
|
||||
};
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-image.accept.delivery";
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-image.accept.check";
|
||||
export declare const family: { readonly name: "node-build-image.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-image.accept.recheck";
|
||||
export declare const stepEndedStream: "SEAT_node-build-image_step-ended";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
export declare function stepEndedSubject(node: string): string;
|
||||
|
||||
export declare const stepEndedSubjectAll: "mesh.seat.node-build-image.event.step-ended.*";
|
||||
|
||||
export declare const deliverySubject: "mesh.seat.node-build-image.accept.delivery";
|
||||
|
||||
export declare const checkSubject: "mesh.seat.node-build-image.accept.check";
|
||||
|
||||
export declare const stepSubject: "mesh.seat.node-build-image.accept.step";
|
||||
|
||||
export declare const recheckSubject: "mesh.seat.node-build-image.accept.recheck";
|
||||
|
||||
export declare const states: {
|
||||
readonly steps: "steps";
|
||||
readonly pauses: "pauses";
|
||||
readonly toolchains: "toolchains";
|
||||
readonly detectedSteps: "detected-steps";
|
||||
};
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function stepsByNodeIDKey(node: string, id: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parseStepsByNodeIDKey(_key: string): { node: string; id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
export declare function pausesByPausedNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByPausedNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
export declare function pausesByDroppedIDKey(id: string): string;
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
export declare function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
export declare function pausesByCapacityNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByCapacityNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function toolchainsByNodeLanguageKey(node: string, language: string): string;
|
||||
|
||||
/** 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 declare function parseToolchainsByNodeLanguageKey(_key: string): { node: string; language: string } | undefined;
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export declare function detectedStepsByModuleArtifactKey(module: string, artifact: string): string;
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export declare function parseDetectedStepsByModuleArtifactKey(_key: string): { module: string; artifact: string } | undefined;
|
||||
|
||||
export type AskArtifact = buildStep.AskArtifact;
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
@@ -128,6 +93,8 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type DetectedStep = buildStep.DetectedStep;
|
||||
export type DetectedSteps = buildStep.DetectedSteps;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
@@ -136,6 +103,9 @@ export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
export type FetchPackage = buildStep.FetchPackage;
|
||||
export type FetchRefusal = buildStep.FetchRefusal;
|
||||
export type KeptArtifactAnswer = buildStep.KeptArtifactAnswer;
|
||||
export type KeptArtifactInput = buildStep.KeptArtifactInput;
|
||||
export type KeptResult = buildStep.KeptResult;
|
||||
export type LevelAnswer = buildStep.LevelAnswer;
|
||||
export type LevelAnswerDigest = buildStep.LevelAnswerDigest;
|
||||
export type LevelAnswerDigestNeedsItem = buildStep.LevelAnswerDigestNeedsItem;
|
||||
@@ -160,8 +130,15 @@ export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type StepEnded = buildStep.StepEnded;
|
||||
export type StepEndedEvent = buildStep.StepEndedEvent;
|
||||
export type StepNames = buildStep.StepNames;
|
||||
export type StepResult = buildStep.StepResult;
|
||||
export type StepRun = buildStep.StepRun;
|
||||
export type StepsAnswer = buildStep.StepsAnswer;
|
||||
export type StepsInput = buildStep.StepsInput;
|
||||
export type TakenVersion = buildStep.TakenVersion;
|
||||
export type TestCounts = buildStep.TestCounts;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
export type ToolchainUsed = buildStep.ToolchainUsed;
|
||||
|
||||
@@ -171,6 +148,9 @@ export type DeliveryAccept = StepAsk;
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of step. */
|
||||
export type StepAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
@@ -189,3 +169,6 @@ export type PausesByCapacityNodeValue = Capacity;
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
/** is one value of the state detected-steps under the key <module>.<artifact>. */
|
||||
export type DetectedStepsByModuleArtifactValue = DetectedSteps;
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
// 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.
|
||||
|
||||
export const seat = "node-build-image";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
step: "step",
|
||||
recheck: "recheck",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export const family = { name: "node-build-image.events", maxAgeDays: 7 };
|
||||
|
||||
export const stepEndedStream = "SEAT_node-build-image_step-ended";
|
||||
|
||||
export function stepEndedSubject(node) {
|
||||
return "mesh.seat.node-build-image.event.step-ended." + node;
|
||||
}
|
||||
|
||||
export const stepEndedSubjectAll = "mesh.seat.node-build-image.event.step-ended.*";
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-image.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-image.accept.check";
|
||||
|
||||
export const stepSubject = "mesh.seat.node-build-image.accept.step";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-image.accept.recheck";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
detectedSteps: "detected-steps",
|
||||
};
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node, id) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id) {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node) {
|
||||
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) {
|
||||
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, language) {
|
||||
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) {
|
||||
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 };
|
||||
}
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export function detectedStepsByModuleArtifactKey(module, artifact) {
|
||||
return module + "." + artifact;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export function parseDetectedStepsByModuleArtifactKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const artifact = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, artifact };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-image, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-image",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+180
-8
@@ -2,12 +2,18 @@
|
||||
|
||||
// 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",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
export interface AskArtifact {
|
||||
@@ -20,6 +26,8 @@ export interface AskArtifact {
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuiltArtifact[];
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
@@ -63,6 +71,20 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
export interface DetectedStep {
|
||||
/** the packages the step runs, by the language's convention */
|
||||
"packages"?: string[];
|
||||
"step": "lint" | "unit" | "integration";
|
||||
}
|
||||
|
||||
/** the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326) */
|
||||
export interface DetectedSteps {
|
||||
"at"?: string;
|
||||
"fingerprint": string;
|
||||
"steps": DetectedStep[];
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -133,6 +155,18 @@ export interface FetchRefusal {
|
||||
"reason": string;
|
||||
}
|
||||
|
||||
/** a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names */
|
||||
export interface KeptResult {
|
||||
/** sha256:<hex> of what the package's tests read */
|
||||
"digest": string;
|
||||
/** unit or integration */
|
||||
"level": string;
|
||||
"package": string;
|
||||
/** the pipeline whose step kept it */
|
||||
"pipeline"?: string;
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
export interface LevelAnswerDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
@@ -323,7 +357,7 @@ export interface StepAsk {
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
/** build, check, compose or step */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
@@ -332,11 +366,57 @@ export interface StepAsk {
|
||||
"packages"?: Record<string, string>;
|
||||
/** a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose */
|
||||
"run"?: RunJob;
|
||||
/** a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*) */
|
||||
"step"?: StepRun;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
/** a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at */
|
||||
export interface StepEnded {
|
||||
"artifact": string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the packages not run because the ask's kept results held them */
|
||||
"carried"?: KeptResult[];
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
"fingerprint": string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** the packages that passed at their digest, for the runner to keep */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
/** the node that ran it, as in the subject */
|
||||
"node": string;
|
||||
/** never passed for a step that ran nothing */
|
||||
"outcome": "passed" | "failed" | "nothing to run" | "could not run";
|
||||
/** the step's output when it fits the message */
|
||||
"output"?: string;
|
||||
/** the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16) */
|
||||
"output-object"?: string;
|
||||
"pipeline": string;
|
||||
"rerun"?: boolean;
|
||||
/** why it failed or could not run, naming the part not heard */
|
||||
"said"?: string;
|
||||
"started"?: string;
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"tests"?: TestCounts;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part */
|
||||
export interface StepNames {
|
||||
/** every watched branch a registration names */
|
||||
"branches": string[];
|
||||
/** every module the registrations name */
|
||||
"modules": string[];
|
||||
/** every repository a registration's git origin names, as <owner>/<name> */
|
||||
"repositories": string[];
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
export interface StepResult {
|
||||
"artifacts"?: BuiltArtifact[];
|
||||
"built"?: boolean;
|
||||
@@ -346,6 +426,8 @@ export interface StepResult {
|
||||
"exit"?: number;
|
||||
"fetch"?: FetchAnswer;
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"key"?: string;
|
||||
/** what the holder's node lacks of it */
|
||||
"lacks"?: string[];
|
||||
@@ -362,6 +444,35 @@ export interface StepResult {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip */
|
||||
export interface StepRun {
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch"?: string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the commit the step runs at */
|
||||
"commit": string;
|
||||
/** where the step reads the change's heads */
|
||||
"fetch": Fetch;
|
||||
/** the artifact's build-input fingerprint at the commit */
|
||||
"fingerprint": string;
|
||||
/** the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*) */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
"names": StepNames;
|
||||
/** the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the step is asked again by the runner's rerun */
|
||||
"rerun"?: boolean;
|
||||
/** the source revision of the watched branch the pipeline runs for; absent for a run on request */
|
||||
"revision"?: number;
|
||||
/** the pipeline step */
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
/** of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said */
|
||||
export interface TakenVersion {
|
||||
"asked": string;
|
||||
@@ -373,6 +484,12 @@ export interface TakenVersion {
|
||||
"sum"?: string;
|
||||
}
|
||||
|
||||
/** how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget) */
|
||||
export interface TestCounts {
|
||||
"integration"?: number;
|
||||
"unit"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -426,3 +543,58 @@ export interface DropInput {
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what kept-artifact takes. */
|
||||
export interface KeptArtifactInput {
|
||||
/** the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it */
|
||||
"digest": string;
|
||||
/** its build's fingerprint */
|
||||
"fp": string;
|
||||
/** the module, the holder of oci-artifact-registry */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what kept-artifact answers. */
|
||||
export interface KeptArtifactAnswer {
|
||||
/** the digest of the bytes kept */
|
||||
"digest"?: string;
|
||||
/** why it could not answer */
|
||||
"error"?: string;
|
||||
/** the fingerprint asked */
|
||||
"fp": string;
|
||||
/** the module asked */
|
||||
"module": string;
|
||||
/** the object's name in it: the digest */
|
||||
"object"?: string;
|
||||
/** why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest */
|
||||
"refused"?: "claims no oci-artifact-registry" | "not kept" | "digest differs";
|
||||
/** bytes */
|
||||
"size"?: number;
|
||||
/** the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus */
|
||||
"store"?: string;
|
||||
/** the refusal in words, naming the module */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is what steps takes. */
|
||||
export interface StepsInput {
|
||||
/** find them anew, not from the kept answer */
|
||||
"again"?: boolean;
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
"fetch": Fetch;
|
||||
"fingerprint"?: string;
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what steps answers. */
|
||||
export interface StepsAnswer {
|
||||
"artifact": string;
|
||||
"fingerprint"?: string;
|
||||
/** answered from the kept answer */
|
||||
"kept"?: boolean;
|
||||
"steps": DetectedStep[];
|
||||
}
|
||||
|
||||
/** is the body of the event step-ended. */
|
||||
export type StepEndedEvent = StepEnded;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export {};
|
||||
Vendored
+72
-89
@@ -4,121 +4,86 @@
|
||||
|
||||
import type * as buildStep from "./parts/build-step.js";
|
||||
|
||||
export const seat = "node-build-node";
|
||||
export declare const seat: "node-build-node";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
recheck: "recheck",
|
||||
} as const;
|
||||
export declare const accepts: {
|
||||
readonly delivery: "delivery";
|
||||
readonly check: "check";
|
||||
readonly step: "step";
|
||||
readonly recheck: "recheck";
|
||||
};
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-node.accept.delivery";
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-node.accept.check";
|
||||
export declare const family: { readonly name: "node-build-node.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-node.accept.recheck";
|
||||
export declare const stepEndedStream: "SEAT_node-build-node_step-ended";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
} as const;
|
||||
export declare function stepEndedSubject(node: string): string;
|
||||
|
||||
export declare const stepEndedSubjectAll: "mesh.seat.node-build-node.event.step-ended.*";
|
||||
|
||||
export declare const deliverySubject: "mesh.seat.node-build-node.accept.delivery";
|
||||
|
||||
export declare const checkSubject: "mesh.seat.node-build-node.accept.check";
|
||||
|
||||
export declare const stepSubject: "mesh.seat.node-build-node.accept.step";
|
||||
|
||||
export declare const recheckSubject: "mesh.seat.node-build-node.accept.recheck";
|
||||
|
||||
export declare const states: {
|
||||
readonly steps: "steps";
|
||||
readonly pauses: "pauses";
|
||||
readonly toolchains: "toolchains";
|
||||
readonly detectedSteps: "detected-steps";
|
||||
};
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function stepsByNodeIDKey(node: string, id: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parseStepsByNodeIDKey(_key: string): { node: string; id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "paused.<node>". */
|
||||
export function pausesByPausedNodeKey(node: string): string {
|
||||
return "paused." + node;
|
||||
}
|
||||
export declare function pausesByPausedNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByPausedNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id: string): string {
|
||||
return "dropped." + id;
|
||||
}
|
||||
export declare function pausesByDroppedIDKey(id: string): string;
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
export declare function parsePausesByDroppedIDKey(_key: string): { id: string } | undefined;
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node: string): string {
|
||||
return "capacity." + node;
|
||||
}
|
||||
export declare function pausesByCapacityNodeKey(node: string): string;
|
||||
|
||||
/** 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 };
|
||||
}
|
||||
export declare function parsePausesByCapacityNodeKey(_key: string): { node: string } | undefined;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
export declare function toolchainsByNodeLanguageKey(node: string, language: string): string;
|
||||
|
||||
/** 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 declare function parseToolchainsByNodeLanguageKey(_key: string): { node: string; language: string } | undefined;
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export declare function detectedStepsByModuleArtifactKey(module: string, artifact: string): string;
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export declare function parseDetectedStepsByModuleArtifactKey(_key: string): { module: string; artifact: string } | undefined;
|
||||
|
||||
export type AskArtifact = buildStep.AskArtifact;
|
||||
export type BuildAnswer = buildStep.BuildAnswer;
|
||||
@@ -128,6 +93,8 @@ export type CheckAnswer = buildStep.CheckAnswer;
|
||||
export type ComposeAnswer = buildStep.ComposeAnswer;
|
||||
export type CurrentAnswer = buildStep.CurrentAnswer;
|
||||
export type CurrentInput = buildStep.CurrentInput;
|
||||
export type DetectedStep = buildStep.DetectedStep;
|
||||
export type DetectedSteps = buildStep.DetectedSteps;
|
||||
export type Drop = buildStep.Drop;
|
||||
export type DropAnswer = buildStep.DropAnswer;
|
||||
export type DropInput = buildStep.DropInput;
|
||||
@@ -136,6 +103,9 @@ export type FetchAnswer = buildStep.FetchAnswer;
|
||||
export type FetchBesideItem = buildStep.FetchBesideItem;
|
||||
export type FetchPackage = buildStep.FetchPackage;
|
||||
export type FetchRefusal = buildStep.FetchRefusal;
|
||||
export type KeptArtifactAnswer = buildStep.KeptArtifactAnswer;
|
||||
export type KeptArtifactInput = buildStep.KeptArtifactInput;
|
||||
export type KeptResult = buildStep.KeptResult;
|
||||
export type LevelAnswer = buildStep.LevelAnswer;
|
||||
export type LevelAnswerDigest = buildStep.LevelAnswerDigest;
|
||||
export type LevelAnswerDigestNeedsItem = buildStep.LevelAnswerDigestNeedsItem;
|
||||
@@ -160,8 +130,15 @@ export type StepAsk = buildStep.StepAsk;
|
||||
export type StepAskBuild = buildStep.StepAskBuild;
|
||||
export type StepAskCheck = buildStep.StepAskCheck;
|
||||
export type StepAskCompose = buildStep.StepAskCompose;
|
||||
export type StepEnded = buildStep.StepEnded;
|
||||
export type StepEndedEvent = buildStep.StepEndedEvent;
|
||||
export type StepNames = buildStep.StepNames;
|
||||
export type StepResult = buildStep.StepResult;
|
||||
export type StepRun = buildStep.StepRun;
|
||||
export type StepsAnswer = buildStep.StepsAnswer;
|
||||
export type StepsInput = buildStep.StepsInput;
|
||||
export type TakenVersion = buildStep.TakenVersion;
|
||||
export type TestCounts = buildStep.TestCounts;
|
||||
export type Toolchain = buildStep.Toolchain;
|
||||
export type ToolchainUsed = buildStep.ToolchainUsed;
|
||||
|
||||
@@ -171,6 +148,9 @@ export type DeliveryAccept = StepAsk;
|
||||
/** is the body of check. */
|
||||
export type CheckAccept = StepAsk;
|
||||
|
||||
/** is the body of step. */
|
||||
export type StepAccept = StepAsk;
|
||||
|
||||
/** is the body of recheck. */
|
||||
export type RecheckAccept = StepAsk;
|
||||
|
||||
@@ -189,3 +169,6 @@ export type PausesByCapacityNodeValue = Capacity;
|
||||
/** is one value of the state toolchains under the key <node>.<language>. */
|
||||
export type ToolchainsByNodeLanguageValue = Toolchain;
|
||||
|
||||
/** is one value of the state detected-steps under the key <module>.<artifact>. */
|
||||
export type DetectedStepsByModuleArtifactValue = DetectedSteps;
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
// 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.
|
||||
|
||||
export const seat = "node-build-node";
|
||||
|
||||
export const verbs = {
|
||||
current: "current",
|
||||
pause: "pause",
|
||||
resume: "resume",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const accepts = {
|
||||
delivery: "delivery",
|
||||
check: "check",
|
||||
step: "step",
|
||||
recheck: "recheck",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export const family = { name: "node-build-node.events", maxAgeDays: 7 };
|
||||
|
||||
export const stepEndedStream = "SEAT_node-build-node_step-ended";
|
||||
|
||||
export function stepEndedSubject(node) {
|
||||
return "mesh.seat.node-build-node.event.step-ended." + node;
|
||||
}
|
||||
|
||||
export const stepEndedSubjectAll = "mesh.seat.node-build-node.event.step-ended.*";
|
||||
|
||||
export const deliverySubject = "mesh.seat.node-build-node.accept.delivery";
|
||||
|
||||
export const checkSubject = "mesh.seat.node-build-node.accept.check";
|
||||
|
||||
export const stepSubject = "mesh.seat.node-build-node.accept.step";
|
||||
|
||||
export const recheckSubject = "mesh.seat.node-build-node.accept.recheck";
|
||||
|
||||
export const states = {
|
||||
steps: "steps",
|
||||
pauses: "pauses",
|
||||
toolchains: "toolchains",
|
||||
detectedSteps: "detected-steps",
|
||||
};
|
||||
|
||||
/** The key of one value of the state steps under the form "<node>.<id>". */
|
||||
export function stepsByNodeIDKey(node, id) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 "dropped.<id>". */
|
||||
export function pausesByDroppedIDKey(id) {
|
||||
return "dropped." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "dropped.<id>", or undefined for a key of another form. */
|
||||
export function parsePausesByDroppedIDKey(_key) {
|
||||
let _rest = _key;
|
||||
if (!_rest.startsWith("dropped.")) return undefined;
|
||||
_rest = _rest.slice(8);
|
||||
if (_rest === "") return undefined;
|
||||
const id = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pauses under the form "capacity.<node>". */
|
||||
export function pausesByCapacityNodeKey(node) {
|
||||
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) {
|
||||
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, language) {
|
||||
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) {
|
||||
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 };
|
||||
}
|
||||
|
||||
/** The key of one value of the state detected-steps under the form "<module>.<artifact>". */
|
||||
export function detectedStepsByModuleArtifactKey(module, artifact) {
|
||||
return module + "." + artifact;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<module>.<artifact>", or undefined for a key of another form. */
|
||||
export function parseDetectedStepsByModuleArtifactKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const module = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const artifact = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { module, artifact };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat node-build-node, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-node-build-node",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+180
-8
@@ -2,12 +2,18 @@
|
||||
|
||||
// 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",
|
||||
drop: "drop",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly current: "current";
|
||||
readonly pause: "pause";
|
||||
readonly resume: "resume";
|
||||
readonly drop: "drop";
|
||||
readonly keptArtifact: "kept-artifact";
|
||||
readonly steps: "steps";
|
||||
};
|
||||
|
||||
export declare const events: {
|
||||
readonly stepEnded: "step-ended";
|
||||
};
|
||||
|
||||
/** one artifact of a build ask: built from the fetched tree, or copied from an upstream pin */
|
||||
export interface AskArtifact {
|
||||
@@ -20,6 +26,8 @@ export interface AskArtifact {
|
||||
export interface BuildAnswer {
|
||||
"artifacts": BuiltArtifact[];
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"out-of-step"?: string[];
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
@@ -63,6 +71,20 @@ export interface ComposeAnswer {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
export interface DetectedStep {
|
||||
/** the packages the step runs, by the language's convention */
|
||||
"packages"?: string[];
|
||||
"step": "lint" | "unit" | "integration";
|
||||
}
|
||||
|
||||
/** the steps detected for one artifact at its newest build-input fingerprint, replaced when a newer fingerprint is detected and by steps with again (design 47 G section 326) */
|
||||
export interface DetectedSteps {
|
||||
"at"?: string;
|
||||
"fingerprint": string;
|
||||
"steps": DetectedStep[];
|
||||
"v": number;
|
||||
}
|
||||
|
||||
/** an ask a caller no longer waits for */
|
||||
export interface Drop {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -133,6 +155,18 @@ export interface FetchRefusal {
|
||||
"reason": string;
|
||||
}
|
||||
|
||||
/** a package's passing result the runner keeps, by the digest of what its tests read (ADR 0666 section 8): the step runs no package whose digest and level it names */
|
||||
export interface KeptResult {
|
||||
/** sha256:<hex> of what the package's tests read */
|
||||
"digest": string;
|
||||
/** unit or integration */
|
||||
"level": string;
|
||||
"package": string;
|
||||
/** the pipeline whose step kept it */
|
||||
"pipeline"?: string;
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
export interface LevelAnswerDigestNeedsItem {
|
||||
"needs"?: string[];
|
||||
"package"?: string;
|
||||
@@ -323,7 +357,7 @@ export interface StepAsk {
|
||||
"check"?: StepAskCheck;
|
||||
"compose"?: StepAskCompose;
|
||||
"id": string;
|
||||
/** build, check or compose */
|
||||
/** build, check, compose or step */
|
||||
"kind": string;
|
||||
/** go, typescript or image */
|
||||
"language": string;
|
||||
@@ -332,11 +366,57 @@ export interface StepAsk {
|
||||
"packages"?: Record<string, string>;
|
||||
/** a run: a program built from a change and run in the build seat's sandbox over the heads, its input asked of a verb of the asker's seat; the Go seat's check stream alone carries it, as a compose */
|
||||
"run"?: RunJob;
|
||||
/** a pipeline step: lint, unit tests or integration tests of one artifact at one commit, sent by the runner as the accepted kind step (design 47 *The steps and who serves them*) */
|
||||
"step"?: StepRun;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports and out-of-step modules; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
/** a pipeline step's end, said by the build seat's holder on the node that ran it (ADR 0666 sections 7, 21): the runner takes it only from that holder's account, naming the ask, the commit and the fingerprint it was asked at */
|
||||
export interface StepEnded {
|
||||
"artifact": string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the packages not run because the ask's kept results held them */
|
||||
"carried"?: KeptResult[];
|
||||
"commit": string;
|
||||
"ended"?: string;
|
||||
"fingerprint": string;
|
||||
/** the ask's id */
|
||||
"id": string;
|
||||
/** the packages that passed at their digest, for the runner to keep */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
/** the node that ran it, as in the subject */
|
||||
"node": string;
|
||||
/** never passed for a step that ran nothing */
|
||||
"outcome": "passed" | "failed" | "nothing to run" | "could not run";
|
||||
/** the step's output when it fits the message */
|
||||
"output"?: string;
|
||||
/** the output's object in the sender's sent store, when over the per-message limit (ADR 0666 section 16) */
|
||||
"output-object"?: string;
|
||||
"pipeline": string;
|
||||
"rerun"?: boolean;
|
||||
/** why it failed or could not run, naming the part not heard */
|
||||
"said"?: string;
|
||||
"started"?: string;
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"tests"?: TestCounts;
|
||||
/** the layout version */
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** the names the registrations hold, which the lint step refuses fixed in code logic (ADR 0666 section 5, seams ruling M7): carried in the ask, never read by the build module from another part */
|
||||
export interface StepNames {
|
||||
/** every watched branch a registration names */
|
||||
"branches": string[];
|
||||
/** every module the registrations name */
|
||||
"modules": string[];
|
||||
/** every repository a registration's git origin names, as <owner>/<name> */
|
||||
"repositories": string[];
|
||||
}
|
||||
|
||||
/** what a step answered, by the kind of ask: a build's artifacts, toolchain, imports, out-of-step modules and the artifact it kept; a check's fetch and levels; a compose's built, key and verdict; a run's built, key, exit, output and said; a declined ask's declined, needs and lacks. The fields of the kinds do not meet, so one layout holds the five */
|
||||
export interface StepResult {
|
||||
"artifacts"?: BuiltArtifact[];
|
||||
"built"?: boolean;
|
||||
@@ -346,6 +426,8 @@ export interface StepResult {
|
||||
"exit"?: number;
|
||||
"fetch"?: FetchAnswer;
|
||||
"imports"?: string[];
|
||||
/** the digest of the artifact this node kept for the artifact store's holder instead of storing it through the seat oci-artifact-registry (the verb kept-artifact serves it); the keeping node is the step's own; absent when every artifact was stored */
|
||||
"kept"?: string;
|
||||
"key"?: string;
|
||||
/** what the holder's node lacks of it */
|
||||
"lacks"?: string[];
|
||||
@@ -362,6 +444,35 @@ export interface StepResult {
|
||||
"verdict"?: unknown;
|
||||
}
|
||||
|
||||
/** one pipeline step of one artifact at one commit (ADR 0666 sections 7, 8, 17): the step a build seat runs in its sandbox from the change's own heads, the names the lint step needs and the kept results it may skip */
|
||||
export interface StepRun {
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
/** the watched branch, or the branch of a run on request */
|
||||
"branch"?: string;
|
||||
/** for a rerun, the caller the runtime proved */
|
||||
"by"?: string;
|
||||
/** the commit the step runs at */
|
||||
"commit": string;
|
||||
/** where the step reads the change's heads */
|
||||
"fetch": Fetch;
|
||||
/** the artifact's build-input fingerprint at the commit */
|
||||
"fingerprint": string;
|
||||
/** the kept results of the artifact's packages, by digest and level (design 47 *Carried, not run*) */
|
||||
"kept"?: KeptResult[];
|
||||
"module": string;
|
||||
"names": StepNames;
|
||||
/** the runner's pipeline key, <branch>.<revision>.<module>, a branch escaped as a key's name is */
|
||||
"pipeline": string;
|
||||
/** the step is asked again by the runner's rerun */
|
||||
"rerun"?: boolean;
|
||||
/** the source revision of the watched branch the pipeline runs for; absent for a run on request */
|
||||
"revision"?: number;
|
||||
/** the pipeline step */
|
||||
"step": "lint" | "unit" | "integration";
|
||||
"toolchain"?: ToolchainUsed;
|
||||
}
|
||||
|
||||
/** of a directory whose go.mod requires an asked mesh package, the version it is built against: the asked one, or go.mod's when it names a newer one, said */
|
||||
export interface TakenVersion {
|
||||
"asked": string;
|
||||
@@ -373,6 +484,12 @@ export interface TakenVersion {
|
||||
"sum"?: string;
|
||||
}
|
||||
|
||||
/** how many tests a step ran and carried, per level (ADR 0666 section 8: the pipeline's end names any repository or catalog module over the test budget) */
|
||||
export interface TestCounts {
|
||||
"integration"?: number;
|
||||
"unit"?: number;
|
||||
}
|
||||
|
||||
/** the toolchain a node reports */
|
||||
export interface Toolchain {
|
||||
/** when (RFC 3339 time) */
|
||||
@@ -426,3 +543,58 @@ export interface DropInput {
|
||||
/** is what drop answers. */
|
||||
export type DropAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what kept-artifact takes. */
|
||||
export interface KeptArtifactInput {
|
||||
/** the artifact's sha256, 64 lowercase hex digits, as the builder's done key names it */
|
||||
"digest": string;
|
||||
/** its build's fingerprint */
|
||||
"fp": string;
|
||||
/** the module, the holder of oci-artifact-registry */
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what kept-artifact answers. */
|
||||
export interface KeptArtifactAnswer {
|
||||
/** the digest of the bytes kept */
|
||||
"digest"?: string;
|
||||
/** why it could not answer */
|
||||
"error"?: string;
|
||||
/** the fingerprint asked */
|
||||
"fp": string;
|
||||
/** the module asked */
|
||||
"module": string;
|
||||
/** the object's name in it: the digest */
|
||||
"object"?: string;
|
||||
/** why nothing is answered: the module claims no oci-artifact-registry, this node keeps no build of it at that fingerprint (never kept, or swept), or keeps it under another digest */
|
||||
"refused"?: "claims no oci-artifact-registry" | "not kept" | "digest differs";
|
||||
/** bytes */
|
||||
"size"?: number;
|
||||
/** the object store the bytes are in, the build module's kept builds, as its manifest's objects names it on the bus */
|
||||
"store"?: string;
|
||||
/** the refusal in words, naming the module */
|
||||
"words"?: string;
|
||||
}
|
||||
|
||||
/** is what steps takes. */
|
||||
export interface StepsInput {
|
||||
/** find them anew, not from the kept answer */
|
||||
"again"?: boolean;
|
||||
/** the artifact reference, <module>:<artifact> */
|
||||
"artifact": string;
|
||||
"fetch": Fetch;
|
||||
"fingerprint"?: string;
|
||||
"module": string;
|
||||
}
|
||||
|
||||
/** is what steps answers. */
|
||||
export interface StepsAnswer {
|
||||
"artifact": string;
|
||||
"fingerprint"?: string;
|
||||
/** answered from the kept answer */
|
||||
"kept"?: boolean;
|
||||
"steps": DetectedStep[];
|
||||
}
|
||||
|
||||
/** is the body of the event step-ended. */
|
||||
export type StepEndedEvent = StepEnded;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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",
|
||||
drop: "drop",
|
||||
keptArtifact: "kept-artifact",
|
||||
steps: "steps",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
stepEnded: "step-ended",
|
||||
};
|
||||
|
||||
export {};
|
||||
+18
-18
@@ -4,31 +4,31 @@
|
||||
|
||||
import type * as registry from "./parts/registry.js";
|
||||
|
||||
export const seat = "npm-package-registry";
|
||||
export declare const seat: "npm-package-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
export const family = { name: "npm-package-registry.events", maxAgeDays: 7 } as const;
|
||||
export declare const family: { readonly name: "npm-package-registry.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.npm-package-registry.event.published";
|
||||
export declare const publishedSubject: "mesh.seat.npm-package-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.npm-package-registry.event.refused";
|
||||
export declare const refusedSubject: "mesh.seat.npm-package-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.npm-package-registry.event.removed";
|
||||
export declare const removedSubject: "mesh.seat.npm-package-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.npm-package-registry.event.kept";
|
||||
export declare const keptSubject: "mesh.seat.npm-package-registry.event.kept";
|
||||
|
||||
export type Artifact = registry.Artifact;
|
||||
export type KeptEvent = registry.KeptEvent;
|
||||
@@ -0,0 +1,30 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "npm-package-registry", defined whole (seats/npm-package-registry/seat.json): The mesh's npm packages: the npm registry protocol's read side, and publishing over the bus.
|
||||
|
||||
export const seat = "npm-package-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export const family = { name: "npm-package-registry.events", maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.npm-package-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.npm-package-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.npm-package-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.npm-package-registry.event.kept";
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat npm-package-registry, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-npm-package-registry",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+12
-12
@@ -2,19 +2,19 @@
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
/** one published thing, as every registry event and answer names it */
|
||||
export interface Artifact {
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export {};
|
||||
+33
-59
@@ -4,83 +4,57 @@
|
||||
|
||||
import type * as registry from "./parts/registry.js";
|
||||
|
||||
export const seat = "oci-artifact-registry";
|
||||
export declare const seat: "oci-artifact-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
hold: "hold",
|
||||
release: "release",
|
||||
list: "list",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
readonly hold: "hold";
|
||||
readonly release: "release";
|
||||
readonly list: "list";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
held: "held",
|
||||
released: "released",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
readonly held: "held";
|
||||
readonly released: "released";
|
||||
};
|
||||
|
||||
export const family = { name: "oci-artifact-registry.events", maxAgeDays: 7 } as const;
|
||||
export declare const family: { readonly name: "oci-artifact-registry.events"; readonly maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.oci-artifact-registry.event.published";
|
||||
export declare const publishedSubject: "mesh.seat.oci-artifact-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.oci-artifact-registry.event.refused";
|
||||
export declare const refusedSubject: "mesh.seat.oci-artifact-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.oci-artifact-registry.event.removed";
|
||||
export declare const removedSubject: "mesh.seat.oci-artifact-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.oci-artifact-registry.event.kept";
|
||||
export declare const keptSubject: "mesh.seat.oci-artifact-registry.event.kept";
|
||||
|
||||
export const heldSubject = "mesh.seat.oci-artifact-registry.event.held";
|
||||
export declare const heldSubject: "mesh.seat.oci-artifact-registry.event.held";
|
||||
|
||||
export const releasedSubject = "mesh.seat.oci-artifact-registry.event.released";
|
||||
export declare const releasedSubject: "mesh.seat.oci-artifact-registry.event.released";
|
||||
|
||||
export const states = {
|
||||
holds: "holds",
|
||||
windows: "windows",
|
||||
} as const;
|
||||
export declare const states: {
|
||||
readonly holds: "holds";
|
||||
readonly windows: "windows";
|
||||
};
|
||||
|
||||
/** The key of one value of the state holds under the form "<seat>.<name>.<digest>". */
|
||||
export function holdsBySeatNameDigestKey(seat: string, name: string, digest: string): string {
|
||||
return seat + "." + name + "." + digest;
|
||||
}
|
||||
export declare function holdsBySeatNameDigestKey(seat: string, name: string, digest: string): string;
|
||||
|
||||
/** The parts of a key of the form "<seat>.<name>.<digest>", or undefined for a key of another form. */
|
||||
export function parseHoldsBySeatNameDigestKey(_key: string): { seat: string; name: string; digest: string } | undefined {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const seat = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const name = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { seat, name, digest };
|
||||
}
|
||||
export declare function parseHoldsBySeatNameDigestKey(_key: string): { seat: string; name: string; digest: string } | undefined;
|
||||
|
||||
/** The key of one value of the state windows under the form "<caller>". */
|
||||
export function windowsByCallerKey(caller: string): string {
|
||||
return caller;
|
||||
}
|
||||
export declare function windowsByCallerKey(caller: string): string;
|
||||
|
||||
/** The parts of a key of the form "<caller>", or undefined for a key of another form. */
|
||||
export function parseWindowsByCallerKey(_key: string): { caller: string } | undefined {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const caller = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { caller };
|
||||
}
|
||||
export declare function parseWindowsByCallerKey(_key: string): { caller: string } | undefined;
|
||||
|
||||
export type Artifact = registry.Artifact;
|
||||
export type KeptEvent = registry.KeptEvent;
|
||||
@@ -0,0 +1,82 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "oci-artifact-registry", defined whole (seats/oci-artifact-registry/seat.json): The mesh's bundles and archives, by digest, in the one artifact store: the OCI distribution protocol's read side.
|
||||
|
||||
export const seat = "oci-artifact-registry";
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
hold: "hold",
|
||||
release: "release",
|
||||
list: "list",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
held: "held",
|
||||
released: "released",
|
||||
};
|
||||
|
||||
export const family = { name: "oci-artifact-registry.events", maxAgeDays: 7 };
|
||||
|
||||
export const publishedSubject = "mesh.seat.oci-artifact-registry.event.published";
|
||||
|
||||
export const refusedSubject = "mesh.seat.oci-artifact-registry.event.refused";
|
||||
|
||||
export const removedSubject = "mesh.seat.oci-artifact-registry.event.removed";
|
||||
|
||||
export const keptSubject = "mesh.seat.oci-artifact-registry.event.kept";
|
||||
|
||||
export const heldSubject = "mesh.seat.oci-artifact-registry.event.held";
|
||||
|
||||
export const releasedSubject = "mesh.seat.oci-artifact-registry.event.released";
|
||||
|
||||
export const states = {
|
||||
holds: "holds",
|
||||
windows: "windows",
|
||||
};
|
||||
|
||||
/** The key of one value of the state holds under the form "<seat>.<name>.<digest>". */
|
||||
export function holdsBySeatNameDigestKey(seat, name, digest) {
|
||||
return seat + "." + name + "." + digest;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<seat>.<name>.<digest>", or undefined for a key of another form. */
|
||||
export function parseHoldsBySeatNameDigestKey(_key) {
|
||||
let _rest = _key;
|
||||
const _at0 = _rest.indexOf(".");
|
||||
if (_at0 <= 0) return undefined;
|
||||
const seat = _rest.slice(0, _at0);
|
||||
_rest = _rest.slice(_at0 + 1);
|
||||
const _at2 = _rest.indexOf(".");
|
||||
if (_at2 <= 0) return undefined;
|
||||
const name = _rest.slice(0, _at2);
|
||||
_rest = _rest.slice(_at2 + 1);
|
||||
if (_rest === "") return undefined;
|
||||
const digest = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { seat, name, digest };
|
||||
}
|
||||
|
||||
/** The key of one value of the state windows under the form "<caller>". */
|
||||
export function windowsByCallerKey(caller) {
|
||||
return caller;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<caller>", or undefined for a key of another form. */
|
||||
export function parseWindowsByCallerKey(_key) {
|
||||
let _rest = _key;
|
||||
if (_rest === "") return undefined;
|
||||
const caller = _rest;
|
||||
_rest = "";
|
||||
if (_rest !== "") return undefined;
|
||||
return { caller };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"description": "The contract of the seat oci-artifact-registry, generated from its definition.",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
".": {
|
||||
"default": "./index.js",
|
||||
"types": "./index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"parts"
|
||||
],
|
||||
"name": "@novox/mesh-delivery-contracts-oci-artifact-registry",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"types": "./index.d.ts",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
|
||||
+12
-12
@@ -2,19 +2,19 @@
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
} as const;
|
||||
export declare const verbs: {
|
||||
readonly publish: "publish";
|
||||
readonly publishPart: "publish-part";
|
||||
readonly versions: "versions";
|
||||
readonly remove: "remove";
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
} as const;
|
||||
export declare const events: {
|
||||
readonly published: "published";
|
||||
readonly refused: "refused";
|
||||
readonly removed: "removed";
|
||||
readonly kept: "kept";
|
||||
};
|
||||
|
||||
/** one published thing, as every registry event and answer names it */
|
||||
export interface Artifact {
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The part "registry" several seats include whole: The verbs and events every registry seat shares, written once so the four cannot drift (design 51, design 26). Who may call each verb is the holder's trusted config value listing its callers (ADR 0363's form), checked against the caller the tool runner proved.
|
||||
|
||||
export const verbs = {
|
||||
publish: "publish",
|
||||
publishPart: "publish-part",
|
||||
versions: "versions",
|
||||
remove: "remove",
|
||||
};
|
||||
|
||||
export const events = {
|
||||
published: "published",
|
||||
refused: "refused",
|
||||
removed: "removed",
|
||||
kept: "kept",
|
||||
};
|
||||
|
||||
export {};
|
||||
Reference in New Issue
Block a user