From 4ce0814b1481bfdb67878deb97e9f1f73a09b4d5 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Fri, 2 Oct 2026 04:26:40 +0200 Subject: [PATCH] Stamp the git tag or short commit in a plain docker build (closes #86) The builder stage now has git and takes the version from the VERSION build argument when one is given, otherwise from `git describe --tags --always` of the repo's .git, copied to /git so go build does not see it. A version that still comes out empty, dev or unknown fails the build. ARG VERSION has no default. .dockerignore keeps .git/config out of the build context, and the comments in script/docker and script/cibuild no longer say .git is excluded. Model: opus-5-5 --- .dockerignore | 3 +++ Dockerfile | 19 ++++++++++++++++--- script/cibuild | 5 ++--- script/docker | 5 ++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.dockerignore b/.dockerignore index 416281f..033ab7b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,3 +4,6 @@ tmp .DS_Store *.log .claude + +# .git is sent so the build can stamp the version, without its config. +.git/config diff --git a/Dockerfile b/Dockerfile index 1504805..4203274 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ RUN make lint # golang:1.25-alpine (2026-02-27) FROM golang:1.25-alpine@sha256:f6751d823c26342f9506c03797d2527668d095b0a15f1862cddb4d927a7a4ced AS builder -RUN apk add --no-cache make +RUN apk add --no-cache git make WORKDIR /src @@ -40,8 +40,21 @@ RUN make test # CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.Version=..." # That script reads VERSION from the environment, so it is handed over # there rather than as a make variable. -ARG VERSION=dev -RUN VERSION="${VERSION}" make build +# +# The version is the VERSION build argument when one is given, otherwise +# `git describe --tags --always` of the repo's .git: the tag on a tagged +# commit, tag-N-gHASH on a commit after one, the short commit when no +# tag is reachable. A version that still comes out empty, dev or unknown +# fails the build. .git goes to /git, not /src/.git, where go build would +# find it and record VCS details of a work tree holding only backend/. +COPY .git /git +ARG VERSION +RUN version="${VERSION:-$(git --git-dir=/git describe --tags --always)}"; \ + case "$version" in ""|dev|unknown) \ + echo "version is '$version' although .git is present" >&2; \ + exit 1 ;; \ + esac; \ + VERSION="$version" make build # Frontend stage # node:22-alpine as of 2026-02-22 diff --git a/script/cibuild b/script/cibuild index 688299f..d8d3200 100755 --- a/script/cibuild +++ b/script/cibuild @@ -16,9 +16,8 @@ main() { "$SCRIPT_DIR/check" # Own line: a failing command substitution inside an argument does # not trip `set -e`, so the inline form degrades silently to an - # empty constant. VERSION is computed here because .dockerignore - # excludes .git, so `git describe` in a build stage yields an empty - # version without failing. + # empty constant. The VERSION build argument takes precedence over + # the version a build stage derives from the .git in the context. version="$(git describe --tags --always --dirty 2>/dev/null || true)" [ -n "$version" ] || version="unknown" docker build --no-cache \ diff --git a/script/docker b/script/docker index c4688e8..07b626c 100755 --- a/script/docker +++ b/script/docker @@ -12,9 +12,8 @@ main() { cd "$ROOT" # Own line: a failing command substitution inside an argument does # not trip `set -e`, so the inline form degrades silently to an - # empty constant. VERSION is computed here because .dockerignore - # excludes .git, so `git describe` in a build stage yields an empty - # version without failing. + # empty constant. The VERSION build argument takes precedence over + # the version a build stage derives from the .git in the context. version="$(git describe --tags --always --dirty 2>/dev/null || true)" [ -n "$version" ] || version="unknown" docker build --no-cache \