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