fix(ci): the file that decides FC_VERSION now moves it (#3202)
CI / lint (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
CI / extension-version (push) Successful in 4s
Build images / build-ml (push) Successful in 5s
Build images / build-agent (push) Successful in 6s
CI / frontend-build (push) Successful in 29s
CI / backend-lint-and-test (push) Successful in 1m5s
Build images / build-web (push) Successful in 3m15s
CI / integration (push) Successful in 4m29s
CI / lint (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
CI / extension-version (push) Successful in 4s
Build images / build-ml (push) Successful in 5s
Build images / build-agent (push) Successful in 6s
CI / frontend-build (push) Successful in 29s
CI / backend-lint-and-test (push) Successful in 1m5s
Build images / build-web (push) Successful in 3m15s
CI / integration (push) Successful in 4m29s
`scripts/artifacts.sh` decides both values the web image carries — the `fc.revision` label the reuse check compares and the `FC_VERSION` baked into the image — and was in no artifact's path set. So a change to `cmd_version` alone left every revision untouched, the reuse check hit, the build was skipped, and the published image went on reporting the OLD version format, indefinitely, until some unrelated commit forced a rebuild. Nothing goes red; the footer just shows a well-formed string of the wrong shape. Milestone 318 step 5 is the worked instance:b3989d0-> rev=fb2c4d5b80be ver=2026.8.28.12495771fd5-> rev=fb2c4d5b80be ver=2026.08.28.1249bce894b-> rev=bce894ba2499 ver=2026.08.28.2208 Same revision across the zero-pad commit, so web's build was skipped. It cost nothing only by timing: FC_VERSION did not exist until step 6 landed one commit later. Web only, and that is the interesting part. Every artifact stamps a revision, but only web also stamps a version. A revision-only artifact needs no entry here, because changing how a revision is COMPUTED changes the derived value, which then disagrees with the label on the published image and forces a rebuild — the mechanism self-corrects, since it compares against a string stamped into a real artifact. Nothing compares a version to anything. That asymmetry is why this was invisible and is now written down in both files. Named as a file rather than `scripts`: release_notes.py sits beside it and only reads derived values, so it decides nothing and must not re-version web. This is #3156 one level up — packaging.sh excluded from the version it derives — so the guard is generalised rather than duplicated: one DERIVERS table naming each deriver and the artifacts whose identity it decides. The too-wide test gains a note saying where the line is, since "copied into no image" no longer settles it on its own.
This commit is contained in:
+33
-1
@@ -3,6 +3,11 @@
|
||||
# version derived from it. Milestone 313; generalises the shape
|
||||
# extension/scripts/packaging.sh established for the extension alone.
|
||||
#
|
||||
# "Built from" is deliberately wider than "copied into". A file that DECIDES an
|
||||
# artifact's identity is part of what that artifact is built from even though it
|
||||
# never reaches the image — see DERIVER below, and #3156 for the same finding
|
||||
# about packaging.sh.
|
||||
#
|
||||
# Four artifacts, four independent versions. An artifact whose shipped files
|
||||
# did not change keeps its version and does not rebuild — that is the whole
|
||||
# point, and it is why each path set must match its Dockerfile rather than
|
||||
@@ -56,6 +61,33 @@ ML_PATHS='Dockerfile.ml requirements-ml.txt requirements.txt backend alembic ale
|
||||
# it: this is deliberately NOT `agent/`.
|
||||
AGENT_PATHS='agent/Dockerfile agent/requirements.txt agent/fc_agent'
|
||||
|
||||
# This file. It is copied into no image and it is still part of what the web
|
||||
# image is built from, because it DECIDES the FC_VERSION baked into that image
|
||||
# (#3202). Same finding as #3156 about packaging.sh, one level up.
|
||||
#
|
||||
# Why web and nothing else. Every artifact stamps `fc.revision`, but only web
|
||||
# also stamps a version (build.yml line ~488 feeds `version web` to the
|
||||
# FC_VERSION build arg; ml and agent ask for `revision` alone, and the
|
||||
# extension takes its version from packaging.sh). For a revision-only artifact
|
||||
# this file needs no entry: any change to how the revision is COMPUTED changes
|
||||
# the derived value, which then disagrees with the label on the published image
|
||||
# and forces a rebuild. That mechanism is self-correcting because it compares
|
||||
# against a string stamped into a real artifact.
|
||||
#
|
||||
# The version is compared against nothing, so it has no such backstop. Before
|
||||
# this entry, a change to cmd_version alone left every artifact's revision
|
||||
# untouched, the reuse check hit, the build was skipped, and the published
|
||||
# image went on reporting the OLD version format — silently, until some
|
||||
# unrelated commit happened to force a rebuild. Milestone 318 step 5 is the
|
||||
# worked instance: b3989d0 and 5771fd5 share revision fb2c4d5b80be while the
|
||||
# version moved 2026.8.28.1249 -> 2026.08.28.1249. It cost nothing only because
|
||||
# FC_VERSION did not exist until one commit later.
|
||||
#
|
||||
# Named as a file, not as `scripts`: release_notes.py lives beside it and only
|
||||
# READS derived values, so it decides nothing and must not re-version anything.
|
||||
# A future script that derives an identity belongs here explicitly.
|
||||
DERIVER='scripts/artifacts.sh'
|
||||
|
||||
|
||||
usage() {
|
||||
echo "usage: artifacts.sh {paths|revision|version} {web|ml|agent|extension}" >&2
|
||||
@@ -71,7 +103,7 @@ ext_paths() {
|
||||
|
||||
cmd_paths() {
|
||||
case "$1" in
|
||||
web) echo "$WEB_PATHS $(ext_paths)" ;;
|
||||
web) echo "$WEB_PATHS $DERIVER $(ext_paths)" ;;
|
||||
ml) echo "$ML_PATHS" ;;
|
||||
agent) echo "$AGENT_PATHS" ;;
|
||||
extension) ext_paths ;;
|
||||
|
||||
Reference in New Issue
Block a user