Record the inputs of a build's source fingerprint in its build record (issue 1215)
This commit is contained in:
@@ -9,6 +9,8 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
|
||||
// What a build says it was made from, as files (novox/hq ADR 0267), and what a build compiling a Go
|
||||
@@ -202,3 +204,20 @@ func TestAGoBundleSaysItsClosureAndAnUntoldImageNothing(t *testing.T) {
|
||||
t.Fatalf("an image compiling nothing it was told of said a build source: %+v", got.Sources)
|
||||
}
|
||||
}
|
||||
|
||||
// 1215/AC1 (compiled here, run by the merge check; the unit level has 1215/AC1 over the same inputs): a build's
|
||||
// result carries every input of its fingerprint, and the SDK function over them gives it again.
|
||||
func TestABuildSaysTheInputsItsFingerprintWasComputedFrom(t *testing.T) {
|
||||
got, _, _ := buildTheProxy(t, aSharedRepository("one", "1"), false)
|
||||
if got.SourceInputs == nil {
|
||||
t.Fatal("the result carries no source inputs")
|
||||
}
|
||||
in := *got.SourceInputs
|
||||
if in.Module != "route-proxy" || in.Tree == "" || in.Contexts["server"] == "" {
|
||||
t.Errorf("the inputs miss the module, its tree or the server's context: %+v", in)
|
||||
}
|
||||
fp, none := delivery.SourceFingerprint(in)
|
||||
if fp == "" || none != "" || fp != got.Source {
|
||||
t.Errorf("the inputs give %q (%q); the build recorded %q", fp, none, got.Source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"github.com/novox/mesh-controller/internal/catalogue"
|
||||
)
|
||||
|
||||
@@ -91,6 +92,10 @@ type Result struct {
|
||||
// (novox/hq issue 280).
|
||||
Source string
|
||||
|
||||
// SourceInputs are what Source was computed from (novox/hq ADR 0437 §5, issue 1215), set also where the source
|
||||
// does not pin the build, so the reason is visible: with them delivery.SourceFingerprint gives Source again.
|
||||
SourceInputs *delivery.SourceInputs
|
||||
|
||||
// ReuseKey is the build's reuse key (novox/hq ADR 0350 §1): its source fingerprint's parts with the builder's
|
||||
// version, and ReuseParts those parts; empty, with NoKey saying why, where the source does not pin the build.
|
||||
ReuseKey string
|
||||
@@ -491,7 +496,7 @@ func build(ctx context.Context, run Runner, publish Publisher,
|
||||
// The reuse key (novox/hq ADR 0350 §1): what a check keeps its build under, and what a walk takes one by.
|
||||
key := keyOf(src, manifest, Version)
|
||||
return Result{Manifest: resolved, Commit: commit, Built: built,
|
||||
Against: against(within, manifest, stoodOn), Read: readBy(manifest), Source: fingerprint,
|
||||
Against: against(within, manifest, stoodOn), Read: readBy(manifest), Source: fingerprint, SourceInputs: resultInputs(src),
|
||||
Trunk: trunk, OnTrunk: onTrunk, Branches: branches, Sources: sources,
|
||||
ReuseKey: key.Key, ReuseParts: key.Parts, NoKey: key.Why, Reused: reused, Why: builtWhy,
|
||||
Predefined: listed}, nil
|
||||
|
||||
@@ -278,6 +278,15 @@ func (s *sourceInputs) inputs() delivery.SourceInputs {
|
||||
}
|
||||
}
|
||||
|
||||
// resultInputs are the inputs a build's result records; nil for a build with no inputs to speak of.
|
||||
func resultInputs(s *sourceInputs) *delivery.SourceInputs {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
in := s.inputs()
|
||||
return &in
|
||||
}
|
||||
|
||||
// fingerprint is the build's source fingerprint, or empty when the source does not pin the build.
|
||||
func (s *sourceInputs) fingerprint() string {
|
||||
if s == nil {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
@@ -81,3 +82,44 @@ func TestTheBuilderFingerprintsWithTheSDKFunction(t *testing.T) {
|
||||
t.Errorf("the SDK function was given %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// 1215/AC1: the inputs a result records, read back, give the fingerprint the build recorded (the live builds of
|
||||
// 1214/AC1), through encoding/json as the build record keeps them.
|
||||
func TestTheInputsAResultRecordsGiveItsFingerprintAgain(t *testing.T) {
|
||||
s := &sourceInputs{module: "build-agent", tree: "11c0b4f90cae0d6e4ef9cc48cbfdf9f6dbe52bca",
|
||||
bases: []string{
|
||||
"sha256:d9e853e87e55526f6b2917df91a2115c36dd7c696a35be12163d44e6e2a4b6bc",
|
||||
"sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c",
|
||||
},
|
||||
contexts: map[string]string{"server": "narrow:d51ca744fd11af59d616c858f76c27b3e58e16e11fbdc0c720eb9d7d19d55fac"}}
|
||||
raw, err := json.Marshal(resultInputs(s))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var back delivery.SourceInputs
|
||||
if err := json.Unmarshal(raw, &back); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := "src1:e846efe73716b78e80860baaac96153de2cb76551325753838ca245d2160a3d7"
|
||||
if fp, none := delivery.SourceFingerprint(back); fp != want || none != "" {
|
||||
t.Errorf("the inputs read back give %q (%q), want %q", fp, none, want)
|
||||
}
|
||||
}
|
||||
|
||||
// 1215/AC3: a build that gets no fingerprint still has its inputs recorded, so the reason is visible.
|
||||
func TestABuildWithNoFingerprintStillSaysItsInputs(t *testing.T) {
|
||||
s := newSourceInputs("app")
|
||||
s.tree = "aaaa"
|
||||
s.notPinned("it resolves packages from the mesh's registry at build time")
|
||||
in := resultInputs(s)
|
||||
if in == nil || in.Module != "app" || in.Tree != "aaaa" || in.Unpinned == "" {
|
||||
t.Fatalf("the inputs of an unpinned build: %+v", in)
|
||||
}
|
||||
if fp, none := delivery.SourceFingerprint(*in); fp != "" || none != in.Unpinned {
|
||||
t.Errorf("the inputs give %q (%q)", fp, none)
|
||||
}
|
||||
noTree := resultInputs(newSourceInputs("app"))
|
||||
if noTree == nil || noTree.Module != "app" || noTree.Tree != "" {
|
||||
t.Errorf("the inputs of a build with no tree: %+v", noTree)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user