fix/dossiers-ngi: update README and scripts for branch status
This commit is contained in:
parent
c14e215ad8
commit
8ad49de231
8 changed files with 188 additions and 15 deletions
|
|
@ -301,6 +301,42 @@ def write_build_meta(editions: Path, slug: str, seconds: float) -> None:
|
|||
(dest / ".edition-build-seconds").write_text(f"{seconds:.3f}\n", encoding="utf-8")
|
||||
|
||||
|
||||
def write_freeze_status(editions: Path, slug: str, ok: bool, error: str = "") -> None:
|
||||
dest = editions / slug
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
(dest / ".edition-freeze-ok").write_text("1\n" if ok else "0\n", encoding="utf-8")
|
||||
errp = dest / ".edition-freeze-error"
|
||||
if ok or not error:
|
||||
if errp.exists():
|
||||
errp.unlink()
|
||||
return
|
||||
errp.write_text(error[:500] + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def freeze_ok_for(editions: Path | None, slug: str, tip_full: str) -> tuple[bool, str]:
|
||||
"""Current origin tip freeze succeeded (green ✓) or not (red ✗)."""
|
||||
if editions is None or not tip_full:
|
||||
return False, ""
|
||||
dest = editions / slug
|
||||
err = ""
|
||||
errp = dest / ".edition-freeze-error"
|
||||
if errp.is_file():
|
||||
err = errp.read_text(encoding="utf-8").strip()
|
||||
recorded = tip_recorded(editions, slug)
|
||||
okp = dest / ".edition-freeze-ok"
|
||||
if okp.is_file():
|
||||
file_ok = okp.read_text(encoding="utf-8").strip().lower() in (
|
||||
"1",
|
||||
"true",
|
||||
"ok",
|
||||
"yes",
|
||||
)
|
||||
else:
|
||||
file_ok = (dest / ".edition-built-at").is_file()
|
||||
ok = bool(file_ok and recorded == tip_full and (dest / "index.html").is_file())
|
||||
return ok, err
|
||||
|
||||
|
||||
def cleanup_stale_editions(editions: Path, tips: dict[str, str]) -> list[str]:
|
||||
"""Drop edition dirs whose branch tip is gone (keep flask alias)."""
|
||||
keep = {edition_slug(b) for b in tips} | {"flask"}
|
||||
|
|
@ -424,12 +460,10 @@ def rebuild_edition(repo: Path, branch: str, tip: str, editions: Path) -> dict:
|
|||
dest = editions / slug
|
||||
t0 = time.perf_counter()
|
||||
force = os.environ.get("FORCE_REBUILD", "").strip() in ("1", "true", "yes")
|
||||
if (
|
||||
not force
|
||||
and tip_recorded(editions, slug) == tip
|
||||
and (dest / "index.html").is_file()
|
||||
):
|
||||
if not force and freeze_ok_for(editions, slug, tip)[0]:
|
||||
inject_bar(dest)
|
||||
if not (dest / ".edition-freeze-ok").is_file():
|
||||
write_freeze_status(editions, slug, True)
|
||||
return {"status": "skipped", "seconds": round(time.perf_counter() - t0, 3)}
|
||||
|
||||
wt: Path | None = None
|
||||
|
|
@ -441,10 +475,12 @@ def rebuild_edition(repo: Path, branch: str, tip: str, editions: Path) -> dict:
|
|||
git(repo, "worktree", "prune", check=False)
|
||||
cp = git(repo, "worktree", "add", "--detach", str(wt), tip, check=False)
|
||||
if cp.returncode != 0:
|
||||
st = f"error:worktree:{cp.stderr.strip()[:200]}"
|
||||
ensure_placeholder(editions, slug, tip)
|
||||
write_freeze_status(editions, slug, False, st)
|
||||
inject_bar(dest)
|
||||
return {
|
||||
"status": f"error:worktree:{cp.stderr.strip()[:200]}",
|
||||
"status": st,
|
||||
"seconds": round(time.perf_counter() - t0, 3),
|
||||
}
|
||||
|
||||
|
|
@ -452,6 +488,7 @@ def rebuild_edition(repo: Path, branch: str, tip: str, editions: Path) -> dict:
|
|||
build = wt / "website" / "build"
|
||||
if not build.is_dir():
|
||||
ensure_placeholder(editions, slug, tip)
|
||||
write_freeze_status(editions, slug, False, "error:no-build")
|
||||
inject_bar(dest)
|
||||
return {"status": "error:no-build", "seconds": round(time.perf_counter() - t0, 3)}
|
||||
|
||||
|
|
@ -460,6 +497,8 @@ def rebuild_edition(repo: Path, branch: str, tip: str, editions: Path) -> dict:
|
|||
".edition-tip",
|
||||
".edition-built-at",
|
||||
".edition-build-seconds",
|
||||
".edition-freeze-ok",
|
||||
".edition-freeze-error",
|
||||
}
|
||||
for child in list(dest.iterdir()):
|
||||
if child.name in keep_meta:
|
||||
|
|
@ -477,13 +516,16 @@ def rebuild_edition(repo: Path, branch: str, tip: str, editions: Path) -> dict:
|
|||
secs = round(time.perf_counter() - t0, 3)
|
||||
(dest / ".edition-tip").write_text(tip + "\n", encoding="utf-8")
|
||||
write_build_meta(editions, slug, secs)
|
||||
write_freeze_status(editions, slug, True)
|
||||
inject_bar(dest)
|
||||
return {"status": "built", "seconds": secs}
|
||||
except Exception as exc: # noqa: BLE001 — hourly must continue
|
||||
st = f"error:{type(exc).__name__}:{exc}"
|
||||
ensure_placeholder(editions, slug, tip)
|
||||
write_freeze_status(editions, slug, False, st)
|
||||
inject_bar(dest)
|
||||
return {
|
||||
"status": f"error:{type(exc).__name__}:{exc}",
|
||||
"status": st,
|
||||
"seconds": round(time.perf_counter() - t0, 3),
|
||||
}
|
||||
finally:
|
||||
|
|
@ -510,10 +552,19 @@ def sync_flask_alias(editions: Path, tips: dict[str, str]) -> None:
|
|||
shutil.copytree(src, dst)
|
||||
(dst / ".edition-tip").write_text(tip + "\n", encoding="utf-8")
|
||||
# reuse src build meta if present
|
||||
for name in (".edition-built-at", ".edition-build-seconds"):
|
||||
for name in (
|
||||
".edition-built-at",
|
||||
".edition-build-seconds",
|
||||
".edition-freeze-ok",
|
||||
".edition-freeze-error",
|
||||
):
|
||||
s = src / name
|
||||
if s.is_file():
|
||||
shutil.copy2(s, dst / name)
|
||||
else:
|
||||
p = dst / name
|
||||
if p.exists():
|
||||
p.unlink()
|
||||
inject_bar(dst)
|
||||
|
||||
|
||||
|
|
@ -570,6 +621,7 @@ def build_payload(repo: Path, tips: dict[str, str], rebuild: bool) -> dict:
|
|||
slug = edition_slug(name)
|
||||
if not (ed_root / slug / "index.html").is_file():
|
||||
ensure_placeholder(ed_root, slug, tip)
|
||||
write_freeze_status(ed_root, slug, False, "placeholder")
|
||||
rebuild_status[name] = {"status": "placeholder", "seconds": 0.0}
|
||||
if not (ed_root / "flask" / "index.html").is_file():
|
||||
sync_flask_alias(ed_root, tips)
|
||||
|
|
@ -601,6 +653,15 @@ def build_payload(repo: Path, tips: dict[str, str], rebuild: bool) -> dict:
|
|||
entry["built_at"] = meta["built_at"]
|
||||
if "build_seconds" in meta:
|
||||
entry["build_seconds"] = meta["build_seconds"]
|
||||
freeze_ok, freeze_err = freeze_ok_for(ed_root, slug, tips[name])
|
||||
st = str(rb.get("status") or "")
|
||||
if st == "built":
|
||||
freeze_ok, freeze_err = True, ""
|
||||
elif st.startswith("error") or st == "placeholder":
|
||||
freeze_ok, freeze_err = False, st
|
||||
entry["freeze_ok"] = freeze_ok
|
||||
if freeze_err:
|
||||
entry["freeze_error"] = freeze_err
|
||||
# sticky bar: +grün/−rot vs parent tip; gray loc when no parent in tree
|
||||
parent = row["parent"]
|
||||
if parent and parent in tips:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue