website: vercel project config #3
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
| # Verifies the FNSTools site builds, and that the generated output committed | |
| # to the repo actually matches its sources. | |
| # | |
| # website/docs/ is committed on purpose -- Vercel serves it with no build | |
| # step -- which means it can go stale silently. Editing packaging/docs/*.md | |
| # and forgetting to rebuild would otherwise ship documentation that does not | |
| # match what the site shows. This job is what makes that impossible. | |
| # | |
| # The build itself also validates: a package with no docs, a docs file with | |
| # no catalog entry, a frontmatter/filename mismatch, or a link to a page or | |
| # heading that does not exist all fail the build rather than the deploy. | |
| name: website | |
| on: | |
| push: | |
| branches: ['**'] | |
| paths: | |
| - 'website/**' | |
| - 'packaging/docs/**' | |
| - 'packaging/catalog.json' | |
| - '.github/workflows/website.yml' | |
| pull_request: | |
| paths: | |
| - 'website/**' | |
| - 'packaging/docs/**' | |
| - 'packaging/catalog.json' | |
| - '.github/workflows/website.yml' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: website | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| cache-dependency-path: website/package-lock.json | |
| - run: npm ci | |
| - name: Syntax-check the tooling | |
| run: node --check tools/build-site.mjs && node --check tools/cms.mjs | |
| - name: Build site and docs | |
| # Skipped release fetch keeps this reproducible: otherwise a release | |
| # published between the commit and this run would restamp index.html | |
| # and fail the drift check below for reasons nobody changed. | |
| env: | |
| FNSTOOLS_NO_RELEASE_FETCH: '1' | |
| run: npm run build | |
| - name: Committed output must match its sources | |
| # `git status --porcelain`, not `git diff`: diff only reports tracked | |
| # files, so a build that ADDS a file -- a new package page, or a | |
| # pagefind index under a new content hash -- would slip through. | |
| run: | | |
| drift=$(git status --porcelain -- docs index.html) | |
| if [ -n "$drift" ]; then | |
| echo "::error::website/docs/ or index.html is stale. Run 'npm run build' in website/ and commit the result." | |
| { | |
| echo "### Generated output is out of date" | |
| echo '```' | |
| echo "$drift" | |
| echo '```' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| echo "generated output is current" | |
| - name: Report docs still needing prose | |
| if: always() | |
| run: | | |
| stubs=$(grep -rl 'TODO: no wiki content' ../packaging/docs || true) | |
| if [ -n "$stubs" ]; then | |
| { | |
| echo "### Packages still documented only by their catalog line" | |
| echo "$stubs" | sed 's|.*/|- |; s|\.md$||' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: Flag a published release newer than the one on the site | |
| if: always() | |
| continue-on-error: true | |
| run: | | |
| live=$(curl -sf --max-time 15 -A 'fnstools-ci' \ | |
| https://pub-8001b4bd92174be7a4544571b53f23da.r2.dev/fnstools/manifest.json \ | |
| | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>{try{console.log(JSON.parse(s).release||'')}catch{console.log('')}})") | |
| site=$(grep -o 'fnstools/v[^/]*/' index.html | head -1 | sed 's|fnstools/||; s|/$||') | |
| if [ -n "$live" ] && [ -n "$site" ] && [ "$live" != "$site" ]; then | |
| echo "::notice::Site advertises $site but $live is published. Re-run 'npm run build' to restamp the download links." | |
| echo "### Download links point at $site; $live is published" >> "$GITHUB_STEP_SUMMARY" | |
| fi |