Skip to content

20260816 - Resolve the telemetry image tag when building the artifact - #31

Merged
Purple10101 merged 1 commit into
mainfrom
20260816-resolve-telemetry-tag-in-artifact
Aug 17, 2026
Merged

20260816 - Resolve the telemetry image tag when building the artifact#31
Purple10101 merged 1 commit into
mainfrom
20260816-resolve-telemetry-tag-in-artifact

Conversation

@Purple10101

Copy link
Copy Markdown
Collaborator

Adding retina-telemetry to docker-compose.yml was not enough to ship it.

The bug

The artifact build resolves image tags with one hand-written sed clause per variable, and TELEMETRY_V had none. The generated manifest kept a literal:

image: ghcr.io/offworldlabs/retina-telemetry:${TELEMETRY_V:-v0.1.0}

Which is exactly what the comment above that block warns about:

gen_docker-compose uses raw sed to extract image names and cannot handle unresolved shell variables

skopeo receives ${TELEMETRY_V:-v0.1.0} as a tag. The release either fails there, or produces an artifact whose telemetry service can never start on a node.

Why nothing caught it

The compose file is valid. docker compose config resolves the variable correctly. The same service block ran on two live nodes against production. The defect isn't in the compose file at all — it's in a transformation of it that enumerates its variables by hand, in another file, with no test.

The fix

The seventh clause, plus a guard that removes the need to remember an eighth: every image line in the generated manifest must be a literal, and the build fails naming the variable that was missed.

Verified against the merged docker-compose.yml:

before after
image tags resolved 9 of 10 10 of 10
guard on the old six-clause build exits 1, printing line 178 and the variable
runtime ${} refs preserved 35, untouched

Runtime variables are deliberately left alone and still resolved from .env at deploy time — the check reads image: lines only. bash -n clean; generated manifest parses as YAML with all 10 services.

🤖 Generated with Claude Code

Adding retina-telemetry to docker-compose.yml was not enough to ship it. The
artifact build resolves image tags with one hand-written sed clause per
variable, and TELEMETRY_V had none — so the generated manifest kept a literal

    image: ghcr.io/offworldlabs/retina-telemetry:${TELEMETRY_V:-v0.1.0}

which is exactly what the comment above that block warns about:
gen_docker-compose extracts image names with raw sed and cannot handle
unresolved shell variables. skopeo would receive `${TELEMETRY_V:-v0.1.0}` as a
tag, and the release either fails there or produces an artifact whose telemetry
service can never start on a node.

Nothing caught it. The compose file is valid, `docker compose config` resolves
the variable correctly, and the same block ran on two live nodes — because the
defect is not in the compose file but in a transformation of it that enumerates
its variables by hand, in another file, with no test.

So this adds the seventh clause and then removes the need to remember an
eighth: every image line in the generated manifest is asserted to be a literal,
and the build fails naming the variable that was missed. A missing clause now
costs a failed build with a precise message rather than a broken artifact.

Runtime variables are untouched and still resolved from .env at deploy time —
the check reads image lines only, and 35 ${} references survive it.
@Purple10101
Purple10101 merged commit a3ffbd3 into main Aug 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant