koopa-admin-log/scripts/dossiers-ngi/README.md

118 lines
5 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# dossiers-ngi — dynamic edition bar + 10‑min rebuild
SoT for the sticky edition bar on **dossiers.ngi.hacktivism.ch**. Live freezes
sit under `editions/<slug>/` on koopa; cookie `tdpd_edition` selects the build.
The bar renders a **semi-graphic parent→children tree** from
`/branch-status.json` (all `origin/*` tips, not a hard-coded ladder).
| Path | Role |
|------|------|
| `sites/…/_cascade/` | Sticky bar shell + JS tree renderer |
| `editions/` on koopa www | Full freezes switched by the bar |
| `sites/…/cascade/` | Legacy tip stubs (optional) |
| `scripts/dossiers-ngi/branch-status-hourly.py` | Fetch remotes → tree JSON → on-demand rebuild |
| `scripts/dossiers-ngi/smoke-branch-tree.sh` | Temp-branch smoke (creates/deletes local origin only) |
| `configs/systemd/user/dossiers-ngi-branch-status.{timer,service}` | Every **10 min** oneshot on koopa (`flock` against overlap) |
## Env
| Var | Default | Meaning |
|-----|---------|---------|
| `TDPD_ROOT` | `$HOME/git/src/ngi/tech-dossier-project-data` | tdpd git checkout (may be git-dir only) |
| `TDPD_VENV` | `(TDPD_ROOT)/.venv` | Frozen-Flask venv; symlinked into worktrees |
| `OUT` | kal `sites/…/branch-status.json` | write path (live www on koopa) |
| `EDITIONS_ROOT` | (none) | `…/editions` — required for `--rebuild` |
| `REBUILD` / `--rebuild` | off | rebuild when `.edition-tip` ≠ tip |
| `FORCE_REBUILD` / `--force` | off | rebuild every branch (timing) |
| `FETCH` / `--no-fetch` | fetch on | `git fetch --prune origin` |
| `FREEZE_CMD` | (make/venv freeze) | stub for smoke tests; `{root}` `{branch}` `{slug}` |
| `DEFAULT_BRANCH` | `feat/website-views` | behind cookie `flask` |
| `HOST` | `https://dossiers.ngi.hacktivism.ch` | public host in JSON |
On koopa: `%h/src/koopa/koopa-admin-log` +
`~/.config/dossiers-ngi/branch-status.env` for path overrides.
NGI clone token lives in **koopa-admin-secrets-enc** (not this tree).
## Manual run
```bash
# JSON only
python3 scripts/dossiers-ngi/branch-status-hourly.py
# rebuild stale freezes + timing block in JSON
EDITIONS_ROOT=/var/www/monitoring-sites/dossiers.ngi.hacktivism.ch/editions \
python3 scripts/dossiers-ngi/branch-status-hourly.py --rebuild
# force all branches (wall clock → rebuild_timing)
… --rebuild --force
```
`rebuild_timing` fields: `wall_seconds`, `built`, `skipped`, `errors`,
`built_seconds_sum`, `built_seconds_max`. Per-branch `rebuild[name].seconds`.
Per branch in JSON / sticky bar:
| Field | Meaning |
|-------|---------|
| `tip` | short SHA |
| `tip_time` | committer time of tip (`%cI`) |
| `built_at` | when this edition freeze was written |
| `build_seconds` | wall time of that freeze |
Rebuild runs **only when** `.edition-tip` ≠ current tip (timer never forces).
Each run also: `git fetch --prune`, `worktree prune`, drop stale
`editions/<slug>/` (gone remotes), purge leftover `tdpd-*` tmp dirs.
## Smoke
```bash
bash scripts/dossiers-ngi/smoke-branch-tree.sh
# → SMOKE_OK (temp origin + smoke/temp-sibling deleted)
```
## Deploy landing (Freigabe)
Do **not** `--delete` the whole www root. Sync:
```bash
SITE="$HOME/git/admin-logs/local/koopa-admin-log/sites/dossiers.ngi.hacktivism.ch"
WWW=hernani@koopa:/var/www/monitoring-sites/dossiers.ngi.hacktivism.ch
rsync -avz --exclude .DS_Store "$SITE/_cascade/" "$WWW/_cascade/"
rsync -avz --exclude .DS_Store "$SITE/branch-status.json" "$WWW/branch-status.json"
# editions/ from a --rebuild run
```
## Sticky cascade bar
`bar.js` fetches `/branch-status.json` and draws:
```
main @ d2fbd79 · tip 2026-09-01 16:52 · build 8.4s · at 2026-09-30 15:23
├── feat/sm-content @ … · tip YYYY-MM-DD HH:MM · …
│ └── …
└── project_template @ …
```
`tip` / `at` always include **date + HH:MM** (ISO already in JSON; clock-only was misleading across days). The bar is **viewport-centered** (max-width 45em, mobile-friendly). Poll every 30s **updates tip/build/at text in place** when the branch structure is unchanged (no full tree remount).
Each name links to `/_cascade/use/<edition>` (cookie + 302 `/`). Caddy map:
```
~^[A-Za-z0-9_-]+$ {http.request.cookie.tdpd_edition}
```
Also serve `/cascade/*` from the site www root (path stubs). Live Caddy must not use a trailing `~.* flask` catch-all.
Edition purity: responses send `Vary: Cookie` and `Cache-Control: private, no-cache` so `/static/css/style.css` (same path, different bodies per edition) cannot stick the green design CSS onto `main` after a views visit.
so new branches need no Caddy edit — only an `editions/<slug>/` tree.
```bash
bash ~/bin/apply-dossiers-ngi-edition-switch.sh
sudo ~/bin/caddy-apply
```
Stanza SoT: `scripts/dossiers-ngi/caddy-dossiers-ngi.snippet`.
Caddy edition map must list each `editions/<slug>` explicitly. A map output of `{http.request.cookie.tdpd_edition}` did not expand on Caddy v2.11.4 (only `flask` worked → 404 for `main`/views). After new tips appear, refresh the snippet map (or regenerate from `ls editions`) before `apply-dossiers-ngi-edition-switch` + `caddy-apply`.