Skip to content

doc review test 10

doc review test 10 #30

name: Documentation Fixer
on:
issue_comment:
types: [created]
jobs:
claude-response:
runs-on: ubuntu-latest
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '@claude') &&
github.event.comment.user.login != 'github-actions[bot]'
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- name: Get PR info
id: pr-info
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER="${{ github.event.issue.number }}"
PR_DATA=$(gh pr view $PR_NUMBER --repo ${{ github.repository }} --json headRefName,isCrossRepository)
echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
echo "branch=$(echo "$PR_DATA" | jq -r '.headRefName')" >> "$GITHUB_OUTPUT"
echo "is_fork=$(echo "$PR_DATA" | jq -r '.isCrossRepository')" >> "$GITHUB_OUTPUT"
- name: Post fork notice
if: steps.pr-info.outputs.is_fork == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr comment ${{ steps.pr-info.outputs.number }} --repo ${{ github.repository }} \
--body "This PR is from a fork. Automated fixes cannot be pushed directly. Apply the suggested changes from the inline comments manually."
- name: Checkout repository
if: steps.pr-info.outputs.is_fork == 'false'
uses: actions/checkout@v4
with:
ref: ${{ steps.pr-info.outputs.branch }}
fetch-depth: 0
- name: Checkout system prompt repository
if: steps.pr-info.outputs.is_fork == 'false'
uses: actions/checkout@v4
with:
repository: netwrix-eng/internal-agents
token: ${{ secrets.PRIVATE_AGENTS_REPO }}
path: system-prompt-repo
ref: builds
sparse-checkout: |
engineering/technical_writing/system-prompt.md
sparse-checkout-cone-mode: false
- name: Read system prompt
id: read-prompt
if: steps.pr-info.outputs.is_fork == 'false'
run: |
{
echo "prompt<<EOF"
cat system-prompt-repo/engineering/technical_writing/system-prompt.md
echo "" # Forces a newline to prevent EOF delimiter errors
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Detect command type
id: cmd-type
if: steps.pr-info.outputs.is_fork == 'false'
run: |
COMMENT="${{ github.event.comment.body }}"
if echo "$COMMENT" | grep -qi 'preexisting'; then
echo "is_preexisting=true" >> "$GITHUB_OUTPUT"
else
echo "is_preexisting=false" >> "$GITHUB_OUTPUT"
fi
- name: Install Vale
if: steps.pr-info.outputs.is_fork == 'false' && steps.cmd-type.outputs.is_preexisting == 'false'
run: |
VERSION=$(curl -s "https://api.github.com/repos/errata-ai/vale/releases/latest" | jq -r '.tag_name')
curl -sfL "https://github.com/errata-ai/vale/releases/download/${VERSION}/vale_${VERSION#v}_Linux_64-bit.tar.gz" \
| sudo tar -xz -C /usr/local/bin vale
- name: Apply fixes
if: steps.pr-info.outputs.is_fork == 'false' && steps.cmd-type.outputs.is_preexisting == 'false'
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
show_full_output: true
claude_args: |
--model claude-sonnet-4-5-20250929
--allowedTools "Read,Write,Edit,Bash(vale:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(git config:*),Bash(git add:*),Bash(git commit:*),Bash(git push:*),Bash(git status:*),Bash(git diff:*)"
--append-system-prompt "${{ steps.read-prompt.outputs.prompt }}"
- name: Record last comment ID
id: pre-claude
if: steps.pr-info.outputs.is_fork == 'false' && steps.cmd-type.outputs.is_preexisting == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
LAST_ID=$(gh api repos/${{ github.repository }}/issues/${{ steps.pr-info.outputs.number }}/comments \
--jq 'if length > 0 then .[-1].id else 0 end' 2>/dev/null || echo "0")
echo "last_comment_id=$LAST_ID" >> "$GITHUB_OUTPUT"
- name: Detect preexisting issues
if: steps.pr-info.outputs.is_fork == 'false' && steps.cmd-type.outputs.is_preexisting == 'true'
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
show_full_output: false
prompt: |
Detect preexisting issues in PR ${{ steps.pr-info.outputs.number }}.
Follow these steps in order:
1. Use `gh pr diff ${{ steps.pr-info.outputs.number }}` to identify which lines are part of the PR diff.
2. Use `gh pr view ${{ steps.pr-info.outputs.number }}` to get the list of changed files, then read the full content of each changed markdown file.
3. Run all three review passes on each file per your instructions, but report ONLY issues on lines that are NOT part of the PR diff.
4. You MUST write your results ONLY to `/tmp/preexisting-issues.md` — always, even if there are no issues. Do not post a comment. Do not write anything else. Use this exact format:
## Preexisting issues
### path/to/file.md
- Line N: issue. Suggested change: '...'
Or if there are no issues:
## Preexisting issues
None.
claude_args: |
--model claude-sonnet-4-5-20250929
--allowedTools "Read,Write,Edit,Bash(gh pr view:*),Bash(gh pr diff:*)"
--append-system-prompt "${{ steps.read-prompt.outputs.prompt }}"
- name: Post preexisting issues comment
if: steps.pr-info.outputs.is_fork == 'false' && steps.cmd-type.outputs.is_preexisting == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.pr-info.outputs.number }}
REPO: ${{ github.repository }}
LAST_COMMENT_ID: ${{ steps.pre-claude.outputs.last_comment_id }}
run: |
python3 << 'PYTHON_EOF'
import os
import json
import subprocess
pr_number = os.environ['PR_NUMBER']
repo = os.environ['REPO']
last_comment_id = int(os.environ.get('LAST_COMMENT_ID', '0'))
FOOTER = (
"\n\n---\n\n"
"To apply the suggested fixes to preexisting issues, comment `@claude` on this PR followed by your instructions\n"
"(`@claude fix all issues` or `@claude fix only the first issue`).\n"
"Note: Automated fixes are only available for branches in this repository, not forks."
)
def normalize_body(body):
"""Keep only the expected structured content from the preexisting issues output."""
idx = body.find('## Preexisting issues')
if idx == -1:
return '## Preexisting issues\nNone.'
body = body[idx:]
clean_lines = []
for line in body.split('\n'):
s = line.strip()
if (s == '## Preexisting issues' or
s.startswith('### ') or
s.startswith('- Line ') or
s == 'None.' or
s == ''):
clean_lines.append(line)
while clean_lines and not clean_lines[-1].strip():
clean_lines.pop()
return '\n'.join(clean_lines)
summary_path = '/tmp/preexisting-issues.md'
if os.path.exists(summary_path):
with open(summary_path) as f:
clean_body = normalize_body(f.read()) + FOOTER
else:
clean_body = '## Preexisting issues\nNone.' + FOOTER
# Find the action's auto-posted comment (ID > last recorded, posted by a bot)
result = subprocess.run(
['gh', 'api', f'repos/{repo}/issues/{pr_number}/comments'],
capture_output=True, text=True, check=True,
)
comments = json.loads(result.stdout)
new_bot_comments = [c for c in comments
if c['id'] > last_comment_id
and c['user']['login'].endswith('[bot]')]
if new_bot_comments:
# Replace the action's auto-comment in-place with our formatted output
target_id = new_bot_comments[-1]['id']
subprocess.run(
['gh', 'api', f'repos/{repo}/issues/comments/{target_id}',
'-X', 'PATCH', '--input', '-'],
input=json.dumps({'body': clean_body}),
capture_output=True, text=True, check=True,
)
else:
subprocess.run(
['gh', 'pr', 'comment', pr_number, '--repo', repo, '--body', clean_body],
check=True,
)
PYTHON_EOF