fix(ci): inject git_hash / git_version / build_date as build args (LC-214) #256

Merged
nrupard merged 1 commit from fix/lc-214-ci-build-provenance into main 2026-05-29 16:48:35 +02:00
Owner

Summary

CI-built artifacts ship with GIT_HASH, GIT_VERSION, and BUILD_DATE baked as the literal string unknown, because the three Forgejo workflows never pass them as --build-arg and the Dockerfile.* defaults flow through. .dockerignore excludes .git/, so build.rs's git-fallback path cannot recover the values either.

Compute the three values in nushell at the top of each Build step (git rev-parse --short=12 HEAD, git describe --tags --always --dirty, date now | format date "%Y-%m-%dT%H:%M:%SZ") and pass them through to docker buildx build as --build-arg.

Patched workflows:

  • .forgejo/workflows/build-oci-image.yml (web image)
  • .forgejo/workflows/build-desktop-linux.yml (deb / AppImage bundle)
  • .forgejo/workflows/build-desktop-windows.yml (raw .exe)

Dockerfile.desktop-windows-installer is NOT patched because it wraps a pre-built .exe with NSIS; no compiled-from-source step there to consume provenance.

BUILD_DATE captured once per build step so all images / bundles in that step share the same wall-clock anchor. The args are not content-addressable so they do not invalidate the buildx layer cache on identical source.

Test plan

  • Diff inspection: each of the three workflows now declares git_hash, git_version, build_date in nu and threads them through three --build-arg flags into docker buildx build.
  • After merge, the next CI run on main produces an image where docker run dev.a8n.run/a8n-tools-private/lets-chat:latest --version prints lets-chat 0.1.0 (<git describe>, commit <12-char hash>, built <ISO 8601>) with NO unknown substring.
  • After the c-01 pull-and-up cycle, the admin nav at chat.pugtsurani.net reads v0.1.0 (<hash>) instead of v0.1.0 (unknown).
  • /settings "About" panel on the deployed staging shows a real commit hash and ISO 8601 build date.
  • Desktop linux + windows binaries built by the next CI run print real values on --version.
## Summary CI-built artifacts ship with `GIT_HASH`, `GIT_VERSION`, and `BUILD_DATE` baked as the literal string `unknown`, because the three Forgejo workflows never pass them as `--build-arg` and the `Dockerfile.*` defaults flow through. `.dockerignore` excludes `.git/`, so `build.rs`'s `git`-fallback path cannot recover the values either. Compute the three values in nushell at the top of each `Build` step (`git rev-parse --short=12 HEAD`, `git describe --tags --always --dirty`, `date now | format date "%Y-%m-%dT%H:%M:%SZ"`) and pass them through to `docker buildx build` as `--build-arg`. Patched workflows: - `.forgejo/workflows/build-oci-image.yml` (web image) - `.forgejo/workflows/build-desktop-linux.yml` (deb / AppImage bundle) - `.forgejo/workflows/build-desktop-windows.yml` (raw `.exe`) `Dockerfile.desktop-windows-installer` is NOT patched because it wraps a pre-built `.exe` with NSIS; no compiled-from-source step there to consume provenance. `BUILD_DATE` captured once per build step so all images / bundles in that step share the same wall-clock anchor. The args are not content-addressable so they do not invalidate the buildx layer cache on identical source. ## Test plan - [x] Diff inspection: each of the three workflows now declares `git_hash`, `git_version`, `build_date` in nu and threads them through three `--build-arg` flags into `docker buildx build`. - [ ] After merge, the next CI run on `main` produces an image where `docker run dev.a8n.run/a8n-tools-private/lets-chat:latest --version` prints `lets-chat 0.1.0 (<git describe>, commit <12-char hash>, built <ISO 8601>)` with NO `unknown` substring. - [ ] After the c-01 pull-and-up cycle, the admin nav at `chat.pugtsurani.net` reads `v0.1.0 (<hash>)` instead of `v0.1.0 (unknown)`. - [ ] `/settings` "About" panel on the deployed staging shows a real commit hash and ISO 8601 build date. - [ ] Desktop linux + windows binaries built by the next CI run print real values on `--version`.
fix(ci): inject git_hash / git_version / build_date as build args (LC-214)
All checks were successful
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 6s
check-secrets / Nosey parker (pull_request) Successful in 6s
check-secrets / TruffleHog (pull_request) Successful in 8s
Create release / Create release from merged PR (pull_request) Has been skipped
check-secrets / Kingfisher (pull_request) Successful in 11s
Check / clippy + fmt + tests (pull_request) Successful in 4m35s
9429dcc659
`server/build.rs` populates the compile-time env vars `GIT_HASH`, `GIT_VERSION`, and `BUILD_DATE`, which `server/src/version.rs` re-exports as `pub const`s consumed by the admin nav badge, the settings about panel, the password reset / email verification pages, the `--version` banner, and the backup archive header.

Two compounding bugs caused every CI-built artifact (web OCI image, desktop linux bundle, desktop windows binary) to bake the literal string `unknown` instead of real values:

1. The three Forgejo workflows passed only `--build-arg CARGO_BUILD_JOBS=...` to `docker buildx build`, never the provenance args. `ci-build/Dockerfile.{web,desktop-linux-bundles,desktop-windows}` declare `ARG GIT_HASH=unknown` / `ARG GIT_VERSION=unknown` / `ARG BUILD_DATE=unknown` defaults followed by `ENV` lines, so the missing args flowed through as the literal default.
2. `.dockerignore:11` excludes `.git/` from the build context, so the `build.rs` fallback path (invoke `git rev-parse` / `git describe` inside the container) cannot recover the values. `build.rs` reads `env::var("GIT_HASH")` first, finds the non-empty `"unknown"` from the Dockerfile ARG, and treats it as resolved.

User-visible effect on staging: the admin nav at `chat.pugtsurani.net` reads `v0.1.0 (unknown)` instead of `v0.1.0 (a1b2c3d4e5f6)`; the same `unknown` substring appears in the settings about panel and the `--version` output.

In each of the three workflows, compute `git_hash` (12-char short hash), `git_version` (`git describe --tags --always --dirty`), and `build_date` (ISO-8601 UTC) in nushell at the top of the build step and pass all three through `--build-arg`. The `checkout` step already uses `fetch-depth: 0`, so `git describe` resolves tags correctly.

`BUILD_DATE` is captured once per build step so every image in that step shares the same wall-clock anchor. The provenance args are NOT content-addressable, so passing them does NOT invalidate buildx's `cache-from` / `cache-to` layer cache on identical source.

Left in place:
- `.dockerignore:11` excluding `.git/`. Pulling `.git/` into the build context would bloat layer keys and only paper over the missing CI wiring.
- The `ARG ...=unknown` defaults in the three Dockerfiles. They remain a sane fallback for ad-hoc `docker build` from a developer machine that forgets to pass the args.
- `ci-build/Dockerfile.desktop-windows-installer` is not patched: it wraps a pre-built `.exe` with NSIS and has no compiled-from-source step that consumes build provenance.

#LC-214
nrupard deleted branch fix/lc-214-ci-build-provenance 2026-05-29 16:48:35 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!256
No description provided.