All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m15s
The sentinel was written to shared/_reload_sentinel.py but shared/ is volume-mounted as root:root, so appuser can't create files there. Move sentinel to /app/_reload_sentinel.py which is owned by appuser and still under Hypercorn's --reload watch path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
"""Watch non-Python files and trigger Hypercorn reload.
|
|
|
|
Hypercorn --reload only watches .py files. This script watches .sx,
|
|
.sx, .js, and .css files and touches a sentinel .py file when they
|
|
change, causing Hypercorn to restart.
|
|
|
|
Usage (from entrypoint.sh, before exec hypercorn):
|
|
python3 -m shared.dev_watcher &
|
|
"""
|
|
|
|
import os
|
|
import time
|
|
import sys
|
|
|
|
WATCH_EXTENSIONS = {".sx", ".sx", ".js", ".css"}
|
|
SENTINEL = "/app/_reload_sentinel.py"
|
|
POLL_INTERVAL = 1.5 # seconds
|
|
|
|
|
|
def _collect_mtimes(roots):
|
|
mtimes = {}
|
|
for root in roots:
|
|
for dirpath, _dirs, files in os.walk(root):
|
|
for fn in files:
|
|
ext = os.path.splitext(fn)[1]
|
|
if ext in WATCH_EXTENSIONS:
|
|
path = os.path.join(dirpath, fn)
|
|
try:
|
|
mtimes[path] = os.path.getmtime(path)
|
|
except OSError:
|
|
pass
|
|
return mtimes
|
|
|
|
|
|
def main():
|
|
# Watch /app/shared and /app/<service>/sx plus static dirs
|
|
roots = []
|
|
for entry in os.listdir("/app"):
|
|
full = os.path.join("/app", entry)
|
|
if os.path.isdir(full):
|
|
roots.append(full)
|
|
if not roots:
|
|
roots = ["/app"]
|
|
|
|
# Ensure sentinel exists
|
|
if not os.path.exists(SENTINEL):
|
|
with open(SENTINEL, "w") as f:
|
|
f.write("# reload sentinel\n")
|
|
|
|
prev = _collect_mtimes(roots)
|
|
while True:
|
|
time.sleep(POLL_INTERVAL)
|
|
curr = _collect_mtimes(roots)
|
|
changed = []
|
|
for path, mtime in curr.items():
|
|
if path not in prev or prev[path] != mtime:
|
|
changed.append(path)
|
|
if changed:
|
|
names = ", ".join(os.path.basename(p) for p in changed[:3])
|
|
if len(changed) > 3:
|
|
names += f" (+{len(changed) - 3} more)"
|
|
print(f"[dev_watcher] Changed: {names} — triggering reload",
|
|
flush=True)
|
|
os.utime(SENTINEL, None)
|
|
prev = curr
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|