|
| 1 | +name: Documentation Sync with Claude Code |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request: |
| 5 | + types: [opened, synchronize, edited] |
| 6 | + |
| 7 | +jobs: |
| 8 | + sync-docs: |
| 9 | + runs-on: ubuntu-latest |
| 10 | + if: "!startsWith(github.event.pull_request.title, 'Version Packages')" |
| 11 | + permissions: |
| 12 | + contents: write |
| 13 | + pull-requests: write |
| 14 | + id-token: write |
| 15 | + steps: |
| 16 | + - name: Generate GitHub App token |
| 17 | + id: generate-token |
| 18 | + uses: actions/create-github-app-token@v1 |
| 19 | + with: |
| 20 | + app-id: ${{ secrets.GH_APP_ID }} |
| 21 | + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} |
| 22 | + owner: cloudflare |
| 23 | + |
| 24 | + - name: Checkout source repository |
| 25 | + uses: actions/checkout@v4 |
| 26 | + with: |
| 27 | + fetch-depth: 0 |
| 28 | + ref: ${{ github.event.pull_request.head.sha }} |
| 29 | + |
| 30 | + - name: Get changed files |
| 31 | + id: changed-files |
| 32 | + run: | |
| 33 | + git fetch origin ${{ github.event.pull_request.base.ref }} |
| 34 | + CHANGED_FILES=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD | tr '\n' ',' | sed 's/,$//') |
| 35 | + echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT |
| 36 | + echo "Changed files: $CHANGED_FILES" |
| 37 | +
|
| 38 | + - name: Checkout cloudflare-docs repository |
| 39 | + uses: actions/checkout@v4 |
| 40 | + with: |
| 41 | + repository: cloudflare/cloudflare-docs |
| 42 | + token: ${{ steps.generate-token.outputs.token }} |
| 43 | + path: cloudflare-docs |
| 44 | + |
| 45 | + - name: Create branch in cloudflare-docs |
| 46 | + run: | |
| 47 | + cd cloudflare-docs |
| 48 | + git config user.name "github-actions[bot]" |
| 49 | + git config user.email "github-actions[bot]@users.noreply.github.com" |
| 50 | + git checkout -b sync-docs-pr-${{ github.event.pull_request.number }} |
| 51 | +
|
| 52 | + - name: Create prompt for Claude Code |
| 53 | + id: create-prompt |
| 54 | + run: | |
| 55 | + # Store PR metadata in environment variables to avoid shell escaping issues |
| 56 | + PR_NUMBER="${{ github.event.pull_request.number }}" |
| 57 | + PR_TITLE="${{ github.event.pull_request.title }}" |
| 58 | + PR_URL="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}" |
| 59 | +
|
| 60 | + cat > /tmp/claude_prompt.md << EOF |
| 61 | + # Intelligent Documentation Sync Task |
| 62 | +
|
| 63 | + ## Context |
| 64 | + - **Source Repository:** ${{ github.repository }} |
| 65 | + - **Original PR Number:** ${PR_NUMBER} |
| 66 | + - **Original PR Title:** ${PR_TITLE} |
| 67 | + - **Original PR URL:** ${PR_URL} |
| 68 | + - **Changed Files:** ${{ steps.changed-files.outputs.changed_files }} |
| 69 | + - **PR Description:** |
| 70 | + ${{ github.event.pull_request.body }} |
| 71 | +
|
| 72 | + ⚠️ **IMPORTANT**: All PR metadata above is the ONLY source of truth. Use these values EXACTLY as written. |
| 73 | + DO NOT fetch PR title/URL from GitHub APIs. |
| 74 | +
|
| 75 | + ## Your Task: Evaluate and Act |
| 76 | +
|
| 77 | + **First, gather the information you need:** |
| 78 | + 1. Review the list of changed files above |
| 79 | + 2. Use \`gh pr diff ${PR_NUMBER}\` to see the full diff for this PR |
| 80 | + 3. Use the Read tool to examine specific files if needed |
| 81 | +
|
| 82 | + You have access to two repositories: |
| 83 | + 1. The current directory (our main repo at ${{ github.repository }}) |
| 84 | + 2. ./cloudflare-docs (already cloned with branch sync-docs-pr-${{ github.event.pull_request.number }} checked out) |
| 85 | +
|
| 86 | + **Step 1: Evaluate if Documentation Sync is Needed** |
| 87 | +
|
| 88 | + Review the changes and determine if they require documentation updates in cloudflare-docs: |
| 89 | +
|
| 90 | + - **ALWAYS sync if ANY of these are true:** |
| 91 | + - Documentation files in docs/ were directly changed (even if other non-doc files also changed) |
| 92 | + - New public API features or functions were added |
| 93 | + - Breaking changes that affect user-facing behavior |
| 94 | + - New configuration options or environment variables |
| 95 | + - New examples or usage patterns that should be documented |
| 96 | + - Bug fixes that clarify documented behavior |
| 97 | +
|
| 98 | + - **DO NOT sync ONLY if ALL changes are:** |
| 99 | + - Only internal code refactoring with no behavior changes |
| 100 | + - Test-only changes |
| 101 | + - CI/workflow changes (UNLESS docs/ files also changed) |
| 102 | + - Minor typo fixes in code comments |
| 103 | + - Internal dependency updates with no API changes |
| 104 | +
|
| 105 | + **IMPORTANT**: If this PR includes ANY changes to files in the docs/ directory, you MUST proceed with the sync, even if the PR also includes other types of changes like workflow updates. |
| 106 | +
|
| 107 | + **Step 2: If Documentation Sync is Needed** |
| 108 | +
|
| 109 | + If you determine documentation updates are required, YOU MUST COMPLETE ALL STEPS: |
| 110 | +
|
| 111 | + 1. Navigate to ./cloudflare-docs (already cloned, branch sync-docs-pr-${PR_NUMBER} checked out) |
| 112 | + 2. Adapt changes for cloudflare-docs repository structure and style |
| 113 | + 3. Create or update the appropriate markdown files |
| 114 | + 4. Ensure content follows cloudflare-docs conventions |
| 115 | +
|
| 116 | + 5. **CRITICAL - Commit changes:** |
| 117 | + Run exactly: `cd cloudflare-docs && git add . && git commit -m "Sync docs from cloudflare/sandbox-sdk#${PR_NUMBER}: ${PR_TITLE}"` |
| 118 | +
|
| 119 | + 6. **CRITICAL - Push to remote:** |
| 120 | + Run exactly: `cd cloudflare-docs && git push origin sync-docs-pr-${PR_NUMBER}` |
| 121 | +
|
| 122 | + 7. **CRITICAL - Create or update PR in cloudflare-docs:** |
| 123 | + ⚠️ **CRITICAL**: Use the exact PR_NUMBER, PR_TITLE, and PR_URL values from the Context section above. |
| 124 | +
|
| 125 | + Copy and run this EXACT script (replace PLACEHOLDER values with actual values from Context): |
| 126 | + ```bash |
| 127 | + # Set variables from Context section above |
| 128 | + PR_NUMBER="PLACEHOLDER_PR_NUMBER" |
| 129 | + PR_TITLE="PLACEHOLDER_PR_TITLE" |
| 130 | + PR_URL="PLACEHOLDER_PR_URL" |
| 131 | +
|
| 132 | + # Check if PR already exists |
| 133 | + EXISTING_PR=$(gh pr list --repo cloudflare/cloudflare-docs --head sync-docs-pr-${PR_NUMBER} --json number --jq '.[0].number') |
| 134 | +
|
| 135 | + # Create PR title and body |
| 136 | + PR_TITLE_TEXT="📚 Sync docs from cloudflare/sandbox-sdk#${PR_NUMBER}: ${PR_TITLE}" |
| 137 | + PR_BODY_TEXT="Syncs documentation changes from [cloudflare/sandbox-sdk#${PR_NUMBER}](${PR_URL}): **${PR_TITLE}**" |
| 138 | +
|
| 139 | + if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then |
| 140 | + # Update existing PR |
| 141 | + echo "Updating existing PR #$EXISTING_PR" |
| 142 | + gh pr edit $EXISTING_PR --repo cloudflare/cloudflare-docs --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT" |
| 143 | + else |
| 144 | + # Create new PR |
| 145 | + echo "Creating new PR" |
| 146 | + gh pr create --repo cloudflare/cloudflare-docs --base main --head sync-docs-pr-${PR_NUMBER} --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT" |
| 147 | + fi |
| 148 | + ``` |
| 149 | +
|
| 150 | + ⚠️ THE TASK IS NOT COMPLETE UNTIL ALL 7 STEPS ARE DONE. Do not stop after editing files. |
| 151 | +
|
| 152 | + ## Documentation Writing Guidelines (Diátaxis Framework) |
| 153 | +
|
| 154 | + When writing the documentation content, adapt your approach based on what changed: |
| 155 | +
|
| 156 | + **For a single function/method:** |
| 157 | + - **Reference**: Technical description - signature, parameters, return types, behavior |
| 158 | + - **Example**: Concise code snippet showing usage in context |
| 159 | + - **Use cases**: Brief bullets on when/why to use it (if not obvious) |
| 160 | + - **DO NOT** create separate "how-to" sections - integrate examples into the reference |
| 161 | +
|
| 162 | + **For new features/workflows (multiple related functions):** |
| 163 | + - **Reference**: Complete API docs for all functions |
| 164 | + - **How-to guide**: Step-by-step guide for real-world tasks |
| 165 | + - **Explanation**: Architecture, design decisions, alternatives |
| 166 | +
|
| 167 | + **For breaking changes:** |
| 168 | + - **Reference**: Updated API documentation |
| 169 | + - **How-to**: Migration guide (before/after) |
| 170 | + - **Explanation**: Why changed, implications |
| 171 | +
|
| 172 | + **Key principles:** |
| 173 | + - Single functions = reference + example (concise) |
| 174 | + - Multi-step workflows = separate how-to guides |
| 175 | + - Keep reference neutral and factual |
| 176 | + - Don't overexplain simple functions |
| 177 | +
|
| 178 | + ## Cloudflare Docs Style Requirements |
| 179 | +
|
| 180 | + **CRITICAL**: Follow all rules from the [Cloudflare Style Guide](https://developers.cloudflare.com/style-guide/) and these specific requirements: |
| 181 | +
|
| 182 | + **Grammar & Formatting:** |
| 183 | + - Do not use contractions, exclamation marks, or non-standard quotes like \`''""\` |
| 184 | + - Fix common spelling errors, specifically misspellings of "wrangler" |
| 185 | + - Remove whitespace characters from the end of lines |
| 186 | + - Remove duplicate words |
| 187 | + - Do not use HTML for ordered lists |
| 188 | +
|
| 189 | + **Links:** |
| 190 | + - Use full relative links (\`/sandbox-sdk/configuration/\`) instead of full URLs, local dev links, or dot notation |
| 191 | + - Always use trailing slashes for links without anchors |
| 192 | + - Use meaningful link words (page titles) - avoid "here", "this page", "read more" |
| 193 | + - Add cross-links to relevant documentation pages where appropriate |
| 194 | +
|
| 195 | + **Components (MUST USE):** |
| 196 | + - All components need to be imported below frontmatter: \`import { ComponentName } from "~/components";\` |
| 197 | + - **WranglerConfig component**: Replace \`toml\` or \`json\` code blocks showing Wrangler configuration with the [\`WranglerConfig\` component](https://developers.cloudflare.com/style-guide/components/wrangler-config/). This is CRITICAL - always use this component for wrangler.toml/wrangler.jsonc examples. |
| 198 | + - **DashButton component**: Replace \`https://dash.cloudflare.com\` in steps with the [\`DashButton\` component](https://developers.cloudflare.com/style-guide/components/dash-button/) |
| 199 | + - **APIRequest component**: Replace \`sh\` code blocks with API requests to \`https://api.cloudflare.com\` with the [\`APIRequest\` component](https://developers.cloudflare.com/style-guide/components/api-request/) |
| 200 | + - **FileTree component**: Replace \`txt\` blocks showing file trees with the [\`FileTree\` component](https://developers.cloudflare.com/style-guide/components/file-tree/) |
| 201 | + - **PackageManagers component**: Replace \`sh\` blocks with npm commands using the [\`PackageManagers\` component](https://developers.cloudflare.com/style-guide/components/package-managers/) |
| 202 | + - **TypeScriptExample component**: Replace \`ts\`/\`typescript\` code blocks with the [\`TypeScriptExample\` component](https://developers.cloudflare.com/style-guide/components/typescript-example/) (except in step-by-step TypeScript-specific tutorials) |
| 203 | +
|
| 204 | + **JSX & Partials:** |
| 205 | + - When using JSX fragments for conditional rendering, use props variable to account for reusability |
| 206 | + - Only use \`<Markdown />\` component in JSX conditionals, and only if needed |
| 207 | + - Do not duplicate content in ternary/binary conditions |
| 208 | + - For variables in links, use HTML instead of Markdown |
| 209 | +
|
| 210 | + **Step 3: Provide Clear Output** |
| 211 | +
|
| 212 | + Clearly state your decision: |
| 213 | + - If syncing: Explain what documentation changes you're making and why |
| 214 | + - If not syncing: Explain why documentation updates aren't needed for this PR |
| 215 | +
|
| 216 | + ## Important Notes |
| 217 | + - Use the GH_TOKEN environment variable for authentication with gh CLI |
| 218 | + - Adapt paths, links, and references as needed for cloudflare-docs structure |
| 219 | + - Follow existing patterns in the cloudflare-docs repository |
| 220 | + - **DEFAULT TO SYNCING**: When in doubt about whether changes warrant a sync, ALWAYS create the sync PR for human review. It's better to create an unnecessary PR than to miss important documentation updates. |
| 221 | +
|
| 222 | + Begin your evaluation now. |
| 223 | + EOF |
| 224 | +
|
| 225 | + echo "prompt<<PROMPT_EOF" >> $GITHUB_OUTPUT |
| 226 | + cat /tmp/claude_prompt.md >> $GITHUB_OUTPUT |
| 227 | + echo "PROMPT_EOF" >> $GITHUB_OUTPUT |
| 228 | +
|
| 229 | + - name: Run Claude Code to create adapted PR |
| 230 | + uses: anthropics/claude-code-action@v1 |
| 231 | + with: |
| 232 | + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} |
| 233 | + github_token: ${{ steps.generate-token.outputs.token }} |
| 234 | + prompt: ${{ steps.create-prompt.outputs.prompt }} |
| 235 | + claude_args: '--allowed-tools "Read,Edit,Write,Bash"' |
| 236 | + env: |
| 237 | + GH_TOKEN: ${{ steps.generate-token.outputs.token }} |
0 commit comments