Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 110 additions & 8 deletions .github/workflows/claude-documentation-fixer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,135 @@ jobs:
github.event.issue.pull_request &&
contains(github.event.comment.body, '@claude')
permissions:
contents: write
contents: read
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- name: Get PR branch
- name: Get PR info
id: pr-info
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_DATA=$(gh pr view ${{ github.event.issue.number }} --repo ${{ github.repository }} --json headRefName,headRefOid)
echo "branch=$(echo "$PR_DATA" | jq -r '.headRefName')" >> "$GITHUB_OUTPUT"
PR_DATA=$(gh pr view ${{ github.event.issue.number }} --repo ${{ github.repository }} --json headRefOid)
echo "sha=$(echo "$PR_DATA" | jq -r '.headRefOid')" >> "$GITHUB_OUTPUT"

- name: Checkout repository
uses: actions/checkout@v4
with:
# Check out the branch by name so git push works.
ref: ${{ steps.pr-info.outputs.branch }}
fetch-depth: 0

- name: Apply fixes
- name: Fetch PR head
run: |
git fetch origin pull/${{ github.event.issue.number }}/head:pr-fix-branch
git checkout pr-fix-branch

- name: Generate fixes
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
show_full_output: true
prompt: |
${{ github.event.comment.body }}

Apply the requested fixes to the documentation files. Edit files directly using the Write and Edit tools.
Do NOT run git commit, git push, or git add. Only edit the files.
claude_args: |
--model claude-sonnet-4-5-20250929
--allowedTools "Read,Write,Edit,Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*),Bash(git config:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git status:*),Bash(git diff:*)"
--allowedTools "Read,Write,Edit,Bash(gh pr view:*),Bash(gh pr diff:*),Bash(git status:*),Bash(git diff:*)"

- name: Post inline suggestions
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.issue.number }}
HEAD_SHA: ${{ steps.pr-info.outputs.sha }}
REPO: ${{ github.repository }}
run: |
python3 << 'PYEOF'
import subprocess, json, os, re, sys

def parse_diff(diff_text):
suggestions = []
current_file = None
lines = diff_text.split('\n')
i = 0
while i < len(lines):
line = lines[i]
if line.startswith('diff --git'):
i += 1
continue
elif line.startswith('--- a/'):
current_file = line[6:]
i += 1
continue
elif line.startswith('+++ b/'):
i += 1
continue
elif line.startswith('@@ '):
m = re.match(r'@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@', line)
if not m:
i += 1
continue
old_line = int(m.group(1))
i += 1
while i < len(lines) and not lines[i].startswith('@@') and not lines[i].startswith('diff '):
if lines[i].startswith('-') or lines[i].startswith('+'):
removed, added = [], []
start = old_line
while i < len(lines) and (lines[i].startswith('-') or lines[i].startswith('+')):
if lines[i].startswith('-'):
removed.append(lines[i][1:])
old_line += 1
else:
added.append(lines[i][1:])
i += 1
if removed:
suggestions.append({'file': current_file, 'start': start, 'end': old_line - 1, 'new': added})
elif lines[i].startswith(' '):
old_line += 1
i += 1
else:
i += 1
else:
i += 1
return suggestions

diff = subprocess.run(['git', 'diff'], capture_output=True, text=True).stdout
if not diff.strip():
print("No changes to suggest")
sys.exit(0)

suggestions = parse_diff(diff)
if not suggestions:
print("No line-replacement suggestions to post")
sys.exit(0)

comments = []
for s in suggestions:
body = '```suggestion\n' + '\n'.join(s['new']) + '\n```'
c = {'path': s['file'], 'line': s['end'], 'side': 'RIGHT', 'body': body}
if s['start'] != s['end']:
c['start_line'] = s['start']
c['start_side'] = 'RIGHT'
comments.append(c)

review_data = {
'commit_id': os.environ['HEAD_SHA'],
'body': f"Here are the suggested fixes ({len(comments)} suggestion(s)). Click 'Apply suggestion' on each one to accept it.",
'event': 'COMMENT',
'comments': comments
}

r = subprocess.run(
['gh', 'api', f"repos/{os.environ['REPO']}/pulls/{os.environ['PR_NUMBER']}/reviews",
'--method', 'POST', '--input', '-'],
input=json.dumps(review_data).encode(),
capture_output=True
)
if r.returncode != 0:
print(f"Error posting suggestions: {r.stderr.decode()}")
sys.exit(1)
print(f"Posted {len(comments)} inline suggestion(s)")
PYEOF
2 changes: 1 addition & 1 deletion .github/workflows/claude-documentation-reviewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ jobs:
run: |
echo "" >> /tmp/review.md
echo "To apply fixes, reply with \`@claude\` followed by your instructions (e.g. \`@claude fix all issues\` or \`@claude fix only the spelling errors\`)." >> /tmp/review.md
echo "Note: automated fixes are only available for branches in this repository, not forks." >> /tmp/review.md
echo "Note: fixes are posted as inline suggestions. Click 'Apply suggestion' on each one to accept it." >> /tmp/review.md
gh pr comment ${{ github.event.pull_request.number }} --body-file /tmp/review.md
Loading