From fb1b520360b6ec2e192757194237771d36c3e5d5 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 18 May 2026 19:38:00 +0200 Subject: [PATCH] ci(documentation): run build/validate on PRs, deploy only on push Split the single deploy job into two: - build: runs on every event (push, schedule, workflow_dispatch, pull_request). Checks out, installs, runs `npm run ci` (which builds and runs each site's postbuild AI-baseline validator from @conduction/docusaurus-preset). Uploads the build/ tree as an artifact on the events that go on to deploy. - deploy: runs only on push / schedule / workflow_dispatch. Downloads the artifact, adds .nojekyll + CNAME, pushes to gh-pages. Why - Sites that ship the AI-baseline gate (robots.txt, llms.txt, sitemaps, JSON-LD, FAQPage, og:image) get PR-time enforcement fleet-wide without each repo needing its own workflow file. Today, the shared workflow's `if: push || schedule || dispatch` guard means a PR can drop schemas, break a sitemap, or remove robots.txt without CI ever firing the validator. The bad code lands, the nightly cron catches it the next morning, production is already broken. This shifts detection left. - Separating build from deploy also de-risks the deploy itself: if the build succeeds but a deploy step fails for a transient reason, we can re-run just the deploy job without rebuilding. Compatibility - No input contract changes. Sites that already call this workflow with `cname: ...; source-folder: ...` keep working. - PRs that previously got no CI signal at all now get a green check (or a red one) from the new `build` job. - Sites without a postbuild validator (most of the fleet today) see the build job run a vanilla `npm run ci` and pass; the gate only fires for sites that have wired it. --- .github/workflows/documentation.yml | 53 +++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index ca1509e7..0a3ea1c4 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -18,16 +18,22 @@ on: type: string default: "20" +# Two jobs so the AI-baseline validation gate runs on every event, +# including pull_request, while the actual gh-pages deploy stays +# gated to push / schedule / workflow_dispatch. Sites that ship the +# postbuild validator from @conduction/docusaurus-preset (robots.txt, +# llms.txt, sitemaps, JSON-LD, FAQPage, og:image, etc.) get PR-time +# enforcement of the contract automatically. + jobs: - deploy: - name: Deploy Documentation + build: + name: Build and validate runs-on: ubuntu-latest - # Deploy on direct pushes, scheduled rebuilds (cron-driven data - # refresh on conduction-website), and manual workflow_dispatch. - # PR runs still build but don't deploy. - if: github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + timeout-minutes: 15 permissions: - contents: write + contents: read + outputs: + built: ${{ steps.flag.outputs.built }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -60,6 +66,39 @@ jobs: exit 1 fi + - name: Upload build artifact for deploy job + if: github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: docusaurus-build + path: ${{ inputs.source-folder }}/build + retention-days: 1 + + - id: flag + run: echo "built=true" >> "$GITHUB_OUTPUT" + + deploy: + name: Deploy Documentation + needs: build + runs-on: ubuntu-latest + # Deploy only on direct pushes, scheduled rebuilds, and manual + # workflow_dispatch. PR runs stop after the build job, so the + # AI-baseline gate runs but no gh-pages push happens. + if: github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download build artifact from build job + uses: actions/download-artifact@v4 + with: + name: docusaurus-build + path: ${{ inputs.source-folder }}/build + - name: Create .nojekyll and CNAME files run: | cd ${{ inputs.source-folder }}/build