From e4d2a191d0c2f7699aab2fd93b0a15c1d04b9cb6 Mon Sep 17 00:00:00 2001 From: Jan Novak Date: Tue, 11 Aug 2026 18:02:41 +0200 Subject: [PATCH] Add plan: bake git commit into the operator binary and log it at startup Co-Authored-By: Claude --- .../2026-08-11-1802-bake-commit-version.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs/plans/2026-08-11-1802-bake-commit-version.md diff --git a/docs/plans/2026-08-11-1802-bake-commit-version.md b/docs/plans/2026-08-11-1802-bake-commit-version.md new file mode 100644 index 0000000..adb9749 --- /dev/null +++ b/docs/plans/2026-08-11-1802-bake-commit-version.md @@ -0,0 +1,75 @@ +# Plan: Bake the git commit into the operator binary and log it at startup + +**Created:** 2026-08-11 18:02 + +## Context + +There is no versioning yet, and the image tag (`egress-proxies-operator:dev`, +`imagePullPolicy: IfNotPresent`) says nothing about what code is actually +running. The user wants the commit hash baked into the image at build time, +and — the key requirement — the binary itself must know it and print it into +the log stream during initialization, so `kubectl logs | head` answers "which +version is running". Docker builds cannot use Go's automatic VCS stamp because +`.dockerignore` excludes `.git` (correctly — re-including it would bust layer +caching), so the hash must travel git → Makefile → `--build-arg` → `-ldflags -X`. + +## Implementation + +**1. New package `internal/version`** (`version.go` + `version_test.go`): + +- `var Commit string` — stamped at link time via + `-ldflags "-X gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/version.Commit="`. +- `func Resolve() string` — returns `Commit` if non-empty; otherwise falls + back to `debug.ReadBuildInfo()` VCS settings (`vcs.revision` truncated to + 12 chars, `-dirty` suffix when `vcs.modified=true`), so plain host builds + (`make build`, `make run`, `go run`) are stamped for free since `.git` is + present there; `"unknown"` when neither source is available (e.g. `go test`). +- Internal `resolve(ldflagsCommit string, readBuildInfo func() (*debug.BuildInfo, bool)) string` + so the fallback logic is table-testable with a fake build-info func + (house style: stdlib testing, `t.Parallel()`, subtests, + `Test_` names). + +**2. `cmd/main.go`**: + +- Add `--version` bool flag; immediately after the existing `flag.Parse()` + (main.go:132), if set: print `version.Resolve()` to stdout and exit 0 + (before logger/manager setup). +- Right after `ctrl.SetLogger(...)` (main.go:134): + `setupLog.Info("Starting egress-proxies-operator", "commit", version.Resolve(), "goVersion", runtime.Version())` + — first line of every run, plain V(0) so it appears at any log level. + +**3. `Makefile`**: + +- Near the other variables: + `GIT_COMMIT ?= $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo unknown)$(shell test -z "$$(git status --porcelain 2>/dev/null)" || echo -dirty)` + (`git status --porcelain` catches staged and untracked changes, which + `git diff --quiet` misses). +- `docker-build`: add `--build-arg GIT_COMMIT=$(GIT_COMMIT)`. +- `docker-buildx`: add the same `--build-arg` to the `buildx build` line. +- `build`/`run`/`run-dev` stay untouched — the ReadBuildInfo fallback covers them. + +**4. `Dockerfile`**: + +- `ARG GIT_COMMIT=unknown` in the builder stage; extend the existing + `go build` with `-ldflags "-X /internal/version.Commit=${GIT_COMMIT}"`. +- Re-declare `ARG GIT_COMMIT` in the distroless stage and add + `LABEL org.opencontainers.image.revision="${GIT_COMMIT}"` so the hash is + also visible via `docker inspect` without running the binary. + +No changes to deploy manifests, providers, or the reconciler. CHANGELOG entry +after the user confirms it works (house convention). + +## Verification + +```bash +go test ./internal/version/ # resolve() table tests +go build ./... && go test ./... # nothing else broke +go run ./cmd/main.go --version # host build: VCS-stamped hash (+ -dirty), exit 0 +make docker-build IMG=egress-proxies-operator:dev +docker run --rm egress-proxies-operator:dev --version # prints the baked commit +docker inspect egress-proxies-operator:dev \ + --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' +``` + +Live check: redeploy on the cluster and confirm the first log line carries +`"commit"`.