From 008307367f9d2195e31c8beb0922c71257455ca9 Mon Sep 17 00:00:00 2001 From: Patrick O'Reilly Date: Thu, 17 Sep 2026 13:52:31 -0700 Subject: [PATCH] docker: stamp the version into the image, and assert it on every build `orlyc --help` in the published image reported "Build: unknown", including in the v0.1.0-rc1 release candidate. `make version` derives the string from `git describe`, .dockerignore excludes .git, so inside the image build there was never anything to describe. That was a documented trade ("fine for an image whose tag carries the version") and it held while the image was only ever :latest. It stops holding at a release: someone running :latest -- which is what the README tells them to run -- has no way to ask the binary what it is. So pass the version in. New ORLY_VERSION build arg writes orly/build_version.h directly when set and falls back to `make version` when it is not, so a bare `docker build .` behaves exactly as before. The workflow resolves it to the tag on a release and dev- otherwise, which means every image can name itself, not just tagged ones. The assertion runs on every image build, pull requests included, rather than only on a publish. That is the #559 lesson applied: the manifest check in this same workflow was gated to publishes, never ran, and failed a correct manifest the first time it did. Verified by building the image locally on arm64 with the arg set: orlyc reports the stamped string and the assertion as written passes. --- .github/workflows/docker.yml | 25 +++++++++++++++++++++++++ Dockerfile | 20 +++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 89fbbc43..4df452a8 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -95,12 +95,37 @@ jobs: # If the default was resolving to amd64 on the arm runner, every RUN line # was going through qemu, which explains the 20x. Pinning it costs nothing # if the default was already correct. + # The version has to be handed to the build: .dockerignore excludes .git, + # so `make version`'s `git describe` finds nothing inside the container + # and the binaries used to report "Build: unknown" even on a release tag. + - name: Resolve the version to stamp + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + ver="${GITHUB_REF#refs/tags/}" + else + ver="dev-${GITHUB_SHA:0:12}" + fi + echo "ORLY_VERSION=$ver" >> "$GITHUB_ENV" + echo "stamping: $ver" + - name: Build image run: | docker build --platform "linux/${{ matrix.arch }}" \ --build-arg JHM_WORKER_COUNT=${{ matrix.workers }} \ + --build-arg ORLY_VERSION="$ORLY_VERSION" \ -t "$IMAGE" . + # Assert the stamp landed, on every build including pull requests -- the + # point being that this runs constantly rather than only on a publish. + # The manifest check in this same workflow was gated to publishes only, + # so it went unexercised until it failed its first real run (#559). + - name: Confirm the binaries know their own version + run: | + got=$(docker run --rm --entrypoint orlyc "$IMAGE" --help 2>&1 \ + | sed -n 's/^Build: //p') + echo "orlyc reports: ${got:-}" + [ "$got" = "$ORLY_VERSION" ] + - name: Confirm the built image is the intended architecture run: | got=$(docker image inspect "$IMAGE" --format '{{.Architecture}}') diff --git a/Dockerfile b/Dockerfile index 0d8d3d54..8fbb35e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,10 +25,24 @@ WORKDIR /src/orly COPY . . # Bootstrap jhm + nycr, then build just the two production binaries this -# image ships (jhm emits to /src/out_orly). `make version` degrades to -# "unknown" without git -- fine for an image whose tag carries the version. +# image ships (jhm emits to /src/out_orly). +# +# The version has to be passed IN. `make version` derives it from `git +# describe`, and .dockerignore excludes .git -- deliberately, it is build +# context nothing here needs -- so inside this build it always degraded to +# "unknown". That was tolerable while the image was only ever :latest; it is +# not once there are release tags, because `orlyc --help` reporting +# "Build: unknown" leaves a user with no way to ask the binary what it is. +# The workflow passes the tag on a release and dev- otherwise. ARG JHM_WORKER_COUNT=4 -RUN make bootstrap version \ +ARG ORLY_VERSION= +RUN if [ -n "$ORLY_VERSION" ]; then \ + printf '#pragma once\n\n/* Generated by the image build; see Dockerfile. */\n#define ORLY_BUILD_VERSION "%s"\n' \ + "$ORLY_VERSION" > orly/build_version.h; \ + make bootstrap; \ + else \ + make bootstrap version; \ + fi \ && PATH="/src/orly/tools:$PATH" \ jhm -c release --worker-count "$JHM_WORKER_COUNT" \ orly/server/orlyi orly/orlyc