Image built by upaas stamps version "unknown" into the binary #366

Open
opened 2026-10-01 20:38:56 +02:00 by clawbot · 2 comments
Collaborator

Reported by the owner in chat, 2026-10-01 ~18:4x UTC, from the webhooker Docker build run by upaas on fsn1app1 (branch prod, commit 1647b43a):

#28 0.585 go build -ldflags '-X main.version=unknown' -o bin/webhooker ./cmd/webhooker

The Dockerfile declares ARG VERSION=unknown, and .dockerignore excludes .git/. Only script/docker resolves a version on the host and passes it in. upaas runs a plain build with no build argument, so every deployed binary reports "unknown".

Definition of done:

  • A webhooker image built by upaas from a branch reports a real version (at least the commit it was built from), not "unknown". The same holds for any plain docker build that has the information available.
  • The comment on this issue states how the version reaches the build before implementation starts. Options include a build argument upaas passes for every app, or the version derived inside the build. Anything needed on the upaas side is filed as its own upaas issue and linked here. Prefer one convention every app can use.
  • A test or check fails if the image would report "unknown" when the version information was provided.
  • Lands on next with an independent review.

model: opus-5-5

Reported by the owner in chat, 2026-10-01 ~18:4x UTC, from the webhooker Docker build run by upaas on fsn1app1 (branch `prod`, commit `1647b43a`): ``` #28 0.585 go build -ldflags '-X main.version=unknown' -o bin/webhooker ./cmd/webhooker ``` The Dockerfile declares `ARG VERSION=unknown`, and `.dockerignore` excludes `.git/`. Only `script/docker` resolves a version on the host and passes it in. upaas runs a plain build with no build argument, so every deployed binary reports "unknown". Definition of done: - A webhooker image built by upaas from a branch reports a real version (at least the commit it was built from), not "unknown". The same holds for any plain `docker build` that has the information available. - The comment on this issue states how the version reaches the build before implementation starts. Options include a build argument upaas passes for every app, or the version derived inside the build. Anything needed on the upaas side is filed as its own upaas issue and linked here. Prefer one convention every app can use. - A test or check fails if the image would report "unknown" when the version information was provided. - Lands on `next` with an independent review. model: opus-5-5
clawbot self-assigned this 2026-10-01 20:38:56 +02:00
Author
Collaborator

Plan.

How the version reaches the build today: the Dockerfile declares ARG VERSION=unknown and hands it to make build, and .dockerignore excludes .git/, so nothing inside the build can run git describe. Only script/docker resolves the version on the host and passes --build-arg VERSION. upaas builds from its own clone of the branch, .git included, and passes no build argument, so the binary gets unknown.

Reading: derive the version inside the build from the .git that the build context already carries, with a VERSION build argument still taking precedence when one is given. upaas adopted this convention for its own image in sneak/upaas#242. It needs no change in upaas: any app whose Dockerfile does the same gets its commit from every build of a clone (upaas, a plain docker build ., CI). upaas clones a branch shallowly, without tags, so its builds report the short commit hash, which meets the definition of done. Alternative not taken: upaas passing a VERSION build argument to every app. That needs a upaas change and still leaves a plain docker build . on a clone at unknown. No upaas issue is needed.

Implementation:

  • .dockerignore stops excluding .git/ and the tracked files it leaves out (*.md, LICENSE, .editorconfig): inside the build, git describe --dirty would see them as deleted and append -dirty. Exclusions of untracked files stay.
  • ARG VERSION loses its unknown default, so an unset argument lets make build fall back to script/version, which already prefers $VERSION, then git describe, then unknown. The ARG stays below the test step.
  • The builder stage must have git and must not trip git's ownership check (safe.directory); either failure silently yields unknown again.
  • A check fails the image build when the context carries .git or VERSION is set and the version is still unknown. Plain and small.
  • script/docker keeps passing the version it resolves on the host. Images built by script/cibuild now carry the commit too, which is item 2 of #265; the rest of that issue is not in this unit.
  • The README, and the Dockerfile and .dockerignore comments that say the build cannot derive the version, are updated.
  • This touches the same files as #351, so it starts from next after that lands.

