Skip to content

Commit 30ad226

Browse files
authored
Merge pull request #297 from netwrix/dev
detects fork vs non-fork at the start
2 parents b9296b4 + f8fad6d commit 30ad226

1 file changed

Lines changed: 48 additions & 97 deletions

File tree

.github/workflows/claude-documentation-reviewer.yml

Lines changed: 48 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,30 @@ jobs:
1010
claude-response:
1111
runs-on: ubuntu-latest
1212
permissions:
13-
contents: read
13+
contents: write
1414
pull-requests: write
1515
issues: write
1616
id-token: write
1717
actions: read
1818
steps:
19-
- name: Checkout repository
19+
- name: Detect fork
20+
id: pr-info
21+
run: |
22+
if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
23+
echo "is_fork=true" >> "$GITHUB_OUTPUT"
24+
else
25+
echo "is_fork=false" >> "$GITHUB_OUTPUT"
26+
fi
27+
28+
- name: Checkout repository (non-fork)
29+
if: steps.pr-info.outputs.is_fork == 'false'
30+
uses: actions/checkout@v4
31+
with:
32+
ref: ${{ github.event.pull_request.head.ref }}
33+
fetch-depth: 0
34+
35+
- name: Checkout repository (fork)
36+
if: steps.pr-info.outputs.is_fork == 'true'
2037
uses: actions/checkout@v4
2138
with:
2239
# Check out by SHA to prevent TOCTOU attacks from forks.
@@ -74,8 +91,8 @@ jobs:
7491
echo "EOF"
7592
} >> "$GITHUB_OUTPUT"
7693
77-
- name: Run documentation review
78-
if: steps.changed-files.outputs.count > 0
94+
- name: Review and fix (non-fork)
95+
if: steps.changed-files.outputs.count > 0 && steps.pr-info.outputs.is_fork == 'false'
7996
uses: anthropics/claude-code-action@v1
8097
with:
8198
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -86,102 +103,36 @@ jobs:
86103
87104
Use `gh pr diff ${{ github.event.pull_request.number }}` to see the exact changes made.
88105
89-
Do not review or comment on any other files (e.g., .js, .ts, .json, etc.). Focus exclusively on the documentation changes in the markdown files listed above.
106+
Do not review or comment on any other files. Focus exclusively on the documentation changes in the markdown files listed above.
90107
91-
Write your findings to /tmp/suggestions.json following the format in your instructions.
108+
1. Fix all issues directly in the files using the Write and Edit tools.
109+
2. Commit and push the fixes using git.
110+
3. Post a PR comment starting with "## Documentation Review" that lists each issue that was fixed, following the format in your instructions.
92111
93112
claude_args: |
94113
--model claude-sonnet-4-5-20250929
95-
--allowedTools "Write,Bash(gh pr diff:*),Bash(gh pr view:*)"
114+
--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:*)"
96115
--append-system-prompt "${{ steps.read-prompt.outputs.prompt }}"
97116
98-
- name: Post inline suggestions
99-
if: steps.changed-files.outputs.count > 0
100-
env:
101-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102-
PR_NUMBER: ${{ github.event.pull_request.number }}
103-
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
104-
REPO: ${{ github.repository }}
105-
run: |
106-
python3 << 'PYEOF'
107-
import subprocess, json, os, sys
108-
109-
pr_number = os.environ['PR_NUMBER']
110-
head_sha = os.environ['HEAD_SHA']
111-
repo = os.environ['REPO']
112-
113-
try:
114-
with open('/tmp/suggestions.json') as f:
115-
data = json.load(f)
116-
except (FileNotFoundError, json.JSONDecodeError) as e:
117-
print(f"Could not read /tmp/suggestions.json: {e}")
118-
sys.exit(1)
119-
120-
# Handle case where Claude wraps the array in an object
121-
if isinstance(data, dict):
122-
for key in data:
123-
if isinstance(data[key], list):
124-
data = data[key]
125-
break
126-
else:
127-
print(f"Unexpected dict structure: {list(data.keys())}")
128-
sys.exit(1)
129-
130-
if not isinstance(data, list):
131-
print(f"Expected array, got {type(data)}")
132-
sys.exit(1)
133-
134-
suggestions = data
135-
136-
if not suggestions:
137-
subprocess.run(
138-
['gh', 'pr', 'comment', pr_number, '--repo', repo,
139-
'--body', 'No issues found in the changed files.'],
140-
check=True
141-
)
142-
print("No issues found")
143-
sys.exit(0)
144-
145-
comments = []
146-
for s in suggestions:
147-
if not isinstance(s, dict):
148-
print(f"Skipping non-object suggestion: {repr(s)[:100]}")
149-
continue
150-
# Accept alternate field names Claude may use
151-
path = s.get('path') or s.get('file')
152-
line = s.get('line') or s.get('line_number')
153-
body_text = s.get('body') or s.get('issue') or s.get('description') or ''
154-
suggestion_text = s.get('suggestion') or s.get('replacement') or s.get('fix') or ''
155-
start_line = s.get('start_line') or s.get('start') or line
156-
if not path or not line or not suggestion_text:
157-
print(f"Skipping incomplete suggestion: {repr(s)[:100]}")
158-
continue
159-
body = body_text + '\n```suggestion\n' + suggestion_text + '\n```'
160-
c = {'path': path, 'line': line, 'side': 'RIGHT', 'body': body}
161-
if start_line and start_line != line:
162-
c['start_line'] = start_line
163-
c['start_side'] = 'RIGHT'
164-
comments.append(c)
165-
166-
if not comments:
167-
print("No valid suggestions to post")
168-
sys.exit(1)
169-
170-
review_data = {
171-
'commit_id': head_sha,
172-
'body': f'Found {len(comments)} issue(s). To apply all fixes at once, reply with `@claude` followed by your instructions (e.g. `@claude fix all issues`).',
173-
'event': 'COMMENT',
174-
'comments': comments
175-
}
176-
177-
r = subprocess.run(
178-
['gh', 'api', f'repos/{repo}/pulls/{pr_number}/reviews',
179-
'--method', 'POST', '--input', '-'],
180-
input=json.dumps(review_data).encode(),
181-
capture_output=True
182-
)
183-
if r.returncode != 0:
184-
print(f"Error posting suggestions: {r.stderr.decode()}")
185-
sys.exit(1)
186-
print(f"Posted {len(comments)} inline suggestion(s)")
187-
PYEOF
117+
- name: Review only (fork)
118+
if: steps.changed-files.outputs.count > 0 && steps.pr-info.outputs.is_fork == 'true'
119+
uses: anthropics/claude-code-action@v1
120+
with:
121+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
122+
github_token: ${{ secrets.GITHUB_TOKEN }}
123+
show_full_output: true
124+
prompt: |
125+
Review ONLY the following markdown files that were changed in this PR: ${{ steps.changed-files.outputs.files }}
126+
127+
Use `gh pr diff ${{ github.event.pull_request.number }}` to see the exact changes made.
128+
129+
Do not review or comment on any other files. Focus exclusively on the documentation changes in the markdown files listed above.
130+
131+
Post a PR comment starting with "## Documentation Review" that lists all issues found, following the format in your instructions.
132+
133+
This PR is from a fork. Do not attempt to edit files or push changes. The author must address the issues manually.
134+
135+
claude_args: |
136+
--model claude-sonnet-4-5-20250929
137+
--allowedTools "Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr comment:*)"
138+
--append-system-prompt "${{ steps.read-prompt.outputs.prompt }}"

0 commit comments

Comments
 (0)