diff --git a/.github/workflows/docs-deploy.yaml b/.github/workflows/docs-deploy.yaml index 842dcc73..82792a34 100644 --- a/.github/workflows/docs-deploy.yaml +++ b/.github/workflows/docs-deploy.yaml @@ -1,19 +1,15 @@ name: Deploy docs -# Publishes the Starlight docs site to GitHub Pages on every push to main that -# touches the docs source or this workflow. Pull requests build the site without -# deploying, so broken docs are caught before they merge. +# Builds and deploys the Starlight docs site to GitHub Pages on every push to +# main that touches the docs source or this workflow. PR-time build validation +# lives in the PR Validation workflow's gate, so a broken docs build blocks the +# merge there; this workflow only builds and deploys on push to main. on: push: branches: [main] paths: - 'docs/**' - '.github/workflows/docs-deploy.yaml' - pull_request: - branches: [main] - paths: - - 'docs/**' - - '.github/workflows/docs-deploy.yaml' # Least-privilege: read the repo, mint an OIDC token for Pages, write the Pages # deployment. No other scopes. diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index adc86c5e..9a3e991e 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -4,7 +4,9 @@ # # This workflow triggers on every PR to main so the PR Gate job always # reports a status. The expensive jobs (Unit Tests, Lint) are gated on a -# path filter and skip when only docs / non-code files changed. The PR Gate +# path filter and skip when only docs / non-code files changed. The Docs +# Build job is gated on a docs path filter and builds the Astro docs site so +# a broken build blocks the merge; it skips when no docs changed. The PR Gate # job aggregates their results and is the single check to require in branch # protection: it passes when each gated job succeeds or is skipped, and # fails when any gated job fails or is cancelled. @@ -26,6 +28,7 @@ jobs: pull-requests: read outputs: code: ${{ steps.filter.outputs.code }} + docs: ${{ steps.filter.outputs.docs }} steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -42,6 +45,8 @@ jobs: - '!.gitattributes' - '!.github/ISSUE_TEMPLATE/**' - '!.github/PULL_REQUEST_TEMPLATE.md' + docs: + - 'docs/**' unit-tests: name: Unit Tests @@ -187,9 +192,31 @@ jobs: fi exit "$CODE" + docs-build: + name: Docs Build + needs: changes + if: needs.changes.outputs.docs == 'true' + runs-on: ubuntu-latest + permissions: + contents: read + defaults: + run: + working-directory: docs + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + cache: npm + cache-dependency-path: docs/package-lock.json + - name: Install dependencies + run: npm ci + - name: Build site + run: npm run build + pr-gate: name: PR Gate - needs: [unit-tests, lint, workflow-drift] + needs: [unit-tests, lint, workflow-drift, docs-build] if: ${{ always() }} runs-on: ubuntu-latest steps: @@ -200,9 +227,11 @@ jobs: echo " unit-tests: ${{ needs.unit-tests.result }}" echo " lint: ${{ needs.lint.result }}" echo " workflow-drift: ${{ needs.workflow-drift.result }}" + echo " docs-build: ${{ needs.docs-build.result }}" exit 1 fi echo "PR Gate passed (jobs succeeded or were skipped)." echo " unit-tests: ${{ needs.unit-tests.result }}" echo " lint: ${{ needs.lint.result }}" echo " workflow-drift: ${{ needs.workflow-drift.result }}" + echo " docs-build: ${{ needs.docs-build.result }}"