From ad1f6e6ac2e23b36338440132f9cd4992fa1a3db Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 17:31:40 +0200 Subject: [PATCH] =?UTF-8?q?Name=20the=20build=20errors=20in=20one=20place,?= =?UTF-8?q?=20and=20which=20are=20not=20built=20again=20until=20the=20sour?= =?UTF-8?q?ce=20changes=20(issue=201587,=20S14,=20ADR=200498=20=C2=A72=20?= =?UTF-8?q?=C2=A74=20=C2=A75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit not stored, not pinned, version taken and refused kind (moved here from the builder); FailedUntilChanged keeps an unpinned upstream or a taken version from rebuilding in a loop, while a failed push is built again. --- go/delivery/builder.go | 20 ++++++++++++++++++++ go/delivery/builder_reference_test.go | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/go/delivery/builder.go b/go/delivery/builder.go index 85fbbe8..faf2eff 100644 --- a/go/delivery/builder.go +++ b/go/delivery/builder.go @@ -135,6 +135,26 @@ func (b BuilderBuild) Referenced() (ok bool, missing []string) { return b.State == BuildDone && len(b.Artifacts) > 0 && len(missing) == 0, missing } +// The prefixes of a failed key's error that a build module answers (novox/hq ADR 0498 clauses 2, 4 and 5; ADR 0478 +// clause 2), each followed by the artifact and the words of what refused it. +const ( + // NotStored: the push of a bundle, an archive or an upstream copy to the artifact store failed; built again. + NotStored = "not stored: " + // NotPinned: an upstream artifact names no digest. + NotPinned = "not pinned: " + // VersionTaken: the package registry holds the package's version with another packed file. + VersionTaken = "version taken: " + // RefusedKind: no build module builds this kind of artifact in its language. + RefusedKind = "refused kind: " +) + +// FailedUntilChanged says whether a failed key's error is one that is not built again until the module's fingerprint +// changes (not pinned, version taken, refused kind: the same source fails the same way); every other failed key, a +// push that was not stored included, is built again as a new revision (ADR 0429 clause 18). +func FailedUntilChanged(err string) bool { + return strings.HasPrefix(err, NotPinned) || strings.HasPrefix(err, VersionTaken) || strings.HasPrefix(err, RefusedKind) +} + // ToolchainUsed is what a build used for one language (ADR 0405 clauses 2 and 7): the installed toolchain's version and // the build module's recipe version. type ToolchainUsed struct { diff --git a/go/delivery/builder_reference_test.go b/go/delivery/builder_reference_test.go index d277440..ab8e26b 100644 --- a/go/delivery/builder_reference_test.go +++ b/go/delivery/builder_reference_test.go @@ -74,3 +74,25 @@ func TestReferencedNamesTheArtifactsWithoutAReference(t *testing.T) { } } +// The errors a build module answers open with a fixed prefix (ADR 0498 clauses 2, 4 and 5; ADR 0478 clause 2), and three +// of them are not built again until the module's fingerprint changes; a failed push is. +func TestOnlyAPushFailureIsBuiltAgainBeforeTheFingerprintChanges(t *testing.T) { + for _, c := range []struct { + err string + again bool + }{ + {NotStored + "code: the store said 500", true}, + {NotPinned + "nats: upstream names no digest", false}, + {VersionTaken + "@novox/mesh-sdk@0.1.15 holds another file", false}, + {RefusedKind + "a package in go", false}, + {"go test: 2 failed", true}, + } { + if got := FailedUntilChanged(c.err); got == c.again { + t.Errorf("FailedUntilChanged(%q) = %v", c.err, got) + } + } + if NotStored != "not stored: " || NotPinned != "not pinned: " || VersionTaken != "version taken: " || RefusedKind != "refused kind: " { + t.Fatal("a prefix changed its words") + } +} +