-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathdocs_hooks.py
More file actions
121 lines (103 loc) · 5.75 KB
/
Copy pathdocs_hooks.py
File metadata and controls
121 lines (103 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""MkDocs build hooks for the Trailblaze docs site.
Report-gallery placeholder filling
-----------------------------------
The Report Gallery (`docs/reports.md`) and the landing-page embed reference per-trail
report assets under `docs/report-assets/<trail>/` (`storyboard.webp`, `timeline.webp`,
`report.html`). Those are produced by CI (`trailblaze report --storyboard --webp`),
uploaded as artifacts, and fetched into the build workspace by the GitHub Pages workflow
— they are NOT committed (the per-trail dirs are gitignored), so the repo carries no
per-trail binaries.
NOTE: assets deliberately live under `docs/report-assets/`, NOT `docs/generated/` —
`docs/generated/` is owned by `:docs:generator:run` and `scripts/generate-docs-and-diff.sh`
does `rm -rf docs/generated` + a reproducibility `git diff`, so anything hand-authored or
runtime-fetched there fails CI.
To keep `mkdocs build --strict` green everywhere (local `mkdocs serve`, the PR
docs-build-check, and the deploy before/without a successful trail run), this hook fills
any MISSING per-trail asset with the single committed, reusable generic placeholder
(`docs/images/report-pending.webp`) just before the file scan. Real fetched assets always
win — the hook only creates files that don't already exist.
Runs automatically on every `mkdocs build`/`serve`; no workflow wiring or staging step
needed. The gallery slugs come from the showcase manifest (`docs/showcase-trails.yml`),
so adding/retargeting a platform there is the only edit needed.
Report-viewer placeholder filling
---------------------------------
`docs/report-viewer/index.html` is the hosted standalone report viewer — one generated,
self-contained file that renders any session archive in the browser. Like the gallery
assets it is NOT committed: the GitHub Pages workflow builds it with
`scripts/build-viewer-shell.sh` (which needs `bun`) into the docs dir just before
`mkdocs build`. So that a docs build without `bun` — a contributor's `mkdocs serve`, the
PR docs-build-check — still resolves the links pointing at it under `--strict`, this hook
drops a short stand-in page there when the real one is absent. The real file always wins.
"""
from pathlib import Path
import yaml
# Gallery slugs (one report-assets/<slug>/ bucket per platform) are read from the
# showcase manifest so they stay in sync with what CI publishes. The fallback is
# used only if the manifest is missing/unreadable, so a strict docs build never
# breaks on a manifest hiccup.
_MANIFEST_NAME = "showcase-trails.yml"
_FALLBACK_SLUGS = ["wikipedia", "ios-contacts", "clock"]
def _gallery_slugs(docs_dir):
"""Gallery slugs from docs/showcase-trails.yml; fall back to the known set."""
manifest = docs_dir / _MANIFEST_NAME
try:
data = yaml.safe_load(manifest.read_text(encoding="utf-8")) or {}
slugs = [
entry["slug"]
for entry in data.values()
if isinstance(entry, dict) and entry.get("slug")
]
return slugs or _FALLBACK_SLUGS
except (OSError, yaml.YAMLError, AttributeError):
return _FALLBACK_SLUGS
_PENDING_HTML = """<!doctype html>
<meta charset="utf-8">
<title>Trailblaze report - generating in CI</title>
<body style="font-family:Inter,-apple-system,sans-serif;max-width:42rem;margin:4rem auto;padding:0 1.5rem;color:#1b4332;line-height:1.6">
<h1>Report generating in CI</h1>
<p>The full interactive Trailblaze report is generated by CI and published with the
docs site on the next push to <code>main</code>. Produce one yourself from any
session with <code>trailblaze report --id <session> --output-dir out --storyboard --webp</code>.</p>
<p><a href="https://github.com/block/trailblaze">Back to Trailblaze</a></p>
</body>
"""
_VIEWER_PENDING_HTML = """<!doctype html>
<meta charset="utf-8">
<title>Trailblaze report viewer - built by the docs deploy</title>
<body style="font-family:Inter,-apple-system,sans-serif;max-width:42rem;margin:4rem auto;padding:0 1.5rem;color:#1b4332;line-height:1.6">
<h1>Report viewer built by the docs deploy</h1>
<p>The standalone report viewer is generated at deploy time and published with the docs
site, so this docs build (which has no <code>bun</code>) is serving a stand-in.</p>
<p>Build the real one from a checkout with
<code>./scripts/build-viewer-shell.sh out</code>, then open <code>out/index.html</code>
and drop a session <code>.zip</code> on it.</p>
<p><a href="https://github.com/block/trailblaze">Back to Trailblaze</a></p>
</body>
"""
def _fill_viewer_placeholder(docs_dir):
"""Stand in for the generated report viewer when the deploy hasn't built it."""
viewer = docs_dir / "report-viewer" / "index.html"
if viewer.exists():
return
viewer.parent.mkdir(parents=True, exist_ok=True)
viewer.write_text(_VIEWER_PENDING_HTML, encoding="utf-8")
def on_pre_build(config):
"""Fill missing per-trail report assets before MkDocs scans the docs dir."""
docs_dir = Path(config["docs_dir"])
_fill_viewer_placeholder(docs_dir)
placeholder = docs_dir / "images" / "report-pending.webp"
if not placeholder.is_file():
# Without the generic placeholder there's nothing to copy; let the strict build
# surface the missing reference rather than silently skipping.
return
pending_bytes = placeholder.read_bytes()
for trail in _gallery_slugs(docs_dir):
trail_dir = docs_dir / "report-assets" / trail
trail_dir.mkdir(parents=True, exist_ok=True)
for webp in ("storyboard.webp", "timeline.webp"):
target = trail_dir / webp
if not target.exists():
target.write_bytes(pending_bytes)
report_html = trail_dir / "report.html"
if not report_html.exists():
report_html.write_text(_PENDING_HTML, encoding="utf-8")