Reading-guide depth rules, applied to all 230 guides #39
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: book | |
| # The book is built on pull requests as well as on master, because the two ways | |
| # it breaks — a mermaid diagram that no longer parses, and a SUMMARY.md entry | |
| # pointing at a moved file — are both invisible in markdown and obvious in the | |
| # rendered output. Catching those after the merge means catching them after they | |
| # have already deployed to Pages. | |
| # | |
| # Only a push to master deploys. Pull requests build and stop. | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| workflow_dispatch: | |
| # Least privilege by default; the deploy job elevates for itself. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: book-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # The reading guides' depth rules (CLAUDE.md § Reading-guide depth) have a | |
| # mechanical part — each step declaring its input and output, a collapsed | |
| # answer under every checklist item, a line-number gutter on every quoted | |
| # snippet. Across 230 guides those survive only if a script enforces them. | |
| # `--all` drops the ratchet the rollout ran behind: every guide is converted, | |
| # so a file that does not follow the rules is a new one that skipped them | |
| # rather than one the rollout has not reached. Nothing here needs a | |
| # toolchain, so it runs first and fast. | |
| depth: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Reading guides follow the depth rules | |
| run: python3 tools/check-reading-depth.py --check --all | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install mdbook + mdbook-mermaid | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: mdbook,mdbook-mermaid | |
| - name: Install mdbook-pdf | |
| uses: baptiste0928/cargo-install@v3 | |
| with: | |
| crate: mdbook-pdf | |
| - name: Add mermaid assets | |
| run: mdbook-mermaid install . | |
| - name: Build HTML + PDF | |
| # PDF backend enabled via env so plain local `mdbook build` needs only mdbook-mermaid. | |
| env: | |
| MDBOOK_OUTPUT__PDF: '{ "trying-times": 3 }' | |
| run: mdbook build | |
| - name: Bundle PDF into site | |
| run: cp book/pdf/output.pdf book/html/database-learning-path.pdf | |
| # Every chapter in SUMMARY.md must have produced a page, and every mermaid | |
| # block must have reached the renderer as a mermaid block rather than as a | |
| # plain code fence. Both are silent failures in markdown and obvious in the | |
| # rendered output, which is the whole reason to check here. | |
| - name: Check the rendered book | |
| run: | | |
| fail=0 | |
| checked=0 | |
| while read -r page; do | |
| # mdbook renders README.md as the directory's index.html | |
| case "$page" in | |
| */README.md) html="book/html/${page%README.md}index.html" ;; | |
| README.md) html="book/html/index.html" ;; | |
| *) html="book/html/${page%.md}.html" ;; | |
| esac | |
| checked=$((checked + 1)) | |
| if [ ! -f "$html" ]; then | |
| echo "::error::SUMMARY.md lists $page but $html was not rendered" | |
| fail=1 | |
| fi | |
| done < <(grep -oE '\]\(([^)]+\.md)\)' SUMMARY.md | sed 's/](//; s/)//' | sort -u) | |
| echo "checked $checked chapters from SUMMARY.md" | |
| # print.html concatenates every page, so it is excluded or every | |
| # diagram would be counted twice. | |
| src=$(grep -rho '^```mermaid' --include='*.md' . --exclude-dir=book --exclude-dir=drafts | wc -l | tr -d ' ') | |
| out=$(grep -rho 'class="mermaid"' book/html --include='*.html' --exclude='print.html' | wc -l | tr -d ' ') | |
| echo "mermaid blocks: $src in source, $out rendered" | |
| if [ "$out" -lt "$src" ]; then | |
| echo "::error::$((src - out)) mermaid block(s) did not render as mermaid" | |
| fail=1 | |
| fi | |
| exit $fail | |
| - uses: actions/upload-pages-artifact@v5 | |
| if: github.event_name == 'push' | |
| with: | |
| path: book/html | |
| # v4 stopped including dotfiles by default. Keeping them means this | |
| # version bump publishes byte-identically to before, rather than | |
| # silently changing the live site: mdbook emits .nojekyll, and the | |
| # source tree's stray .gitignore files get copied in by src = ".". | |
| # (Pages deployed via Actions never runs Jekyll, so .nojekyll is | |
| # almost certainly inert here — but proving that is a separate change | |
| # from bumping a version.) | |
| include-hidden-files: true | |
| deploy: | |
| needs: build | |
| if: github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pages: write | |
| id-token: write | |
| # deploy-pages resolves the artifact by id since v4 and documents | |
| # actions:read as required. It happens to work without it today, but | |
| # relying on that is relying on undocumented behaviour, and a read-only | |
| # scope is the cheapest possible way to stop doing so. | |
| actions: read | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - id: deployment | |
| uses: actions/deploy-pages@v5 |