ops/dossiers-ngi: hourly branch-status builder + systemd timer
This commit is contained in:
parent
83998499da
commit
6e57fceb19
5 changed files with 195 additions and 0 deletions
42
scripts/dossiers-ngi/README.md
Normal file
42
scripts/dossiers-ngi/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# dossiers-ngi — cascade landing + hourly branch-status
|
||||
|
||||
SoT for the blank cascade landing on **dossiers.ngi.hacktivism.ch**
|
||||
(path roots only; no dossiers.2 / dossiers.3 ownership here).
|
||||
|
||||
| Path | Role |
|
||||
|------|------|
|
||||
| `sites/dossiers.ngi.hacktivism.ch/` | Landing HTML (EN, ASCII ladder) |
|
||||
| `scripts/dossiers-ngi/branch-status-hourly.py` | Read tips from tdpd checkout → `branch-status.json` |
|
||||
| `configs/systemd/user/dossiers-ngi-branch-status.{timer,service}` | Hourly oneshot on koopa |
|
||||
|
||||
## Env
|
||||
|
||||
| Var | Default | Meaning |
|
||||
|-----|---------|---------|
|
||||
| `TDPD_ROOT` | `$HOME/git/src/ngi/tech-dossier-project-data` | tech-dossier-project-data checkout for tip SHAs |
|
||||
| `ADMIN_LOG` | (script derives from `__file__`) | koopa-admin-log root |
|
||||
|
||||
On koopa the clone often lives at `%h/src/koopa/koopa-admin-log`; set
|
||||
`TDPD_ROOT` in the service `Environment=` if the tdpd path differs.
|
||||
|
||||
## Manual run
|
||||
|
||||
```bash
|
||||
python3 scripts/dossiers-ngi/branch-status-hourly.py
|
||||
# → sites/dossiers.ngi.hacktivism.ch/branch-status.json
|
||||
```
|
||||
|
||||
## Deploy landing (Freigabe)
|
||||
|
||||
```text
|
||||
hernani@koopa:/var/www/monitoring-sites/dossiers.ngi.hacktivism.ch/
|
||||
```
|
||||
|
||||
rsync from `sites/dossiers.ngi.hacktivism.ch/` — Freigabe this session required.
|
||||
Hourly JSON can sit next to the HTML once the timer is installed on koopa
|
||||
(Freigabe for host mutation).
|
||||
|
||||
## Ownership
|
||||
|
||||
Hourly builder belongs in **kal** (this tree). Do **not** put
|
||||
`scripts/branch-status-hourly.py` back into tdpd.
|
||||
84
scripts/dossiers-ngi/branch-status-hourly.py
Executable file
84
scripts/dossiers-ngi/branch-status-hourly.py
Executable file
|
|
@ -0,0 +1,84 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Emit branch-status.json for the dossiers.ngi path-root ladder.
|
||||
|
||||
Reads tip SHAs from the tech-dossier-project-data git checkout
|
||||
(TDPD_ROOT / default). Writes under the kal landing SoT:
|
||||
|
||||
sites/dossiers.ngi.hacktivism.ch/branch-status.json
|
||||
|
||||
Path roots only under https://dossiers.ngi.hacktivism.ch/
|
||||
(/main/, /feat-sm-content/, /feat-website-features/,
|
||||
/feat-website-design/, /feat-website-views/).
|
||||
Single public host only. Hourly builder lives in kal, not tdpd.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
ADMIN_LOG = Path(__file__).resolve().parents[2]
|
||||
OUT = ADMIN_LOG / "sites" / "dossiers.ngi.hacktivism.ch" / "branch-status.json"
|
||||
HOST = "https://dossiers.ngi.hacktivism.ch"
|
||||
|
||||
# Default local clone; override with TDPD_ROOT (koopa may use a different path).
|
||||
DEFAULT_TDPD = Path.home() / "git" / "src" / "ngi" / "tech-dossier-project-data"
|
||||
|
||||
LADDER = [
|
||||
("main", "", f"{HOST}/main/"),
|
||||
("feat/sm-content", "main", f"{HOST}/feat-sm-content/"),
|
||||
("feat/website-features", "feat/sm-content", f"{HOST}/feat-website-features/"),
|
||||
("feat/website-design", "feat/website-features", f"{HOST}/feat-website-design/"),
|
||||
("feat/website-views", "feat/website-design", f"{HOST}/feat-website-views/"),
|
||||
]
|
||||
|
||||
|
||||
def tdpd_root() -> Path:
|
||||
raw = os.environ.get("TDPD_ROOT", "").strip()
|
||||
return Path(raw).expanduser() if raw else DEFAULT_TDPD
|
||||
|
||||
|
||||
def tip_of(repo: Path, branch: str) -> str:
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
["git", "-C", str(repo), "rev-parse", "--short", branch],
|
||||
stderr=subprocess.DEVNULL,
|
||||
text=True,
|
||||
).strip()
|
||||
return out
|
||||
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
||||
return ""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
repo = tdpd_root()
|
||||
if not (repo / ".git").exists() and not repo.is_dir():
|
||||
print(f"TDPD_ROOT missing or not a dir: {repo}", file=sys.stderr)
|
||||
return 1
|
||||
branches = []
|
||||
for name, parent, url in LADDER:
|
||||
branches.append(
|
||||
{
|
||||
"branch": name,
|
||||
"tip": tip_of(repo, name),
|
||||
"parent": parent,
|
||||
"url": url,
|
||||
}
|
||||
)
|
||||
payload = {
|
||||
"generated": datetime.now(timezone.utc).astimezone().isoformat(timespec="seconds"),
|
||||
"host": HOST,
|
||||
"tdpd_root": str(repo),
|
||||
"branches": branches,
|
||||
}
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"wrote {OUT}", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue