Skip to content

fix(docker): bake build-time git SHA into the image so hermes dump reports it#33655

Merged
benbarclay merged 1 commit into
mainfrom
docker-commit-sha
May 28, 2026
Merged

fix(docker): bake build-time git SHA into the image so hermes dump reports it#33655
benbarclay merged 1 commit into
mainfrom
docker-commit-sha

Conversation

@benbarclay

Copy link
Copy Markdown
Collaborator

Problem

Users running hermes dump inside the Docker container see:

--- hermes dump ---
version:          0.14.0 (2026.5.16) [(unknown)]

The startup banner has the same issue — it drops its · upstream <sha> suffix entirely inside the container. Root cause: .dockerignore line 2 excludes .git, so git rev-parse HEAD always fails inside the image. That makes support triage from container bug reports impossible — we can't tell which commit the user is actually running.

Fix

Thread the build-time commit SHA through as a Docker build-arg, write it to /opt/hermes/.hermes_build_sha in the image, and have a new hermes_cli/build_info.get_build_sha() helper read it as a fallback after the existing live-git lookup fails.

Output format is identical between live-git and baked-SHA paths — same 8-char short SHA whether resolved live or baked. No special-casing required in support tooling that parses hermes dump.

After the fix

CI-built images:

--- hermes dump ---
version:          0.14.0 (2026.5.16) [abc12345]
Hermes Agent v0.14.0 (2026.5.16) · upstream abc12345

Source installs and local docker build without --build-arg are unchanged: the helper returns None when the file is absent, and callers fall through to live git rev-parse.

Changes

File What
Dockerfile ARG HERMES_GIT_SHA= + conditional file write after the source copy. Empty/missing arg → no file → callers fall back to live git.
.github/workflows/docker-publish.yml Passes HERMES_GIT_SHA=${{ github.sha }} on all four build-push-action steps (amd64/arm64 × smoke-test/push).
hermes_cli/build_info.py (new) Single read-side helper. Defensive: returns None on any IO error.
hermes_cli/dump.py _get_git_commit() tries live git, then baked SHA, then (unknown).
hermes_cli/banner.py get_git_banner_state() falls back to baked SHA as {upstream==local, ahead=0} — a built image is pinned to one commit by definition.

Test coverage

Unit (19 new tests):

  • tests/hermes_cli/test_build_info.py — file present/absent/empty/whitespace/error, truncation behavior
  • tests/hermes_cli/test_dump_git_commit.py — live-git wins; both fallback paths; legacy (unknown) preserved; identical-output-format regression guard (per request to keep dump output unchanged)
  • tests/hermes_cli/test_banner_git_state.py (extended) — no-repo + baked SHA, no-repo + no-SHA, shallow-clone fallback

Integration:

  • tests/docker/test_dump_build_sha.py — runs against the real built image, reads /opt/hermes/.hermes_build_sha, asserts hermes dump surfaces it (or stays at (unknown) if no build-arg was passed)

Verified end-to-end locally:

  • docker build --build-arg HERMES_GIT_SHA=abc1234567890abc1234567890abc1234567890a .docker run ... dump reports [abc12345]
  • docker build . (no arg) → reports [(unknown)] (unchanged from main) ✅
  • Full tests/hermes_cli/ suite: 5576 tests pass, 0 failures
  • hadolint Dockerfile clean

Lane

Pure area/docker — Dockerfile, docker workflow, and the tiny build_info.py helper that reads a file baked at image build time. No changes to run_agent.py, model_tools.py, gateway, or any runtime code path Teknium owns.

`hermes dump` and the startup banner both call `git rev-parse HEAD` to
report the running commit, but `.dockerignore` line 2 excludes `.git` —
so inside the published image `hermes dump` shows
`version: ... [(unknown)]` and the banner drops its `· upstream <sha>`
suffix entirely.  That makes support triage from container bug reports
impossible: we can't tell which commit the user is actually running.

Fix: thread the build-time SHA through as a Docker build-arg, write it
to `/opt/hermes/.hermes_build_sha` in the image, and have a new
`hermes_cli/build_info.get_build_sha()` read it as a fallback after the
existing live-git lookup fails.  Output format is unchanged in both
callsites — same 8-char short SHA whether resolved live or baked.

Wiring:
  - Dockerfile: `ARG HERMES_GIT_SHA=` + write-file step after the source
    copy.  Empty/missing arg → no file written → callers fall through to
    live git (so local `docker build` without --build-arg is unchanged).
  - docker-publish.yml: passes `HERMES_GIT_SHA=${{ github.sha }}` on all
    four build-push-action steps (amd64/arm64, smoke-test + final push).
  - dump.py:_get_git_commit() / banner.py:get_git_banner_state(): try
    live git first, fall back to baked SHA, then to legacy `(unknown)`
    / None.  Banner returns `upstream == local, ahead=0` because a built
    image is by definition pinned to one commit.

Coverage:
  - Unit tests cover build_info (file present/absent/empty/error,
    truncation, whitespace), dump (live-git wins, both fallbacks,
    identical output-format regression guard), and banner (no-repo +
    baked, no-repo + no-sha, shallow-clone fallback).
  - tests/docker/test_dump_build_sha.py is an integration regression
    guard that runs against the real image, reads
    `/opt/hermes/.hermes_build_sha`, and asserts `hermes dump` surfaces
    its content (or stays at `(unknown)` if no file).
  - Verified end-to-end: `docker build --build-arg HERMES_GIT_SHA=abc...`
    → `docker run ... dump` reports `[abc12345]`; without the build-arg
    it reports `[(unknown)]` as before.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: docker-commit-sha vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9520 on HEAD, 9520 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5016 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have area/docker Docker image, Compose, packaging comp/cli CLI entry point, hermes_cli/, setup wizard labels May 28, 2026
@benbarclay benbarclay merged commit 66489f3 into main May 28, 2026
27 checks passed
@benbarclay benbarclay deleted the docker-commit-sha branch May 28, 2026 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docker Docker image, Compose, packaging comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants