name: Deploy Docs
on:
push:
branches: [main]
paths:
- 'docs/**'
# The twoslash showcase gallery is rendered from these at docs-build time
# (docs/scripts/build-twoslash-showcase.sh), so a fixture/renderer change
# must redeploy the docs too.
- 'libs/twoslash/**'
- 'package.json'
- 'yarn.lock'
- '.yarnrc.yml'
# No `branches` filter: a stacked PR's base is a feature branch, and its
# preview matters as much as a PR against main. The deploy is a preview
# either way — `ci/deploy-cloudflare-pages.sh` keys it on the PR's head
# branch (`GITHUB_HEAD_REF`), never on the base — so only the push to main
# above is a production deploy.
pull_request:
paths:
- 'docs/**'
# The twoslash showcase gallery is rendered from these at docs-build time
# (docs/scripts/build-twoslash-showcase.sh), so a fixture/renderer change
# must redeploy the docs too.
- 'libs/twoslash/**'
- 'package.json'
- 'yarn.lock'
- '.yarnrc.yml'
workflow_dispatch:
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
env:
# Corepack asks before downloading the packageManager pin. CI must not.
COREPACK_ENABLE_DOWNLOAD_PROMPT: '0'
# yarn install + the wasm nix build + VitePress build + Cloudflare deploy run ~5m
# uncontended; runner contention during stacked-PR storms stretches the
# nix setup/teardown past 15m, cancelling after the deploy had succeeded.
timeout-minutes: 30
permissions:
contents: read
deployments: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v7
# `yarn docs:build` first runs `build:wasm`, which invokes
# `nix build .#table-wasm` to compile the drawTable playground module.
# Install Nix and wire up the binary cache so the ldc-wasm toolchain is
# pulled from the cache rather than built from source.
- name: Setup Nix
uses: ./.github/actions/setup-nix
with:
push-to-cache: true
cachix-cache: ${{ vars.CACHIX_CACHE }}
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
trusted-public-keys: ${{ vars.TRUSTED_PUBLIC_KEYS }}
substituters: ${{ vars.SUBSTITUTERS }}
use-nix-cache: true
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 24
# setup-node's `cache: yarn` calls `yarn --version` while the action
# runs, before Corepack has put Yarn on PATH. Enable Corepack first,
# then cache the folder Yarn itself reports.
- name: Enable Corepack
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: '0'
run: corepack enable
- name: Get Yarn cache directory
id: yarn-cache
run: echo "dir=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT"
- name: Cache Yarn
uses: actions/cache@v6
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: yarn-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
restore-keys: yarn-${{ runner.os }}-
- name: Install dependencies
run: yarn install --immutable
# The README badges read these from the deployed site. Regenerating them
# here rather than committing them keeps the number honest: it is
# computed from the same aggregate `ci --ci-stats --merges` prints, and a
# committed JSON would be stale from the merge after the one that wrote
# it. A failure here is not worth failing a docs deploy over -- the
# previously deployed badge simply stays up.
- name: Refresh the merge badges
continue-on-error: true
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
nix run .#ci-minimal -- --ci-stats --merges \
--repo "$GITHUB_REPOSITORY" --limit 1000 \
--badge-dir docs/public/badges
# Same headroom as the CI job's build — see the note there.
- name: Build VitePress site
env:
NODE_OPTIONS: --max-old-space-size=8192
run: yarn docs:build
# Shared with CircleCI — see ci/README.md. The script wraps the same two
# calls `cloudflare/wrangler-action` and `actions/github-script` made:
# `wrangler pages deploy`, then a marker-keyed upsert of the preview
# comment (so a re-run edits its own comment rather than appending).
- name: Deploy to Cloudflare Pages & comment the preview URL
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
GITHUB_TOKEN: ${{ github.token }}
run: ci/deploy-cloudflare-pages.sh