Some checks failed
- deploy.sh writes .build-info with commit SHA and timestamp after git pull - /health endpoint now returns version, commit, and deployed_at fields - Admin sidebar footer shows version and commit SHA - Hetzner docs updated: runner --config flag, swap, and runner timeout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.6 KiB
Python
61 lines
1.6 KiB
Python
# app/core/build_info.py
|
|
"""
|
|
Build information utilities.
|
|
|
|
Reads commit SHA and deploy timestamp from .build-info file
|
|
(written by scripts/deploy.sh at deploy time), or falls back
|
|
to git for local development.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import subprocess
|
|
from datetime import UTC, datetime
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_BUILD_INFO_FILE = Path(__file__).resolve().parent.parent.parent / ".build-info"
|
|
_cached_info: dict | None = None
|
|
|
|
|
|
def get_build_info() -> dict:
|
|
"""Return build info: commit, deployed_at, environment."""
|
|
global _cached_info
|
|
if _cached_info is not None:
|
|
return _cached_info
|
|
|
|
info = {
|
|
"commit": None,
|
|
"deployed_at": None,
|
|
}
|
|
|
|
# Try .build-info file first (written by deploy.sh)
|
|
if _BUILD_INFO_FILE.is_file():
|
|
try:
|
|
data = json.loads(_BUILD_INFO_FILE.read_text())
|
|
info["commit"] = data.get("commit")
|
|
info["deployed_at"] = data.get("deployed_at")
|
|
except Exception as e:
|
|
logger.warning(f"Failed to read .build-info: {e}")
|
|
|
|
# Fall back to git for local development
|
|
if not info["commit"]:
|
|
try:
|
|
result = subprocess.run(
|
|
["git", "rev-parse", "--short=8", "HEAD"],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=5,
|
|
)
|
|
if result.returncode == 0:
|
|
info["commit"] = result.stdout.strip()
|
|
except Exception:
|
|
pass
|
|
|
|
if not info["deployed_at"]:
|
|
info["deployed_at"] = datetime.now(UTC).isoformat()
|
|
|
|
_cached_info = info
|
|
return info
|