Count a build record without a state as the outcome it is (issue 1281): the controller never stores state built
This commit is contained in:
@@ -11,6 +11,7 @@ import "time"
|
||||
type BuildRecord struct {
|
||||
ID string `json:"id"`
|
||||
State string `json:"state,omitempty"`
|
||||
Failed string `json:"failed,omitempty"`
|
||||
Repository string `json:"repository"`
|
||||
Ref string `json:"ref,omitempty"`
|
||||
Module string `json:"module,omitempty"`
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
// internal/inventory/chain_requests.go:19, the module's directory in its repository (Build.Path, internal/chain/records.go:100).
|
||||
// The fixture is a record the controller's own encoder wrote (json.Marshal of a chain.Build, mesh-controller
|
||||
// internal/chain, a throwaway test run once and deleted) with build-agent's build-1792395447088936520 values, plus a
|
||||
// manifest-digest and one made artifact, which a BuildRecord does not carry.
|
||||
// manifest-digest and one made artifact (shape: mesh-controller internal/chain/records.go:91-117 Build, json tags, at commit
|
||||
// 1f708e2d8d72e2c27dbeaba02f14c128d700eada; an outcome has no state key and a build asked after a merge no ref, records.go:57-59), which a BuildRecord does not carry.
|
||||
func loadBuildFixture(t *testing.T) []byte {
|
||||
t.Helper()
|
||||
raw, err := os.ReadFile("testdata/build-record-build-agent.json")
|
||||
@@ -29,10 +30,11 @@ func TestBuildRecordDecodes(t *testing.T) { // 1223/AC1
|
||||
for _, c := range []struct{ name, got, want string }{
|
||||
{"id", r.ID, "build-1792395447088936520"},
|
||||
{"module", r.Module, "build-agent"},
|
||||
{"repository", r.Repository, "novox/mesh-controller"},
|
||||
{"ref", r.Ref, "main"},
|
||||
{"repository", r.Repository, "http://novox.internal:20000/novox/mesh-controller.git"},
|
||||
{"ref", r.Ref, ""},
|
||||
{"commit", r.Commit, "7a74cee83f88e6585a5511c3cc53bdf0f5303d20"},
|
||||
{"state", r.State, "built"},
|
||||
{"state", r.State, ""},
|
||||
{"failed", r.Failed, ""},
|
||||
{"source-fingerprint", r.SourceFingerprint, "src1:e846efe73716b78e80860baaac96153de2cb76551325753838ca245d2160a3d7"},
|
||||
} {
|
||||
if c.got != c.want {
|
||||
@@ -42,6 +44,9 @@ func TestBuildRecordDecodes(t *testing.T) { // 1223/AC1
|
||||
if want := time.Date(2026, 10, 19, 9, 38, 0, 0, time.UTC); !r.At.Equal(want) {
|
||||
t.Errorf("at = %v, want %v", r.At, want)
|
||||
}
|
||||
if !r.IsTrunkBuild() { // 1281/AC7
|
||||
t.Error("the fixture, a record as the controller writes it, is not a trunk build")
|
||||
}
|
||||
if r.SourceInputs == nil {
|
||||
t.Fatal("source-inputs missing")
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"id":"build-1792395447088936520","state":"built","repository":"novox/mesh-controller","ref":"main","module":"build-agent","commit":"7a74cee83f88e6585a5511c3cc53bdf0f5303d20","path":"modules/build-agent","manifest-digest":"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","source-fingerprint":"src1:e846efe73716b78e80860baaac96153de2cb76551325753838ca245d2160a3d7","source-inputs":{"Module":"build-agent","Tree":"11c0b4f90cae0d6e4ef9cc48cbfdf9f6dbe52bca","Bases":["sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc","sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c"],"Contexts":{"server":"narrow:d51ca744fd11af59d616c858f76c27b3e58e16e11fbdc0c720eb9d7d19d55fac"},"Toolchains":null,"Unpinned":""},"made":[{"name":"server","kind":"image","reference":"registry.example/build-agent@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc"}],"at":"2026-10-19T09:38:00Z"}
|
||||
{"id":"build-1792395447088936520","repository":"http://novox.internal:20000/novox/mesh-controller.git","module":"build-agent","commit":"7a74cee83f88e6585a5511c3cc53bdf0f5303d20","path":"modules/build-agent","manifest-digest":"sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef","source-fingerprint":"src1:e846efe73716b78e80860baaac96153de2cb76551325753838ca245d2160a3d7","source-inputs":{"Module":"build-agent","Tree":"11c0b4f90cae0d6e4ef9cc48cbfdf9f6dbe52bca","Bases":["sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc","sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c"],"Contexts":{"server":"narrow:d51ca744fd11af59d616c858f76c27b3e58e16e11fbdc0c720eb9d7d19d55fac"},"Toolchains":null,"Unpinned":""},"made":[{"name":"server","kind":"image","reference":"registry.example/build-agent@sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc"}],"at":"2026-10-19T09:38:00Z"}
|
||||
|
||||
@@ -24,9 +24,9 @@ func SameRepository(a, b string) bool {
|
||||
return a != "" && strings.EqualFold(a, b)
|
||||
}
|
||||
|
||||
// IsTrunkBuild is whether the record is a successful build of the trunk that recorded its source inputs: state built, and
|
||||
// ref "main" or none. A build a delivery plan asked after a merge, or rebuild or build --behind, follows the branch
|
||||
// IsTrunkBuild is whether the record is a successful build of the trunk that recorded its source inputs: an outcome
|
||||
// (the controller writes no state on one; state asked is a request, records.go:57-59), not failed, and ref "main" or none. A build a delivery plan asked after a merge, or rebuild or build --behind, follows the branch
|
||||
// without naming it, so it carries no ref; a build of any other branch or of a commit names it (issue 1281).
|
||||
func (r BuildRecord) IsTrunkBuild() bool {
|
||||
return r.State == "built" && r.SourceInputs != nil && (r.Ref == "" || r.Ref == "main")
|
||||
return r.State == "" && r.Failed == "" && r.SourceInputs != nil && (r.Ref == "" || r.Ref == "main")
|
||||
}
|
||||
|
||||
@@ -42,16 +42,17 @@ func TestIsTrunkBuild(t *testing.T) { // 1281/AC2
|
||||
r BuildRecord
|
||||
want bool
|
||||
}{
|
||||
{"built on main", BuildRecord{State: "built", Ref: "main", SourceInputs: inputs}, true},
|
||||
{"built on main", BuildRecord{Ref: "main", SourceInputs: inputs}, true},
|
||||
// a build a delivery plan asked after a merge, or rebuild / build --behind, carries no ref (live builds,
|
||||
// 2026-10-19: zsh build-1792417485811374131, mesh-delivery build-1792435539606203626)
|
||||
{"built with no ref", BuildRecord{State: "built", SourceInputs: inputs}, true},
|
||||
{"another branch", BuildRecord{State: "built", Ref: "feat/x", SourceInputs: inputs}, false},
|
||||
{"a commit", BuildRecord{State: "built", Ref: "9efdd87a", SourceInputs: inputs}, false},
|
||||
{"failed", BuildRecord{State: "failed", Ref: "main", SourceInputs: inputs}, false},
|
||||
{"no state", BuildRecord{Ref: "main", SourceInputs: inputs}, false},
|
||||
{"no source inputs", BuildRecord{State: "built", Ref: "main"}, false},
|
||||
{"no ref and no source inputs", BuildRecord{State: "built"}, false},
|
||||
{"built with no ref", BuildRecord{SourceInputs: inputs}, true},
|
||||
{"another branch", BuildRecord{Ref: "feat/x", SourceInputs: inputs}, false},
|
||||
{"a commit", BuildRecord{Ref: "9efdd87a", SourceInputs: inputs}, false},
|
||||
{"asked", BuildRecord{State: "asked", SourceInputs: inputs}, false},
|
||||
{"answered, state built", BuildRecord{State: "built", SourceInputs: inputs}, false},
|
||||
{"failed", BuildRecord{Failed: "boom", Ref: "main", SourceInputs: inputs}, false},
|
||||
{"no source inputs", BuildRecord{Ref: "main"}, false},
|
||||
{"no ref and no source inputs", BuildRecord{}, false},
|
||||
} {
|
||||
if got := c.r.IsTrunkBuild(); got != c.want {
|
||||
t.Errorf("%s: IsTrunkBuild = %v, want %v", c.name, got, c.want)
|
||||
@@ -59,7 +60,7 @@ func TestIsTrunkBuild(t *testing.T) { // 1281/AC2
|
||||
}
|
||||
// decoded as the controller writes it: the key "ref" is absent
|
||||
var r BuildRecord
|
||||
raw := `{"id":"build-1792417485811374131","state":"built","repository":"http://novox.internal:20000/novox/mesh-catalog.git","module":"zsh","source-inputs":{"Module":"zsh","Tree":"t"}}`
|
||||
raw := `{"id":"build-1792417485811374131","repository":"http://novox.internal:20000/novox/mesh-catalog.git","module":"zsh","source-inputs":{"Module":"zsh","Tree":"t"}}`
|
||||
if err := json.Unmarshal([]byte(raw), &r); err != nil || !r.IsTrunkBuild() {
|
||||
t.Errorf("a decoded record with no ref: trunk = %v, err %v", r.IsTrunkBuild(), err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user