Build log: a build narrates between its start and its end (build.said)
Its module, fingerprint, line and why, as design 51 has a build narrate its publish; a start or end carries no line (A3g's finding). Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -132,6 +132,10 @@ const (
|
||||
BuildLogRead = BuilderModule + "." + BuilderLog
|
||||
BuildStartedEvent = "build.started"
|
||||
BuildEndedEvent = "build.ended"
|
||||
// BuildSaidEvent is a build's narration between its start and its end (design 51: a build narrates its publish,
|
||||
// asked, waiting on a seat, stored, refused, at least every five minutes while it waits): its module, fingerprint,
|
||||
// line and why.
|
||||
BuildSaidEvent = "build.said"
|
||||
// BuilderLogDays is how long the log keeps its entries.
|
||||
BuilderLogDays = 30
|
||||
// BuildsSinceTool is the builder's tool answering every ended build since a time, in order (clause 9): its
|
||||
@@ -175,6 +179,9 @@ type BuildLogEntry struct {
|
||||
// sorted and each once, as the build module answered them (BuildAnswer.Imports; novox/hq ADR 0593 §2): the indexer
|
||||
// keeps them on the module (KeptInputs2.Imports) when the build's fingerprint is the module's.
|
||||
Imports []string `json:"imports,omitempty"`
|
||||
// Line is a narration's words, Why what it narrates (asked, waiting, stored, refused): a build.said entry's alone.
|
||||
Line string `json:"line,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// BuildsSince is the answer of BuildsSinceTool: every ended build since a time, oldest first, and whether the log held
|
||||
@@ -214,8 +221,18 @@ func EndedSince(entries []BuildLogEntry, since time.Time) []BuildLogEntry {
|
||||
func EncodeBuildLogEntry(e BuildLogEntry) ([]byte, error) {
|
||||
e.V = Version
|
||||
switch {
|
||||
case e.Event == BuildSaidEvent:
|
||||
switch {
|
||||
case e.Module == "" || e.FP == "" || e.At.IsZero() || e.Line == "":
|
||||
return nil, fmt.Errorf("delivery: a build's narration names its module, fingerprint, line and time")
|
||||
case e.Outcome != "" || len(e.Made) > 0 || e.Manifest != "" || len(e.Against) > 0 || len(e.Imports) > 0:
|
||||
return nil, fmt.Errorf("delivery: a build's narration names no outcome, manifest, base, artifact or import")
|
||||
}
|
||||
return json.Marshal(e)
|
||||
case e.Event != BuildStartedEvent && e.Event != BuildEndedEvent:
|
||||
return nil, fmt.Errorf("delivery: a build log entry is %s or %s, not %q", BuildStartedEvent, BuildEndedEvent, e.Event)
|
||||
return nil, fmt.Errorf("delivery: a build log entry is %s, %s or %s, not %q", BuildStartedEvent, BuildSaidEvent, BuildEndedEvent, e.Event)
|
||||
case e.Line != "" || e.Why != "":
|
||||
return nil, fmt.Errorf("delivery: a build's start or end carries no narration's line")
|
||||
case e.Module == "" || e.FP == "" || e.Node == "" || e.At.IsZero() || e.Repository == "" || e.Commit == "":
|
||||
return nil, fmt.Errorf("delivery: a build log entry names its module, fingerprint, repository, commit, node and time")
|
||||
case e.Event == BuildEndedEvent && e.Outcome == "":
|
||||
|
||||
@@ -75,6 +75,28 @@ func TestPublishedPackagesAndImportsRoundTripAndRefuse(t *testing.T) {
|
||||
if _, err := EncodeBuildLogEntry(end); err == nil {
|
||||
t.Error("unsorted imports encoded")
|
||||
}
|
||||
// A build narrates between its start and its end (build.said): its module, fingerprint, line and why, nothing of an
|
||||
// end; a start or end carries no line.
|
||||
said := BuildLogEntry{Event: BuildSaidEvent, Module: "netcheck", FP: "src2:x", At: good.At,
|
||||
Line: "waiting on container-image-registry", Why: "waiting"}
|
||||
if raw, err := EncodeBuildLogEntry(said); err != nil {
|
||||
t.Errorf("a narration refused: %v", err)
|
||||
} else if e, err := DecodeBuildLogEntry(raw); err != nil || e.Line != said.Line || e.Why != "waiting" {
|
||||
t.Errorf("a narration's round trip: %+v, %v", e, err)
|
||||
}
|
||||
for name, mutate := range map[string]func(e *BuildLogEntry){
|
||||
"a narration with no line": func(e *BuildLogEntry) { e.Line = "" },
|
||||
"a narration with an outcome": func(e *BuildLogEntry) { e.Outcome = "done" },
|
||||
"an end with a line": func(e *BuildLogEntry) {
|
||||
e.Event, e.Outcome, e.Node, e.Repository, e.Commit = BuildEndedEvent, "done", "ace", "novox/mesh-catalog", commit
|
||||
},
|
||||
} {
|
||||
e := said
|
||||
mutate(&e)
|
||||
if _, err := EncodeBuildLogEntry(e); err == nil {
|
||||
t.Errorf("%s encoded", name)
|
||||
}
|
||||
}
|
||||
var answer BuildAnswer
|
||||
if err := json.Unmarshal([]byte(`{"artifacts":[],"imports":["`+sdk+`"]}`), &answer); err != nil || len(answer.Imports) != 1 {
|
||||
t.Fatalf("build answer imports: %v, %v", err, answer.Imports)
|
||||
|
||||
Reference in New Issue
Block a user