Add unified template asset cache-busting version

This commit is contained in:
copilot-swe-agent[bot]
2026-05-27 15:59:50 +00:00
committed by GitHub
parent 1cd4fc8b40
commit 3745eedd74
3 changed files with 59 additions and 25 deletions
+35 -1
View File
@@ -652,6 +652,35 @@ templates = Jinja2Templates(directory=os.path.join(_BASE_DIR, "templates"))
# ── Static asset cache-busting ────────────────────────────────────
def _compute_asset_version() -> str:
"""Return a stable asset version string for cache-busting template assets."""
nix_match = re.search(r"/nix/store/([a-z0-9]{32})-", os.path.realpath(_BASE_DIR))
if nix_match:
return nix_match.group(1)[:16]
hasher = hashlib.sha256()
for root in (
os.path.join(_BASE_DIR, "static"),
os.path.join(_BASE_DIR, "templates"),
):
if not os.path.isdir(root):
continue
for dirpath, dirnames, filenames in os.walk(root):
dirnames.sort()
for filename in sorted(filenames):
path = os.path.join(dirpath, filename)
try:
stat = os.stat(path)
except OSError:
continue
hasher.update(path.encode())
hasher.update(f"{stat.st_mtime_ns}:{stat.st_size}".encode())
return hasher.hexdigest()[:16]
ASSET_VERSION = _compute_asset_version()
def _file_hash(filename: str) -> str:
"""Return first 8 chars of the MD5 hex digest for a static file."""
path = os.path.join(_BASE_DIR, "static", filename)
@@ -1894,7 +1923,10 @@ def _verify_support_removed() -> bool:
@app.get("/login", response_class=HTMLResponse)
async def login_page(request: Request):
return templates.TemplateResponse("login.html", {"request": request})
return templates.TemplateResponse("login.html", {
"request": request,
"asset_version": ASSET_VERSION,
})
@app.get("/auto-login")
@@ -1961,6 +1993,7 @@ async def api_logout(request: Request):
async def index(request: Request):
return templates.TemplateResponse("index.html", {
"request": request,
"asset_version": ASSET_VERSION,
})
@@ -1969,6 +2002,7 @@ async def onboarding(request: Request):
_ensure_onboarding_reopened_for_migration()
return templates.TemplateResponse("onboarding.html", {
"request": request,
"asset_version": ASSET_VERSION,
"onboarding_js_hash": _ONBOARDING_JS_HASH,
})
+22 -22
View File
@@ -4,17 +4,17 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sovran_SystemsOS Hub</title>
<link rel="stylesheet" href="/static/css/base.css" />
<link rel="stylesheet" href="/static/css/buttons.css" />
<link rel="stylesheet" href="/static/css/header.css" />
<link rel="stylesheet" href="/static/css/layout.css" />
<link rel="stylesheet" href="/static/css/tiles.css" />
<link rel="stylesheet" href="/static/css/modals.css" />
<link rel="stylesheet" href="/static/css/features.css" />
<link rel="stylesheet" href="/static/css/onboarding.css" />
<link rel="stylesheet" href="/static/css/support.css" />
<link rel="stylesheet" href="/static/css/domain-setup.css" />
<link rel="stylesheet" href="/static/css/security.css" />
<link rel="stylesheet" href="/static/css/base.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/buttons.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/header.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/layout.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/tiles.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/modals.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/features.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/onboarding.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/support.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/domain-setup.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/security.css?v={{ asset_version }}" />
</head>
<body>
@@ -263,16 +263,16 @@
</div>
</div>
<script src="/static/js/constants.js"></script>
<script src="/static/js/state.js"></script>
<script src="/static/js/helpers.js"></script>
<script src="/static/js/tiles.js"></script>
<script src="/static/js/service-detail.js"></script>
<script src="/static/js/support.js"></script>
<script src="/static/js/update.js"></script>
<script src="/static/js/rebuild.js"></script>
<script src="/static/js/features.js"></script>
<script src="/static/js/security.js"></script>
<script src="/static/js/events.js"></script>
<script src="/static/js/constants.js?v={{ asset_version }}"></script>
<script src="/static/js/state.js?v={{ asset_version }}"></script>
<script src="/static/js/helpers.js?v={{ asset_version }}"></script>
<script src="/static/js/tiles.js?v={{ asset_version }}"></script>
<script src="/static/js/service-detail.js?v={{ asset_version }}"></script>
<script src="/static/js/support.js?v={{ asset_version }}"></script>
<script src="/static/js/update.js?v={{ asset_version }}"></script>
<script src="/static/js/rebuild.js?v={{ asset_version }}"></script>
<script src="/static/js/features.js?v={{ asset_version }}"></script>
<script src="/static/js/security.js?v={{ asset_version }}"></script>
<script src="/static/js/events.js?v={{ asset_version }}"></script>
</body>
</html>
@@ -4,8 +4,8 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sovran Hub — Login</title>
<link rel="stylesheet" href="/static/css/base.css" />
<link rel="stylesheet" href="/static/css/buttons.css" />
<link rel="stylesheet" href="/static/css/base.css?v={{ asset_version }}" />
<link rel="stylesheet" href="/static/css/buttons.css?v={{ asset_version }}" />
</head>
<body>
<div class="login-wrapper">