From 0286d51f262ad135de32c84cc011ba5965912170 Mon Sep 17 00:00:00 2001 From: Max Isbey <224885523+maxisbey@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:26:07 +0000 Subject: [PATCH] ci: pick the docs-preview toolchain from the PR checkout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs-preview.yml runs on pull_request_target, so the workflow file always comes from the base branch while the code being built comes from the PR head. Hardcoding the build recipe here breaks previews for any head whose toolchain differs from the base — including the pending MkDocs-to-Zensical migration, whose preview can currently only go green after it merges. Detect the recipe from the checkout instead: heads that ship scripts/docs/build.sh (a complete recipe, dependency sync included) build with it; anything else keeps the current MkDocs path, dependency sync and all. Fail the artifact upload when the build arm writes nothing to site/ rather than surfacing as a download error in the deploy job. --- .github/workflows/docs-preview.yml | 39 +++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index bf10369cc9..6f9ec2cc34 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -1,13 +1,14 @@ name: Docs Preview -# Builds the mkdocs site for a PR and deploys it to Cloudflare Pages. +# Builds the docs site for a PR and deploys it to Cloudflare Pages. # -# Security: mkdocs executes Python from the PR (mkdocstrings imports src/mcp, -# `!!python/name:` directives). The build is gated by `authorize` (admin sender -# for auto-preview, admin/maintainer commenter for /preview-docs) and isolated -# from Cloudflare secrets — `build` runs PR code with no secrets and hands the -# static site to `deploy` via an artifact, so PR code never shares a runner -# with the Cloudflare token. +# Security: the build executes Python from the PR (mkdocstrings imports +# src/mcp, `!!python/name:` config directives run, and heads may ship their +# own build scripts). The build is gated by `authorize` (admin sender for +# auto-preview, admin/maintainer commenter for /preview-docs) and isolated +# from Cloudflare secrets — `build` runs PR code with no secrets and hands +# the static site to `deploy` via an artifact, so PR code never shares a +# runner with the Cloudflare token. # # Required configuration: # - secrets.CLOUDFLARE_API_TOKEN (scope: Account → Cloudflare Pages → Edit) @@ -21,6 +22,7 @@ on: - docs/** - docs_src/** - mkdocs.yml + - scripts/docs/** - pyproject.toml issue_comment: types: [created] @@ -128,17 +130,30 @@ jobs: enable-cache: false version: 0.9.5 - - run: uv sync --frozen --group docs - - run: uv run --frozen --no-sync mkdocs build - env: - # Silence mkdocs-material's MkDocs 2.0 warning banner in CI logs. - NO_MKDOCS_2_WARNING: "1" + # pull_request_target runs this workflow file from the base branch, so + # the whole recipe — dependency sync included — must come from the + # checkout itself: heads that ship scripts/docs/build.sh (the Zensical + # toolchain) build with it; older heads, and v1.x heads previewed via + # /preview-docs, still build with MkDocs. Both arms must write the site + # to site/. Keep the detection in sync with build_site() in + # scripts/build-docs.sh. + - run: | + if [ -f scripts/docs/build.sh ]; then + bash scripts/docs/build.sh + else + uv sync --frozen --group docs + # The env var silences mkdocs-material's MkDocs 2.0 warning banner. + NO_MKDOCS_2_WARNING=1 uv run --frozen --no-sync mkdocs build + fi - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: site path: site/ retention-days: 1 + # An empty site/ means the build arm broke its output contract; fail + # here instead of surfacing as a confusing download error in deploy. + if-no-files-found: error deploy: needs: [authorize, build]