Skip to content

Docs Preview Deploy #2160

Docs Preview Deploy

Docs Preview Deploy #2160

name: Docs Preview Deploy
on:
workflow_run:
workflows: ["Docs Preview Build"]
types: [completed]
permissions:
actions: read
contents: read
pull-requests: read
jobs:
deploy:
name: Deploy Docs & Snippets
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
environment: docs-development
steps:
# Derive PR identity from the trusted workflow_run event, not from build-job artifacts.
- id: meta
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
REPO: ${{ github.repository }}
# A single SHA can belong to multiple PRs, so disambiguate by the trusted head branch instead of taking .[0].
#
# Read the (untrusted) branch via jq's env builtin so it is treated as data. Interpolating $HEAD_BRANCH into
# the jq program would let a branch name containing a double quote break out of the string literal and inject
# jq (e.g. forge pr_number, or read env via the env builtin).
run: |
echo "full_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
echo "sha=${HEAD_SHA:0:7}" >> "$GITHUB_OUTPUT"
ESCAPED="${HEAD_BRANCH//\//-}"
echo "branch=$ESCAPED" >> "$GITHUB_OUTPUT"
PR=$(gh api "repos/$REPO/commits/$HEAD_SHA/pulls" \
--jq 'first(.[] | select(.state == "open" and .head.ref == env.HEAD_BRANCH) | .number)')
echo "pr_number=$PR" >> "$GITHUB_OUTPUT"
# Deploy Snippets
- uses: actions/download-artifact@v8
with:
name: docs-snippets-build
path: ./docs-snippets--build
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- uses: cloudflare/wrangler-action@v4
id: publish-docs-snippets
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
command: >-
pages deploy ./docs-snippets--build
--project-name=${{ vars.CLOUDFLARE_SNIPPETS_PROJECT_NAME }}
--branch=${{ steps.meta.outputs.branch }}-${{ steps.meta.outputs.sha }}
# Deploy docs
- uses: actions/checkout@v6
with:
ref: main
sparse-checkout: |
docs/package.json
docs/pnpm-lock.yaml
docs/wrangler.jsonc
docs/open-next.config.ts
.github/deployment_preview_template.md
# The docs-build tarball is produced by the untrusted build job, so it can contain arbitrary files. Download it to
# an isolated path (NOT ./docs) and copy only the .open-next directory into place. Extracting it directly into
# ./docs would let it plant a malicious package.json / .pnpmfile.cjs / .npmrc beside the trusted files that the
# later `pnpm install` reads.
- uses: actions/download-artifact@v8
with:
name: docs-build
path: ./_artifact
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Extract docs build in isolation
run: |
mkdir _scratch
tar -xf ./_artifact/docs-build.tar -C _scratch
rm -rf ./docs/.open-next
cp -r _scratch/.open-next ./docs/.open-next
- uses: actions/setup-node@v6
with:
node-version: 24
- uses: pnpm/action-setup@v6
with:
version: 11
- name: Deploy docs to Cloudflare Workers
id: publish-docs
working-directory: ./docs
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
run: |
pnpm install
set +e
OUTPUT=$(pnpm exec opennextjs-cloudflare upload -- --env dev 2>&1)
EXIT_CODE=$?
echo "$OUTPUT"
PREVIEW_URL=$(echo "$OUTPUT" | grep "Version Preview URL:" | awk '{print $NF}')
echo "preview-url=$PREVIEW_URL" >> $GITHUB_OUTPUT
exit $EXIT_CODE
# Create/update comment with link to preview
- uses: actions/create-github-app-token@v3
id: generate-token
with:
app-id: ${{ secrets.AUTO_MAID_APP_ID }}
private-key: ${{ secrets.AUTO_MAID_PRIVATE_KEY }}
- uses: peter-evans/find-comment@v4
id: find-comment
with:
issue-number: ${{ steps.meta.outputs.pr_number }}
comment-author: 'auto-maid[bot]'
- uses: chuhlomin/render-template@v1.12
id: render-markdown
with:
template: .github/deployment_preview_template.md
vars: |
sha: ${{ steps.meta.outputs.full_sha }}
url: ${{ steps.publish-docs.outputs.preview-url }}
- uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.generate-token.outputs.token }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ steps.meta.outputs.pr_number }}
body: ${{ steps.render-markdown.outputs.result }}
edit-mode: replace
# Check that all relative URLs are working
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- run: go install github.com/raviqqe/muffet/v2@latest
- run: muffet ${{ steps.publish-docs.outputs.preview-url }} --buffer-size=32768 --exclude="(\/cdn-cgi\/)|(github.com)|(pub.dev)|(shadcn.com)"