Skip to content

fix(core): validate CDN-supplied apiHost before building upload URL #3

fix(core): validate CDN-supplied apiHost before building upload URL

fix(core): validate CDN-supplied apiHost before building upload URL #3

name: Sync docs on merged PRs
# Runs after a PR merges into master and asks Claude to check whether any
# documentation (root README, package READMEs, /docs) needs updating to
# reflect the change, opening a follow-up PR only if it finds something to
# update.
#
# Gated to keep run volume (and cost) down: only master-targeted merges
# (branches: [master] below) that also carry an approving review
# (reviewDecision == APPROVED, checked in the gate step) trigger a Claude run.
# master requires 1 approval by branch protection, but enforce_admins is off,
# so an admin can still merge without one - this gate closes that gap rather
# than assuming protection alone guarantees a review happened.
#
# Uses pull_request_target (not pull_request) so the workflow runs with this
# repo's own permissions even when the merged PR came from a fork - this repo
# takes plenty of external contributions and a plain `pull_request` trigger
# gets a read-only token for fork-authored PRs, which would make `gh pr
# create` fail below. This is safe here because we only ever check out
# base.ref (the already-reviewed, already-merged default branch), never the
# PR's own head ref - we never build or execute the contributor's code.
#
# Installs the Claude Code CLI directly via npm rather than using
# `uses: anthropics/claude-code-action` - this repo's Actions policy is
# allowed_actions: selected with an empty patterns_allowed list (only
# GitHub-owned actions are permitted), so a third-party `uses:` reference
# fails at startup before any job runs. Installing and invoking the CLI
# ourselves only needs actions/checkout and actions/setup-node, both
# GitHub-owned and already allowed, so it sidesteps that policy without
# requiring an org/repo policy change.
on:
pull_request_target:
types: [closed]
branches: [master]
permissions:
contents: write
pull-requests: write
jobs:
doc-sync:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest-large
steps:
- name: Require an approved review
id: gate
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
decision=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json reviewDecision -q .reviewDecision)
echo "review decision for #$PR_NUMBER: ${decision:-<empty>}"
if [ "$decision" = "APPROVED" ]; then
echo "approved=true" >> "$GITHUB_OUTPUT"
else
echo "approved=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout base branch
if: steps.gate.outputs.approved == 'true'
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ github.event.pull_request.base.ref }}
fetch-depth: 0
- name: Setup Node
if: steps.gate.outputs.approved == 'true'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
- name: Install Claude Code CLI
if: steps.gate.outputs.approved == 'true'
run: npm install -g @anthropic-ai/claude-code
- name: Configure git identity for Claude's commits
if: steps.gate.outputs.approved == 'true'
run: |
git config --global user.email "claude-bot@users.noreply.github.com"
git config --global user.name "claude-bot"
- name: Write prompt
if: steps.gate.outputs.approved == 'true'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
cat > "$RUNNER_TEMP/claude-prompt.txt" <<EOF
Pull request #$PR_NUMBER ("$PR_TITLE") was just merged into $BASE_REF.
1. Run \`gh pr diff $PR_NUMBER\` to see exactly what changed.
2. Search this repository's documentation (root README.md, each package's README.md, and any /docs content) for anything describing the behavior, API, configuration, or usage that this PR changed.
3. If you find documentation that's now inaccurate, incomplete, or missing details because of this change, update it to match. Do not treat CHANGELOG.md files as documentation - they're generated by release tooling, leave them alone.
4. If no documentation needs updating, stop here: do not create a branch, commit, or pull request.
5. If you did update documentation, create a new branch off $BASE_REF named \`docs/sync-pr-$PR_NUMBER\`, commit the changes, push it, and open a pull request against $BASE_REF with \`gh pr create\`. Title it "docs: sync with #$PR_NUMBER" and explain in the body which doc(s) you updated, why, and link back to #$PR_NUMBER.
EOF
- name: Sync docs with Claude
if: steps.gate.outputs.approved == 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ github.token }}
run: |
claude -p "$(cat "$RUNNER_TEMP/claude-prompt.txt")" \
--allowedTools "Edit,MultiEdit,Write,Read,Glob,Grep,Bash(git:*),Bash(gh:*)"