MCP client refactor - storage adapter #103
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Documentation Sync with Claude Code | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, edited] | |
| jobs: | |
| sync-docs: | |
| runs-on: ubuntu-latest | |
| if: "!startsWith(github.event.pull_request.title, 'Version Packages')" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| id-token: write | |
| steps: | |
| - name: Checkout source repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Get changed files | |
| id: changed-files | |
| run: | | |
| git fetch origin ${{ github.event.pull_request.base.ref }} | |
| git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD > changed_files.txt | |
| echo "Changed files:" | |
| cat changed_files.txt | |
| grep '^docs/.*\.md$' changed_files.txt > docs_changed.txt || echo "No docs changed" | |
| - name: Get file contents and diffs | |
| id: get-diffs | |
| run: | | |
| mkdir -p /tmp/diffs | |
| touch /tmp/diffs/changes.txt | |
| # Capture all changed files and their diffs | |
| while IFS= read -r file; do | |
| echo "=== $file ===" >> /tmp/diffs/changes.txt | |
| git diff origin/${{ github.event.pull_request.base.ref }}...HEAD -- "$file" >> /tmp/diffs/changes.txt | |
| echo -e "\n\n" >> /tmp/diffs/changes.txt | |
| done < changed_files.txt | |
| # Always run - let Claude decide if docs are needed | |
| echo "skip=false" >> $GITHUB_OUTPUT | |
| - name: Checkout cloudflare-docs repository | |
| if: steps.get-diffs.outputs.skip != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: cloudflare/cloudflare-docs | |
| token: ${{ secrets.AGENTS_GITHUB_TOKEN }} | |
| path: cloudflare-docs | |
| - name: Create branch in cloudflare-docs | |
| if: steps.get-diffs.outputs.skip != 'true' | |
| run: | | |
| cd cloudflare-docs | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git checkout -b sync-docs-pr-${{ github.event.pull_request.number }} | |
| - name: Create prompt for Claude Code | |
| if: steps.get-diffs.outputs.skip != 'true' | |
| id: create-prompt | |
| run: | | |
| # Store PR metadata in environment variables to avoid shell escaping issues | |
| PR_NUMBER="${{ github.event.pull_request.number }}" | |
| PR_TITLE="${{ github.event.pull_request.title }}" | |
| PR_URL="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}" | |
| cat > /tmp/claude_prompt.md << EOF | |
| # Intelligent Documentation Sync Task | |
| ⚠️ **CRITICAL INSTRUCTION**: All PR metadata is provided in the Context section below. | |
| DO NOT run \`gh pr view\`, \`gh api\`, or any other command to fetch PR information from GitHub. | |
| The PR number, title, and URL below are the ONLY source of truth. Use them EXACTLY as written. | |
| ## Context | |
| - **Source Repository:** ${{ github.repository }} | |
| - **Original PR Number:** ${PR_NUMBER} | |
| - **Original PR Title:** ${PR_TITLE} | |
| - **Original PR URL:** ${PR_URL} | |
| - **PR Description:** | |
| ${{ github.event.pull_request.body }} | |
| ## Changed Files and Diffs | |
| $(cat /tmp/diffs/changes.txt) | |
| ## Your Task: Evaluate and Act | |
| You have access to two repositories: | |
| 1. The current directory (our main repo at ${{ github.repository }}) | |
| 2. ./cloudflare-docs (already cloned with branch sync-docs-pr-${{ github.event.pull_request.number }} checked out) | |
| **Step 1: Evaluate if Documentation Sync is Needed** | |
| Please review the changes in this PR and determine if they require documentation updates in cloudflare-docs: | |
| - **ALWAYS sync if ANY of these are true:** | |
| - Documentation files in docs/ were directly changed (even if other non-doc files also changed) | |
| - New public API features or functions were added | |
| - Breaking changes that affect user-facing behavior | |
| - New configuration options or environment variables | |
| - New examples or usage patterns that should be documented | |
| - Bug fixes that clarify documented behavior | |
| - **DO NOT sync ONLY if ALL changes are:** | |
| - Only internal code refactoring with no behavior changes | |
| - Test-only changes | |
| - CI/workflow changes (UNLESS docs/ files also changed) | |
| - Minor typo fixes in code comments | |
| - Internal dependency updates with no API changes | |
| **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. | |
| **Step 2: If Documentation Sync is Needed** | |
| If you determine documentation updates are required, YOU MUST COMPLETE ALL STEPS: | |
| 1. Navigate to ./cloudflare-docs (already cloned, branch sync-docs-pr-${PR_NUMBER} checked out) | |
| 2. Adapt changes for cloudflare-docs repository structure and style | |
| 3. Create or update the appropriate markdown files | |
| 4. Ensure content follows cloudflare-docs conventions | |
| 5. **CRITICAL - Commit changes:** | |
| Run exactly: `cd cloudflare-docs && git add . && git commit -m "Sync docs from cloudflare/agents#${PR_NUMBER}: ${PR_TITLE}"` | |
| 6. **CRITICAL - Push to remote:** | |
| Run exactly: `cd cloudflare-docs && git push origin sync-docs-pr-${PR_NUMBER}` | |
| 7. **CRITICAL - Create or update PR in cloudflare-docs:** | |
| ⚠️ **CRITICAL**: | |
| - DO NOT fetch PR data from GitHub API to get title/description | |
| - DO NOT add your own description or summary | |
| - Use ONLY the PR_NUMBER, PR_TITLE, and PR_URL from the Context section above | |
| First check if PR already exists, then create or update: | |
| ```bash | |
| # Check if PR already exists | |
| EXISTING_PR=$(gh pr list --repo cloudflare/cloudflare-docs --head sync-docs-pr-${PR_NUMBER} --json number --jq '.[0].number') | |
| PR_TITLE_TEXT="📚 Sync docs from cloudflare/agents#${PR_NUMBER}: ${PR_TITLE}" | |
| PR_BODY_TEXT="Syncs documentation changes from [cloudflare/agents#${PR_NUMBER}](${PR_URL}): **${PR_TITLE}**" | |
| if [ -n "$EXISTING_PR" ]; then | |
| # Update existing PR | |
| echo "Updating existing PR #$EXISTING_PR" | |
| gh pr edit $EXISTING_PR --repo cloudflare/cloudflare-docs --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT" | |
| else | |
| # Create new PR | |
| echo "Creating new PR" | |
| gh pr create --repo cloudflare/cloudflare-docs --base main --head sync-docs-pr-${PR_NUMBER} --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT" | |
| fi | |
| ``` | |
| DO NOT modify the PR_TITLE_TEXT or PR_BODY_TEXT variables. | |
| 8. **CRITICAL - Comment on original PR:** | |
| ⚠️ **IMPORTANT**: Execute this ENTIRE script as ONE command. Do not split into multiple executions. | |
| Copy and run this complete bash script: | |
| ```bash | |
| #!/bin/bash | |
| set -e | |
| echo "=== Step 8: Managing PR comment ===" | |
| # Get the docs PR URL | |
| DOCS_PR_URL=$(gh pr list --repo cloudflare/cloudflare-docs --head sync-docs-pr-${PR_NUMBER} --json url --jq '.[0].url') | |
| echo "Docs PR URL: $DOCS_PR_URL" | |
| # Find existing comment with our unique marker | |
| EXISTING_COMMENT_ID=$(gh api "repos/cloudflare/agents/issues/${PR_NUMBER}/comments" \ | |
| --jq '.[] | select(.body | contains("<!-- DOCS-SYNC-AUTOMATION -->")) | .id' \ | |
| | head -n 1) | |
| # Prepare comment body (note the unique marker at the start) | |
| COMMENT_BODY=\$(printf '%s\n\n%s\n\n%s' \\ | |
| '<!-- DOCS-SYNC-AUTOMATION -->' \\ | |
| "📚 **Documentation sync PR:** \$DOCS_PR_URL" \\ | |
| '_This comment is automatically updated when the PR changes._') | |
| # Update existing or create new comment | |
| if [ -n "$EXISTING_COMMENT_ID" ] && [ "$EXISTING_COMMENT_ID" != "null" ]; then | |
| echo "Found existing comment ID: $EXISTING_COMMENT_ID - updating it" | |
| gh api --method PATCH \ | |
| "repos/cloudflare/agents/issues/comments/$EXISTING_COMMENT_ID" \ | |
| -f body="$COMMENT_BODY" | |
| echo "✅ Updated existing comment" | |
| else | |
| echo "No existing comment found - creating new one" | |
| gh pr comment ${PR_NUMBER} \ | |
| --repo cloudflare/agents \ | |
| --body "$COMMENT_BODY" | |
| echo "✅ Created new comment" | |
| fi | |
| # Cleanup any duplicate comments (keep only the newest) | |
| ALL_COMMENT_IDS=$(gh api "repos/cloudflare/agents/issues/${PR_NUMBER}/comments" \ | |
| --jq '.[] | select(.body | contains("<!-- DOCS-SYNC-AUTOMATION -->")) | .id') | |
| COMMENT_COUNT=$(echo "$ALL_COMMENT_IDS" | wc -l | tr -d ' ') | |
| if [ "$COMMENT_COUNT" -gt 1 ]; then | |
| echo "⚠️ Found $COMMENT_COUNT duplicate comments - cleaning up" | |
| # Keep the last one (newest), delete others | |
| echo "$ALL_COMMENT_IDS" | head -n -1 | while read -r OLD_ID; do | |
| if [ -n "$OLD_ID" ]; then | |
| echo "Deleting old comment ID: $OLD_ID" | |
| gh api --method DELETE "repos/cloudflare/agents/issues/comments/$OLD_ID" | |
| fi | |
| done | |
| echo "✅ Cleaned up duplicate comments" | |
| else | |
| echo "✅ Only one comment exists - no cleanup needed" | |
| fi | |
| echo "=== Step 8 complete ===" | |
| ``` | |
| ⚠️ THE TASK IS NOT COMPLETE UNTIL ALL 8 STEPS ARE DONE. Do not stop after editing files. | |
| ## Documentation Writing Guidelines (Diátaxis Framework) | |
| When writing the documentation content, adapt your approach based on what changed: | |
| **For a single function/method:** | |
| - **Reference**: Technical description - signature, parameters, return types, behavior | |
| - **Example**: Concise code snippet showing usage in context | |
| - **Use cases**: Brief bullets on when/why to use it (if not obvious) | |
| - **DO NOT** create separate "how-to" sections - integrate examples into the reference | |
| **For new features/workflows (multiple related functions):** | |
| - **Reference**: Complete API docs for all functions | |
| - **How-to guide**: Step-by-step guide for real-world tasks | |
| - **Explanation**: Architecture, design decisions, alternatives | |
| **For breaking changes:** | |
| - **Reference**: Updated API documentation | |
| - **How-to**: Migration guide (before/after) | |
| - **Explanation**: Why changed, implications | |
| **Key principles:** | |
| - Single functions = reference + example (concise) | |
| - Multi-step workflows = separate how-to guides | |
| - Keep reference neutral and factual | |
| - Don't overexplain simple functions | |
| ## Cloudflare Docs Style Requirements | |
| **CRITICAL**: Follow all rules from the [Cloudflare Style Guide](https://developers.cloudflare.com/style-guide/) and these specific requirements: | |
| **Grammar & Formatting:** | |
| - Do not use contractions, exclamation marks, or non-standard quotes like \`''""\` | |
| - Fix common spelling errors, specifically misspellings of "wrangler" | |
| - Remove whitespace characters from the end of lines | |
| - Remove duplicate words | |
| - Do not use HTML for ordered lists | |
| **Links:** | |
| - Use full relative links (\`/agents/configuration/\`) instead of full URLs, local dev links, or dot notation | |
| - Always use trailing slashes for links without anchors | |
| - Use meaningful link words (page titles) - avoid "here", "this page", "read more" | |
| - Add cross-links to relevant documentation pages where appropriate | |
| **Components (MUST USE):** | |
| - All components need to be imported below frontmatter: \`import { ComponentName } from "~/components";\` | |
| - **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. | |
| - **DashButton component**: Replace \`https://dash.cloudflare.com\` in steps with the [\`DashButton\` component](https://developers.cloudflare.com/style-guide/components/dash-button/) | |
| - **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/) | |
| - **FileTree component**: Replace \`txt\` blocks showing file trees with the [\`FileTree\` component](https://developers.cloudflare.com/style-guide/components/file-tree/) | |
| - **PackageManagers component**: Replace \`sh\` blocks with npm commands using the [\`PackageManagers\` component](https://developers.cloudflare.com/style-guide/components/package-managers/) | |
| - **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) | |
| **JSX & Partials:** | |
| - When using JSX fragments for conditional rendering, use props variable to account for reusability | |
| - Only use \`<Markdown />\` component in JSX conditionals, and only if needed | |
| - Do not duplicate content in ternary/binary conditions | |
| - For variables in links, use HTML instead of Markdown | |
| **Step 3: Provide Clear Output** | |
| Clearly state your decision: | |
| - If syncing: Explain what documentation changes you're making and why | |
| - If not syncing: Explain why documentation updates aren't needed for this PR | |
| ## Important Notes | |
| - Use the GH_TOKEN environment variable for authentication with gh CLI | |
| - Adapt paths, links, and references as needed for cloudflare-docs structure | |
| - Follow existing patterns in the cloudflare-docs repository | |
| - **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. | |
| Begin your evaluation now. | |
| EOF | |
| echo "prompt<<PROMPT_EOF" >> $GITHUB_OUTPUT | |
| cat /tmp/claude_prompt.md >> $GITHUB_OUTPUT | |
| echo "PROMPT_EOF" >> $GITHUB_OUTPUT | |
| - name: Run Claude Code to create adapted PR | |
| if: steps.get-diffs.outputs.skip != 'true' | |
| uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| prompt: ${{ steps.create-prompt.outputs.prompt }} | |
| claude_args: "--allowed-tools Bash,Edit,Write" | |
| env: | |
| GH_TOKEN: ${{ secrets.AGENTS_GITHUB_TOKEN }} |