Model: opus-5-5

Plan. How the version reaches the build today: the `Dockerfile` declares `ARG VERSION=unknown` and hands it to `make build`, and `.dockerignore` excludes `.git/`, so nothing inside the build can run `git describe`. Only `script/docker` resolves the version on the host and passes `--build-arg VERSION`. upaas builds from its own clone of the branch, `.git` included, and passes no build argument, so the binary gets `unknown`. Reading: derive the version inside the build from the `.git` that the build context already carries, with a `VERSION` build argument still taking precedence when one is given. upaas adopted this convention for its own image in https://git.eeqj.de/sneak/upaas/pulls/242. It needs no change in upaas: any app whose `Dockerfile` does the same gets its commit from every build of a clone (upaas, a plain `docker build .`, CI). upaas clones a branch shallowly, without tags, so its builds report the short commit hash, which meets the definition of done. Alternative not taken: upaas passing a `VERSION` build argument to every app. That needs a upaas change and still leaves a plain `docker build .` on a clone at `unknown`. No upaas issue is needed. Implementation: - `.dockerignore` stops excluding `.git/` and the tracked files it leaves out (`*.md`, `LICENSE`, `.editorconfig`): inside the build, `git describe --dirty` would see them as deleted and append `-dirty`. Exclusions of untracked files stay. - `ARG VERSION` loses its `unknown` default, so an unset argument lets `make build` fall back to `script/version`, which already prefers `$VERSION`, then `git describe`, then `unknown`. The `ARG` stays below the test step. - The builder stage must have `git` and must not trip git's ownership check (`safe.directory`); either failure silently yields `unknown` again. - A check fails the image build when the context carries `.git` or `VERSION` is set and the version is still `unknown`. Plain and small. - `script/docker` keeps passing the version it resolves on the host. Images built by `script/cibuild` now carry the commit too, which is item 2 of https://git.eeqj.de/sneak/webhooker/issues/265; the rest of that issue is not in this unit. - The README, and the `Dockerfile` and `.dockerignore` comments that say the build cannot derive the version, are updated. - This touches the same files as https://git.eeqj.de/sneak/webhooker/pulls/351, so it starts from `next` after that lands. Model: opus-5-5
Author
Collaborator

Implemented in #410.

The image now derives its version from the .git its build context carries, so a plain docker build . of a clone stamps the commit it was built from; the shallow single-branch clone upaas builds stamps the short commit hash. .dockerignore now sends .git and every tracked file, ARG VERSION no longer defaults to unknown, and a VERSION build arg still takes precedence. The builder stage installs git and fails when its context carries .git and the version still comes out unknown. Nothing changes in upaas.

  • Judgement call: the check keys on .git alone, because a VERSION build arg is stamped as given.
  • Judgement call: no safe.directory setting; files copied into the build belong to root, the user the build runs as.
  • Side effect: docs-only commits now rebuild the image in CI, since .git changes with every commit.

Model: opus-5-5

Implemented in https://git.eeqj.de/sneak/webhooker/pulls/410. The image now derives its version from the `.git` its build context carries, so a plain `docker build .` of a clone stamps the commit it was built from; the shallow single-branch clone upaas builds stamps the short commit hash. `.dockerignore` now sends `.git` and every tracked file, `ARG VERSION` no longer defaults to `unknown`, and a `VERSION` build arg still takes precedence. The builder stage installs `git` and fails when its context carries `.git` and the version still comes out `unknown`. Nothing changes in upaas. - Judgement call: the check keys on `.git` alone, because a `VERSION` build arg is stamped as given. - Judgement call: no `safe.directory` setting; files copied into the build belong to root, the user the build runs as. - Side effect: docs-only commits now rebuild the image in CI, since `.git` changes with every commit. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#366