From 8a59546e28af9693e23aed7f139fab577a0fdf92 Mon Sep 17 00:00:00 2001 From: Josh Poole Date: Mon, 17 Aug 2026 10:13:29 +0100 Subject: [PATCH] 20260816 - Resolve the telemetry image tag when building the artifact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- scripts/build_mender_artifact.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/build_mender_artifact.sh b/scripts/build_mender_artifact.sh index 9568d53..9bba274 100755 --- a/scripts/build_mender_artifact.sh +++ b/scripts/build_mender_artifact.sh @@ -61,8 +61,21 @@ sed -e 's/\${BLAH2_V:-\([^}]*\)}/\1/g' \ -e 's/\${CONFIG_MERGER_V:-\([^}]*\)}/\1/g' \ -e 's/\${SPECTRUM_V:-\([^}]*\)}/\1/g' \ -e 's/\${RETINA_TRACKER_V:-\([^}]*\)}/\1/g' \ + -e 's/\${TELEMETRY_V:-\([^}]*\)}/\1/g' \ "${COMPOSE_FILE}" > "${MANIFEST_DIR}/docker-compose.yaml" +# Every image tag must be a literal by this point. The list above is by hand, +# so adding a service to docker-compose.yml without adding its clause here +# leaves a ${VAR:-default} that skopeo receives as a literal tag — the artifact +# either fails to build or installs a service that can never start. Cheaper to +# fail here, with the name of the variable that was missed. +if unresolved=$(grep -nE '^\s+image:.*\$\{' "${MANIFEST_DIR}/docker-compose.yaml"); then + echo "Error: unresolved image tag variables in the generated manifest:" >&2 + echo "${unresolved}" >&2 + echo "Add a matching -e clause above for each." >&2 + exit 1 +fi + SCRIPT_DIR="$(dirname "$0")/mender-state-scripts" # Build artifact — gen_docker-compose pulls images via skopeo automatically