Flatten budget-app contents into repo root

This commit is contained in:
jpmvaz
2026-10-29 20:41:01 +00:00
parent c9fd26f1c7
commit 93f2696764
95 changed files with 184 additions and 187 deletions
+59
View File
@@ -0,0 +1,59 @@
"""Run before `alembic upgrade`: when there are database changes to apply, ask the backup container for a
fresh dump and wait for it, so every upgrade can be rolled back to the moment just before it.
The api stops (and Docker retries it) if the backup fails, unless SKIP_PRE_UPGRADE_BACKUP=true.
"""
import os
import sys
import time
import uuid
from pathlib import Path
from alembic.config import Config
from alembic.runtime.migration import MigrationContext
from alembic.script import ScriptDirectory
from .db import engine
REQUESTS = Path(os.getenv("BACKUP_REQUEST_DIR", "/requests"))
TIMEOUT = int(os.getenv("PRE_UPGRADE_BACKUP_TIMEOUT", "900"))
def pending() -> tuple[str | None, str]:
head = ScriptDirectory.from_config(Config("alembic.ini")).get_current_head()
with engine.connect() as conn:
current = MigrationContext.configure(conn).get_current_revision()
return current, head
def main() -> int:
current, head = pending()
if current is None or current == head:
return 0 # new database, or nothing to migrate
if os.getenv("SKIP_PRE_UPGRADE_BACKUP", "").lower() == "true":
print(f"pre-upgrade backup skipped ({current} -> {head})", flush=True)
return 0
if not REQUESTS.is_dir():
print(f"pre-upgrade backup: {REQUESTS} not mounted, cannot ask the backup container", file=sys.stderr, flush=True)
return 1
rid = time.strftime("%Y%m%d%H%M%S") + "-" + uuid.uuid4().hex[:6]
(REQUESTS / f"{rid}.request").write_text(f"database upgrade {current} -> {head}\n")
print(f"database upgrade {current} -> {head}: waiting for the backup container to take a backup", flush=True)
done = REQUESTS / f"{rid}.done"
deadline = time.time() + TIMEOUT
while time.time() < deadline:
if done.exists():
answer = done.read_text().strip() # the backup container clears old answers itself
if answer == "ok":
print("pre-upgrade backup written", flush=True)
return 0
print("pre-upgrade backup FAILED; not upgrading. See: docker compose logs backup", file=sys.stderr, flush=True)
return 1
time.sleep(2)
print("pre-upgrade backup did not answer in time; not upgrading. Is the backup container running?",
file=sys.stderr, flush=True)
return 1
if __name__ == "__main__":
sys.exit(main())