HERMES-GIELIE/api
nesquena-hermes 38e215e8f8
fix: dynamic version badge — read from git tag, never hardcoded (#790)
* fix: dynamic version badge — read from git tag, never hardcoded

The settings panel showed v0.50.87 and the HTTP Server: header said
HermesWebUI/0.50.38 — both hardcoded strings that drift further behind
with every release because there was no mechanism to keep them in sync.

Changes:
- api/updates.py: add _run_git() (moved before _detect_webui_version),
  _detect_webui_version(), and WEBUI_VERSION module constant resolved
  once at import time via 'git describe --tags --always --dirty'.
  Fallback chain: git → api/_version.py → 'unknown'.
- api/routes.py: inject webui_version into GET /api/settings response
  so the frontend can read it without a separate API call.
- static/panels.js: loadSettingsPanel() populates .settings-version-badge
  from settings.webui_version — one line after the existing api() call.
- static/index.html: replace stale hardcoded 'v0.50.87' with '—'
  placeholder; JS overwrites it as soon as the settings panel opens.
- server.py: replace hardcoded 'HermesWebUI/0.50.38' server_version with
  'HermesWebUI/' + WEBUI_VERSION.lstrip('v') — stays in sync automatically.
- Dockerfile: add ARG HERMES_VERSION=unknown and write api/_version.py
  so Docker images (where .git is excluded) still show the correct tag.
- .github/workflows/release.yml: pass build-args: HERMES_VERSION=${{ github.ref_name }}
  to the Docker build step on tag pushes.
- .gitignore: exclude api/_version.py (generated by Docker/CI, never committed).

No manual 'update the version badge' step is required going forward.
Tagging is sufficient — the badge and HTTP header update automatically.

Tests: 18 new tests in tests/test_version_badge.py covering the full
resolution chain, /api/settings injection, HTML placeholder, JS wiring,
and server.py import. 1596 tests pass total.

* fix: address review feedback on PR #790

- api/updates.py: replace exec() with regex parse for api/_version.py
  (no supply-chain risk from build artifact; exec unnecessary for one assignment)
- api/updates.py: cap git describe timeout at 3s (was 10s — import-time
  stall on NFS/.git would block server startup unnecessarily)
- server.py: lstrip('v') → removeprefix('v') (lstrip strips chars not prefix)
- server.py: emit bare 'HermesWebUI' when version is 'unknown' rather than
  'HermesWebUI/unknown' (log aggregators expect semver-ish suffix or none)
- CHANGELOG.md: add v0.50.124 entry for this user-visible change
- tests: rename exec-error test to reflect regex behaviour; add tests for
  removeprefix usage and unknown-version header guard (1598 tests total)

---------

Co-authored-by: nesquena-hermes <hermes@nesquena.com>
2026-04-20 20:36:53 -07:00
..
__init__.py Hermes Web UI — Sprints 11-14: multi-provider models, settings, session QoL, alerts, polish 2026-03-31 07:02:47 +00:00
auth.py release: v0.50.102–v0.50.108 batch (code blocks, utf-8, image URLs, deletion warning, PermissionError, Docker docs, kimi-k2.5) (#755) 2026-04-20 00:26:55 -07:00
clarify.py feat: harden clarify dialog flow and refresh recovery 2026-04-15 13:10:50 +08:00
commands.py feat: slash command parity + skill autocomplete — v0.50.91 (PR #711) 2026-04-19 05:37:44 +00:00
config.py fix(config): invalidate model-list TTL cache on default-model change 2026-04-20 19:32:33 -07:00
gateway_watcher.py fix(sessions): return None instead of 'unknown' for missing gateway session model (fixes #443) 2026-04-14 19:06:22 +00:00
helpers.py fix(csp): allow external https images in img-src — closes #608 2026-04-16 23:34:21 -07:00
models.py perf: TTL cache for model list + incremental session index (#780) 2026-04-21 00:33:03 +00:00
onboarding.py fix(onboarding): remove CLI fast path from _provider_oauth_authenticated — fixes 4 test failures 2026-04-18 07:23:16 +00:00
profiles.py release: v0.50.102–v0.50.108 batch (code blocks, utf-8, image URLs, deletion warning, PermissionError, Docker docs, kimi-k2.5) (#755) 2026-04-20 00:26:55 -07:00
routes.py fix: dynamic version badge — read from git tag, never hardcoded (#790) 2026-04-20 20:36:53 -07:00
session_ops.py feat: slash command parity + skill autocomplete — v0.50.91 (PR #711) 2026-04-19 05:37:44 +00:00
startup.py v0.46.0: security, Docker UID/GID, model discovery, i18n, cancel fix 2026-04-11 10:17:52 -07:00
state_sync.py security: bandit fixes B310/B324/B110 + QuietHTTPServer (#354) 2026-04-13 11:11:56 -07:00
streaming.py fix(streaming): eagerly release session lock in cancel_stream() (#778) 2026-04-20 23:54:40 +00:00
updates.py fix: dynamic version badge — read from git tag, never hardcoded (#790) 2026-04-20 20:36:53 -07:00
upload.py v0.50.25: mobile scroll, import timestamps, profile security, mic fallback (#404) 2026-04-13 22:11:45 -07:00
workspace.py fix: HERMES_WEBUI_DEFAULT_WORKSPACE wins over settings.json; trust DEFAULT_WORKSPACE subtree (#610) 2026-04-16 18:09:16 -07:00