Recently Written · git

subplz-web

git clone https://github.com/equwal/subplz-web

Log | Files | Refs


commit ca036bce54a881736cf8a97caeb845875f522a50
equwal <truex@equwal.com>
2026-09-20 21:22:51 -0700

Report the running release in /healthz; document tagging

 README.md       | 12 ++++++++++++
 backend/main.py | 17 +++++++++++++++++
 2 files changed, 29 insertions(+)
diff --git a/README.md b/README.md
index f95907b..6d8a9ae 100644
--- a/README.md
+++ b/README.md
@@ -373,6 +373,18 @@ once you are registered somewhere).
 
 ---
 
+## Releases
+
+Every deploy is a tag (`vMAJOR.MINOR.PATCH`) with a GitHub release; `/healthz`
+reports which one is running. Tag, push, then deploy that tag:
+
+```bash
+git tag -a v2.0.1 -m "what changed" && git push origin main --tags
+gh release create v2.0.1 --notes "what changed"
+```
+
+---
+
 ## Scaling out
 
 Everything environment-specific is an env var with a localhost default. See
diff --git a/backend/main.py b/backend/main.py
index 484ace4..bceb993 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -10,6 +10,7 @@ from __future__ import annotations
 
 import logging
 import mimetypes
+import subprocess
 from contextlib import asynccontextmanager
 
 from fastapi import FastAPI
@@ -30,6 +31,21 @@ log = logging.getLogger("subplz.web")
 
 FRONTEND = ROOT / "frontend"
 
+
+def _version() -> str:
+    """The release this checkout is: the nearest git tag, e.g. v2.0.0 or
+    v2.0.0-3-gabc1234 when it is ahead of one. Answers "what is deployed?"."""
+    try:
+        return subprocess.run(
+            ["git", "-c", f"safe.directory={ROOT.as_posix()}", "describe", "--tags", "--always", "--dirty"],
+            cwd=ROOT, capture_output=True, text=True, timeout=10, check=True,
+        ).stdout.strip() or "unknown"
+    except (subprocess.SubprocessError, OSError):
+        return "unknown"
+
+
+VERSION = _version()
+
 # Python takes these from the OS, and Windows gets both wrong. A module served
 # as text/plain is refused outright, and WebAssembly will not stream-compile.
 mimetypes.add_type("text/javascript", ".js")
@@ -108,6 +124,7 @@ async def cross_origin_isolation(request, call_next):
 def healthz():
     return {
         "ok": True,
+        "version": VERSION,
         "languages": len(all_languages()),
         "queue_backend": settings.queue_backend,
         "queue_depth": queue.depth(),