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
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
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Reported by the owner in chat, 2026-10-01 ~18:4x UTC, from the webhooker Docker build run by upaas on fsn1app1 (branch
prod, commit1647b43a):The Dockerfile declares
ARG VERSION=unknown, and.dockerignoreexcludes.git/. Onlyscript/dockerresolves 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:
docker buildthat has the information available.nextwith an independent review.model: opus-5-5
Plan.
How the version reaches the build today: the
DockerfiledeclaresARG VERSION=unknownand hands it tomake build, and.dockerignoreexcludes.git/, so nothing inside the build can rungit describe. Onlyscript/dockerresolves the version on the host and passes--build-arg VERSION. upaas builds from its own clone of the branch,.gitincluded, and passes no build argument, so the binary getsunknown.Reading: derive the version inside the build from the
.gitthat the build context already carries, with aVERSIONbuild 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 whoseDockerfiledoes the same gets its commit from every build of a clone (upaas, a plaindocker 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 aVERSIONbuild argument to every app. That needs a upaas change and still leaves a plaindocker build .on a clone atunknown. No upaas issue is needed.Implementation:
.dockerignorestops excluding.git/and the tracked files it leaves out (*.md,LICENSE,.editorconfig): inside the build,git describe --dirtywould see them as deleted and append-dirty. Exclusions of untracked files stay.ARG VERSIONloses itsunknowndefault, so an unset argument letsmake buildfall back toscript/version, which already prefers$VERSION, thengit describe, thenunknown. TheARGstays below the test step.gitand must not trip git's ownership check (safe.directory); either failure silently yieldsunknownagain..gitorVERSIONis set and the version is stillunknown. Plain and small.script/dockerkeeps passing the version it resolves on the host. Images built byscript/cibuildnow carry the commit too, which is item 2 of #265; the rest of that issue is not in this unit.Dockerfileand.dockerignorecomments that say the build cannot derive the version, are updated.nextafter that lands.Model: opus-5-5
Implemented in #410.
The image now derives its version from the
.gitits build context carries, so a plaindocker build .of a clone stamps the commit it was built from; the shallow single-branch clone upaas builds stamps the short commit hash..dockerignorenow sends.gitand every tracked file,ARG VERSIONno longer defaults tounknown, and aVERSIONbuild arg still takes precedence. The builder stage installsgitand fails when its context carries.gitand the version still comes outunknown. Nothing changes in upaas..gitalone, because aVERSIONbuild arg is stamped as given.safe.directorysetting; files copied into the build belong to root, the user the build runs as..gitchanges with every commit.Model: opus-5-5