Repository navigation
fix(build): a published release is adopted unless its code changed - #1148
Merged
antoinetoussaint-byte merged 1 commit intoOct 24, 2026
Merged
Conversation
A released tag whose image records other build inputs than this build's refused every render: one image built from another checkout (another recipe invocation, another base resolution) blocked every later render of every module on the cell, because a render needs every workload's digest. Every build now records its input classes beside the aggregate label: org.codefly.build.inputs.code (build context + Go module manifests), .recipe (recipe tree, Dockerfile, build invocation) and .bases (resolved base images). The aggregate key is unchanged. A published release with other inputs is adopted when its code class equals this build's, with a warning naming the class that differs; other code refuses, naming the code; another agent than the release pins still refuses (#1146). An image labelled before the classes existed is adopted with a warning that its code was not compared (--rebuild builds it again). Build-qualified override tags keep the exact-identity check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defect
On 2026-10-24, with CLI 0.1.211 and 0.1.210 alike,
codefly deploy gitops render robin --env staging(obin-ai/platform-obin) is refused:Neither documents' release (0.1.14) nor its agent (go-grpc 0.1.58, not overridden) had changed. Another operator's checkout had built the published image earlier that day. Rendering one module rebuilds or reuses all 25 services, because the cell file needs every workload's digest. So one image built anywhere with different non-code inputs blocks every later render of every module on that cell. The image carried only the aggregate
org.codefly.build.inputs, a hash over schema, recipe, Dockerfile, context, dockerignore, buildx command, recipe tree, context tree, Go modules and bases, so the render could not tell a code change from a recipe-invocation or base-image difference.Per
build_plan.go: "A released version is built once … when the registry already holds this service at this version, it is that image." The refusal exists only to catch a version that did not move with its code.Design (fix, at the owner of the decision)
Per-class labels. Every build records, beside the unchanged aggregate:
org.codefly.build.inputs.code: build context, dockerignore, context tree, Go module manifestsorg.codefly.build.inputs.recipe: recipe name, Dockerfile, recipe tree, normalized buildx commandorg.codefly.build.inputs.bases: resolved base image digestsThey are computed in
imageBuildIdentityfrom the sameimageInputs(identityClasses). Like the aggregate, they are added to argv after the identity is computed, so they never feed it. The aggregate key is byte-identical, so existing labelled images still match their own inputs.Released-version decision (
judgePublishedRelease/publishedReleaseVerdict):--rebuildbuilds it againWhy adopt pre-class images by default. Refusing blocks every cell that holds one such image, which is today's defect. Rebuilding would overwrite a release wherever tags are mutable. Adopting follows the principle quoted above. The existing
--rebuildflag is the explicit opt-out, so no new flag was added.Override builds (fix(build): a build under an agent override is tagged apart from the release #1146). A
-build.<identity>tag keeps the exact-aggregate check and is refused on mismatch (publishedFromOtherInputs, unchanged).Reused: the existing label seam (
withBuildFlags,resolveImageBuildLabels/buildLabelsFromImageConfig),imageInputs, the refusal helper from #1146, and--rebuild. Not added: a new flag, a second identity, or any change to the aggregate key or the local cache.Tests
TestAPublishedVersionFromTheSameInputsIsAdoptedNotRebuilt: aggregate equal → adopt (unchanged)TestAPublishedReleaseIsJudgedByItsCode: labels read off a real harness build. Same code with other recipe and bases → adopt. Pre-class aggregate only → adopt. Other code → refuse. Other agent → refuse. A published release is never rebuilt in any case.TestPublishedReleaseVerdictNamesTheClass: the warning names recipe vs bases, the legacy warning, and a code refusal that names the codeTestAPublishedVersionLabelledBeforeClassesIsAdopted: replaces the old "other inputs refuses" testTestBuildInputsAreReadFromEveryPlatform: class labels are written to argv and read backTestAnOverriddenAgentBuildOfAPublishedVersionIsTaggedApartandTestAnOverriddenBuildIsPushedQualifiedAtTheRegistryItPullsThroughpass unchangedgo test ./pkg/orchestration/ ./pkg/gitops/passes, andmake lintreports 0 issues.Docs
The image-reuse section of
docs/commands.mdnow describes the class labels and the decision table, and explains why adopt is the default.Not verified
documents:0.1.14carries only the aggregate, so with this change the render adopts it with the pre-class warning. Nobody has observed that on the cell yet.imagetools inspectreading the new labels is covered only by thebuildLabelsFromImageConfigunit test, not against a real registry.🤖 Generated with Claude Code