@@ -2,7 +2,7 @@ name: Claude Code Review
22
33on :
44 pull_request_target :
5- types : [opened, synchronize, ready_for_review, reopened, labeled]
5+ types : [opened, ready_for_review, reopened, labeled]
66 issue_comment :
77 types : [created]
88
1515 github.event.action == 'opened' ||
1616 github.event.action == 'ready_for_review' ||
1717 github.event.action == 'reopened' ||
18- github.event.action == 'synchronize' ||
1918 (
2019 github.event.action == 'labeled' &&
2120 github.event.label.name == 'claude-full-review'
@@ -42,47 +41,42 @@ jobs:
4241 sudo apt-get update
4342 sudo apt-get install -y unzip jq
4443
45- - name : Checkout base repo
46- uses : actions/checkout@v4
47- with :
48- fetch-depth : 1
49-
50- - name : Determine PR number and requested review mode
44+ - name : Determine PR number
5145 id : mode
5246 shell : bash
47+ env :
48+ GH_TOKEN : ${{ github.token }}
5349 run : |
5450 set -euo pipefail
5551
5652 if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
5753 PR_NUMBER="${{ github.event.pull_request.number }}"
58- case "${{ github.event.action }}" in
59- opened|ready_for_review|reopened)
60- REQUESTED_MODE="full"
61- ;;
62- synchronize)
63- REQUESTED_MODE="incremental"
64- ;;
65- labeled)
66- if [[ "${{ github.event.label.name }}" == "claude-full-review" ]]; then
67- REQUESTED_MODE="full"
68- else
69- REQUESTED_MODE="full"
70- fi
71- ;;
72- *)
73- REQUESTED_MODE="full"
74- ;;
75- esac
7654 elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
7755 PR_NUMBER="${{ github.event.issue.number }}"
78- REQUESTED_MODE="full"
7956 else
8057 echo "Unsupported event"
8158 exit 1
8259 fi
8360
61+ PR_HEAD_REF="$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json headRefName --jq .headRefName)"
62+
8463 echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
85- echo "requested_mode=$REQUESTED_MODE" >> "$GITHUB_OUTPUT"
64+ echo "pr_head_ref=$PR_HEAD_REF" >> "$GITHUB_OUTPUT"
65+
66+ - name : Checkout base repo
67+ uses : actions/checkout@v4
68+ with :
69+ fetch-depth : 0
70+
71+ - name : Fetch PR head
72+ shell : bash
73+ env :
74+ PR_NUMBER : ${{ steps.mode.outputs.pr_number }}
75+ run : |
76+ set -euo pipefail
77+ # Fetch the PR merge ref — works for both same-repo and fork PRs
78+ # (fork branches don't exist on origin, but pull/<n>/head always does)
79+ git fetch origin "pull/${PR_NUMBER}/head"
8680
8781 - name : Resolve review state
8882 id : state
9488
9589 PR_NUMBER="${{ steps.mode.outputs.pr_number }}"
9690 REPO="${{ github.repository }}"
97- REQUESTED_MODE="${{ steps.mode.outputs.requested_mode }}"
9891
9992 mkdir -p .claude-review/context
10093
@@ -108,23 +101,13 @@ jobs:
108101 )"
109102
110103 EXISTING_COMMENT_ID=""
111- PREVIOUS_REVIEWED_SHA=""
112104
113105 if [[ -n "${LAST_COMMENT_B64:-}" ]]; then
114106 LAST_COMMENT_JSON="$(printf '%s' "$LAST_COMMENT_B64" | base64 -d)"
115107 EXISTING_COMMENT_ID="$(printf '%s' "$LAST_COMMENT_JSON" | jq -r '.id // empty')"
116- COMMENT_BODY="$(printf '%s' "$LAST_COMMENT_JSON" | jq -r '.body // empty')"
117- PREVIOUS_REVIEWED_SHA="$(printf '%s' "$COMMENT_BODY" | sed -n 's/.*reviewed_sha=\([0-9a-fA-F]\{7,\}\).*/\1/p' | tail -n1)"
118- fi
119-
120- EFFECTIVE_MODE="$REQUESTED_MODE"
121- if [[ "$REQUESTED_MODE" == "incremental" && -z "${PREVIOUS_REVIEWED_SHA:-}" ]]; then
122- EFFECTIVE_MODE="full"
123108 fi
124109
125110 echo "existing_comment_id=${EXISTING_COMMENT_ID:-}" >> "$GITHUB_OUTPUT"
126- echo "previous_reviewed_sha=${PREVIOUS_REVIEWED_SHA:-}" >> "$GITHUB_OUTPUT"
127- echo "effective_mode=$EFFECTIVE_MODE" >> "$GITHUB_OUTPUT"
128111
129112 - name : Build review diff and changed-file list
130113 id : review_input
@@ -136,43 +119,23 @@ jobs:
136119
137120 PR_NUMBER="${{ steps.mode.outputs.pr_number }}"
138121 REPO="${{ github.repository }}"
139- MODE="${{ steps.state.outputs.effective_mode }}"
140- CURRENT_SHA="${{ steps.state.outputs.current_head_sha }}"
141- PREV_SHA="${{ steps.state.outputs.previous_reviewed_sha }}"
142122
143123 mkdir -p .claude-review
144- : > .claude-review/review.diff
145- : > .claude-review/changed_files.txt
146124
147- build_full() {
148- gh pr diff "$PR_NUMBER" --repo "$REPO" > .claude-review/review.diff
149- gh pr view "$PR_NUMBER" --repo "$REPO" --json files --jq '.files[].path' > .claude-review/changed_files.txt
150- echo "actual_mode=full" >> "$GITHUB_OUTPUT"
151- }
125+ gh pr diff "$PR_NUMBER" --repo "$REPO" > .claude-review/review.diff.raw
126+ gh pr view "$PR_NUMBER" --repo "$REPO" --json files --jq '.files[].path' > .claude-review/changed_files.txt.raw
152127
153- if [[ "$MODE" == "full" ]]; then
154- build_full
155- else
156- if gh api -H "Accept: application/vnd.github.diff" \
157- "repos/$REPO/compare/$PREV_SHA...$CURRENT_SHA" > .claude-review/review.diff.tmp 2>/dev/null \
158- && gh api "repos/$REPO/compare/$PREV_SHA...$CURRENT_SHA" --jq '.files[].filename' > .claude-review/changed_files.txt.tmp 2>/dev/null; then
159- mv .claude-review/review.diff.tmp .claude-review/review.diff
160- mv .claude-review/changed_files.txt.tmp .claude-review/changed_files.txt
161- echo "actual_mode=incremental" >> "$GITHUB_OUTPUT"
162- else
163- echo "Compare diff failed; falling back to full review."
164- build_full
165- fi
166- fi
128+ # Filter out tests/ directory — golden files don't need code review
129+ grep -v '^tests/' .claude-review/changed_files.txt.raw > .claude-review/changed_files.txt || true
130+ # Strip diff hunks for tests/ files
131+ awk '
132+ /^diff --git a\/tests\// { skip=1; next }
133+ /^diff --git / { skip=0 }
134+ !skip { print }
135+ ' .claude-review/review.diff.raw > .claude-review/review.diff
167136
168137 sed -i '/^[[:space:]]*$/d' .claude-review/changed_files.txt || true
169138
170- if [[ ! -s .claude-review/review.diff ]] || [[ ! -s .claude-review/changed_files.txt ]]; then
171- echo "Prepared diff or changed file list is empty; falling back to full review."
172- build_full
173- sed -i '/^[[:space:]]*$/d' .claude-review/changed_files.txt || true
174- fi
175-
176139 echo "review_diff_path=.claude-review/review.diff" >> "$GITHUB_OUTPUT"
177140 echo "changed_files_path=.claude-review/changed_files.txt" >> "$GITHUB_OUTPUT"
178141
@@ -190,6 +153,10 @@ jobs:
190153
191154 mkdir -p .claude-review/context
192155
156+ # Prioritize src/ files for context (most likely to need review)
157+ sort -t/ -k1,1 -s < "${{ steps.review_input.outputs.changed_files_path }}" | \
158+ awk '/^src\//{print; next} {rest[NR]=$0} END{for(i in rest) print rest[i]}' > .claude-review/sorted_files.txt
159+
193160 while IFS= read -r path; do
194161 [[ -z "$path" ]] && continue
195162 COUNT=$((COUNT + 1))
@@ -206,10 +173,10 @@ jobs:
206173 [[ -z "$CONTENT" ]] && continue
207174
208175 LINE_COUNT="$(printf '%s' "$CONTENT" | wc -l | tr -d ' ')"
209- if [[ "$LINE_COUNT" -le 400 ]]; then
176+ if [[ "$LINE_COUNT" -le 1500 ]]; then
210177 printf '%s' "$CONTENT" > ".claude-review/context/$SAFE_NAME"
211178 fi
212- done < "${{ steps.review_input.outputs.changed_files_path }}"
179+ done < .claude-review/sorted_files.txt
213180
214181 echo "context_dir=.claude-review/context" >> "$GITHUB_OUTPUT"
215182
@@ -221,6 +188,7 @@ jobs:
221188 : > .claude-review/output.md
222189
223190 - name : Run Claude Code Review
191+ continue-on-error : true
224192 uses : anthropics/claude-code-action@v1
225193 with :
226194 claude_code_oauth_token : ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
@@ -229,16 +197,13 @@ jobs:
229197 plugins : " code-review@claude-code-plugins"
230198 claude_args : >
231199 --dangerously-skip-permissions
232- --max-turns 90
200+ --max-turns 40
233201 --allowedTools
234202 "Bash"
235203 prompt : |
236204 You are running in GitHub Actions review automation.
237205
238- REQUESTED REVIEW MODE: ${{ steps.state.outputs.effective_mode }}
239- ACTUAL REVIEW MODE: ${{ steps.review_input.outputs.actual_mode }}
240206 PR NUMBER: ${{ steps.mode.outputs.pr_number }}
241- PREVIOUS REVIEWED SHA: ${{ steps.state.outputs.previous_reviewed_sha }}
242207 CURRENT HEAD SHA: ${{ steps.state.outputs.current_head_sha }}
243208
244209 Review ONLY the prepared inputs for this run.
@@ -264,7 +229,7 @@ jobs:
264229 - Nearby unchanged lines in changed files may be used as supporting context only.
265230 - Do NOT raise findings about code outside changed files.
266231 - Do NOT provide general repo suggestions or unrelated improvement ideas.
267- - Do NOT include positive confirmations like "No issues with X".
232+ - Do NOT include positive confirmations like "No issues with X"
268233 - If confidence is low, omit the finding.
269234
270235 Allowed workflow:
@@ -278,23 +243,25 @@ jobs:
278243 8) Do NOT post, update, or create GitHub comments yourself
279244
280245 Review policy:
281- - In full mode, review the full PR diff.
282- - In incremental mode, review only the delta diff.
283- - In incremental mode, report only new issues introduced by that delta.
284- - Do NOT repeat earlier findings.
246+ - Review the full PR diff.
285247 - Do NOT restate the full PR summary.
286248 - If there are no high-confidence findings, leave .claude-review/output.md empty and STOP.
287249
288- Review standard:
289- - Prefer correctness, reliability, cleanup/finalization gaps, inconsistent behavior, edge cases, and meaningful test gaps.
250+ Review standard (in priority order per CLAUDE.md "Code Review Priorities"):
251+ 1. Correctness (logic bugs, numerical issues, array bounds)
252+ 2. Precision discipline (stp vs wp mixing)
253+ 3. Memory management (@:ALLOCATE/@:DEALLOCATE pairing, GPU pointer setup)
254+ 4. MPI correctness (halo exchange, buffer sizing, GPU_UPDATE calls)
255+ 5. GPU code (GPU_* Fypp macros only, no raw pragmas)
256+ 6. Physics consistency (pressure formula matches model_eqns)
257+ 7. Compiler portability (4 CI-gated compilers + AMD flang for GPU)
290258 - Avoid style nitpicks.
291259 - A finding is valid only if it is supported by changed lines, with changed-file context used only to confirm it.
292260
293261 Output rules:
294262 - Write markdown only to .claude-review/output.md
295- - If there are findings, use exactly one of these formats.
263+ - If there are findings, use exactly this format:
296264
297- For full mode:
298265 Claude Code Review
299266
300267 Head SHA: <sha>
@@ -308,17 +275,6 @@ jobs:
308275
309276 <!-- claude-review: thread=primary; reviewed_sha=<current_head_sha>; mode=full -->
310277
311- For incremental mode:
312- Claude Code Review
313-
314- Incremental review from: <previous_sha>
315- Head SHA: <current_sha>
316-
317- New findings since last Claude review:
318- - <only high-confidence issues grounded in changed hunks of the delta diff>
319-
320- <!-- claude-review: thread=primary; reviewed_sha=<current_head_sha>; mode=incremental -->
321-
322278 - Always include the hidden marker exactly once at the end of the file.
323279 - If there are no findings, write nothing.
324280
0 commit comments