Skip to content

Ib collisions

Ib collisions #1535

name: Claude Code Review
on:
pull_request_target:
types: [opened, ready_for_review, reopened, labeled]
issue_comment:
types: [created]
jobs:
claude-review:
if: >
(
github.event_name == 'pull_request_target' &&
(
github.event.action == 'opened' ||
github.event.action == 'ready_for_review' ||
github.event.action == 'reopened' ||
(
github.event.action == 'labeled' &&
github.event.label.name == 'claude-full-review'
)
)
) ||
(
github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
contains(github.event.comment.body, '@claude full review')
)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
actions: read
steps:
- name: Install dependencies
shell: bash
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y unzip jq
- name: Determine PR number
id: mode
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
PR_NUMBER="${{ github.event.pull_request.number }}"
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
PR_NUMBER="${{ github.event.issue.number }}"
else
echo "Unsupported event"
exit 1
fi
PR_HEAD_REF="$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json headRefName --jq .headRefName)"
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
echo "pr_head_ref=$PR_HEAD_REF" >> "$GITHUB_OUTPUT"
- name: Checkout base repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch PR head
shell: bash
env:
PR_NUMBER: ${{ steps.mode.outputs.pr_number }}
run: |
set -euo pipefail
# Fetch the PR merge ref — works for both same-repo and fork PRs
# (fork branches don't exist on origin, but pull/<n>/head always does)
git fetch origin "pull/${PR_NUMBER}/head"
- name: Resolve review state
id: state
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
PR_NUMBER="${{ steps.mode.outputs.pr_number }}"
REPO="${{ github.repository }}"
mkdir -p .claude-review/context
CURRENT_HEAD_SHA="$(gh pr view "$PR_NUMBER" --repo "$REPO" --json headRefOid --jq .headRefOid)"
echo "current_head_sha=$CURRENT_HEAD_SHA" >> "$GITHUB_OUTPUT"
LAST_COMMENT_B64="$(
gh api --paginate "repos/$REPO/issues/$PR_NUMBER/comments?per_page=100" \
--jq '.[] | select(.body | contains("<!-- claude-review: thread=primary;")) | @base64' \
| tail -n1 || true
)"
EXISTING_COMMENT_ID=""
if [[ -n "${LAST_COMMENT_B64:-}" ]]; then
LAST_COMMENT_JSON="$(printf '%s' "$LAST_COMMENT_B64" | base64 -d)"
EXISTING_COMMENT_ID="$(printf '%s' "$LAST_COMMENT_JSON" | jq -r '.id // empty')"
fi
echo "existing_comment_id=${EXISTING_COMMENT_ID:-}" >> "$GITHUB_OUTPUT"
- name: Build review diff and changed-file list
id: review_input
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
PR_NUMBER="${{ steps.mode.outputs.pr_number }}"
REPO="${{ github.repository }}"
mkdir -p .claude-review
gh pr diff "$PR_NUMBER" --repo "$REPO" > .claude-review/review.diff.raw
gh pr view "$PR_NUMBER" --repo "$REPO" --json files --jq '.files[].path' > .claude-review/changed_files.txt.raw
# Filter out tests/ directory — golden files don't need code review
grep -v '^tests/' .claude-review/changed_files.txt.raw > .claude-review/changed_files.txt || true
# Strip diff hunks for tests/ files
awk '
/^diff --git a\/tests\// { skip=1; next }
/^diff --git / { skip=0 }
!skip { print }
' .claude-review/review.diff.raw > .claude-review/review.diff
sed -i '/^[[:space:]]*$/d' .claude-review/changed_files.txt || true
echo "review_diff_path=.claude-review/review.diff" >> "$GITHUB_OUTPUT"
echo "changed_files_path=.claude-review/changed_files.txt" >> "$GITHUB_OUTPUT"
- name: Prefetch bounded context for changed files only
id: context
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
REPO="${{ github.repository }}"
HEAD_SHA="${{ steps.state.outputs.current_head_sha }}"
COUNT=0
mkdir -p .claude-review/context
# Prioritize src/ files for context (most likely to need review)
sort -t/ -k1,1 -s < "${{ steps.review_input.outputs.changed_files_path }}" | \
awk '/^src\//{print; next} {rest[NR]=$0} END{for(i in rest) print rest[i]}' > .claude-review/sorted_files.txt
while IFS= read -r path; do
[[ -z "$path" ]] && continue
COUNT=$((COUNT + 1))
[[ "$COUNT" -gt 10 ]] && break
SAFE_NAME="$(printf '%s' "$path" | tr '/ ' '__')"
RAW="$(gh api "repos/$REPO/contents/$path?ref=$HEAD_SHA" 2>/dev/null || true)"
[[ -z "$RAW" ]] && continue
ENCODING="$(printf '%s' "$RAW" | jq -r '.encoding // empty')"
[[ "$ENCODING" != "base64" ]] && continue
CONTENT="$(printf '%s' "$RAW" | jq -r '.content // empty' | tr -d '\n' | base64 -d 2>/dev/null || true)"
[[ -z "$CONTENT" ]] && continue
LINE_COUNT="$(printf '%s' "$CONTENT" | wc -l | tr -d ' ')"
if [[ "$LINE_COUNT" -le 1500 ]]; then
printf '%s' "$CONTENT" > ".claude-review/context/$SAFE_NAME"
fi
done < .claude-review/sorted_files.txt
echo "context_dir=.claude-review/context" >> "$GITHUB_OUTPUT"
- name: Initialize review output
shell: bash
run: |
set -euo pipefail
mkdir -p .claude-review
: > .claude-review/output.md
- name: Run Claude Code Review
continue-on-error: true
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ github.token }}
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
plugins: "code-review@claude-code-plugins"
claude_args: >
--dangerously-skip-permissions
--max-turns 40
--allowedTools
"Bash"
prompt: |
You are running in GitHub Actions review automation.
PR NUMBER: ${{ steps.mode.outputs.pr_number }}
CURRENT HEAD SHA: ${{ steps.state.outputs.current_head_sha }}
Review ONLY the prepared inputs for this run.
Prepared inputs:
- Diff to review: ${{ steps.review_input.outputs.review_diff_path }}
- Changed files list: ${{ steps.review_input.outputs.changed_files_path }}
- Optional full-file context for small changed files: ${{ steps.context.outputs.context_dir }}
Hard scope rules:
- Do NOT inspect checked-out repository code except:
- ./CLAUDE.md
- ./.claude/rules/*.md (max 10 files)
- ${{ steps.review_input.outputs.review_diff_path }}
- ${{ steps.review_input.outputs.changed_files_path }}
- files inside ${{ steps.context.outputs.context_dir }}
- Do NOT fetch or inspect any other repository files.
- Do NOT inspect unchanged files outside the reviewed diff.
- Do NOT follow imports, includes, callers, callees, or related modules outside changed files.
- Do NOT mention any file path not present in the changed files list.
- Every finding must be grounded in at least one changed hunk from the reviewed diff.
- Other changed files may be used as supporting context only.
- Nearby unchanged lines in changed files may be used as supporting context only.
- Do NOT raise findings about code outside changed files.
- Do NOT provide general repo suggestions or unrelated improvement ideas.
- Do NOT include positive confirmations like "No issues with X"
- If confidence is low, omit the finding.
Allowed workflow:
1) ls -1 .claude/rules 2>/dev/null || true
2) cat CLAUDE.md 2>/dev/null || true
3) find .claude/rules -maxdepth 1 -name "*.md" -print | head -n 10 | xargs -I{} cat "{}" 2>/dev/null || true
4) cat "${{ steps.review_input.outputs.changed_files_path }}"
5) cat "${{ steps.review_input.outputs.review_diff_path }}"
6) Optionally inspect files inside "${{ steps.context.outputs.context_dir }}" only
7) Write the final review markdown to .claude-review/output.md, then STOP
8) Do NOT post, update, or create GitHub comments yourself
Review policy:
- Review the full PR diff.
- Do NOT restate the full PR summary.
- If there are no high-confidence findings, leave .claude-review/output.md empty and STOP.
Review standard (in priority order per CLAUDE.md "Code Review Priorities"):
1. Correctness (logic bugs, numerical issues, array bounds)
2. Precision discipline (stp vs wp mixing)
3. Memory management (@:ALLOCATE/@:DEALLOCATE pairing, GPU pointer setup)
4. MPI correctness (halo exchange, buffer sizing, GPU_UPDATE calls)
5. GPU code (GPU_* Fypp macros only, no raw pragmas)
6. Physics consistency (pressure formula matches model_eqns)
7. Compiler portability (4 CI-gated compilers + AMD flang for GPU)
- Avoid style nitpicks.
- A finding is valid only if it is supported by changed lines, with changed-file context used only to confirm it.
Output rules:
- Write markdown only to .claude-review/output.md
- If there are findings, use exactly this format:
Claude Code Review
Head SHA: <sha>
Files changed:
- <count>
- <up to 10 paths from changed_files.txt>
Findings:
- <only high-confidence issues grounded in changed hunks>
<!-- claude-review: thread=primary; reviewed_sha=<current_head_sha>; mode=full -->
- Always include the hidden marker exactly once at the end of the file.
- If there are no findings, write nothing.
- name: Publish review comment
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
PR_NUMBER="${{ steps.mode.outputs.pr_number }}"
REPO="${{ github.repository }}"
COMMENT_ID="${{ steps.state.outputs.existing_comment_id }}"
OUTPUT_FILE=".claude-review/output.md"
if [[ ! -f "$OUTPUT_FILE" ]]; then
echo "No output file; nothing to publish."
exit 0
fi
if [[ ! -s "$OUTPUT_FILE" ]] || [[ -z "$(tr -d '[:space:]' < "$OUTPUT_FILE")" ]]; then
echo "Review output is empty; not posting a comment."
exit 0
fi
BODY_JSON="$(jq -Rs '{body: .}' < "$OUTPUT_FILE")"
if [[ -n "${COMMENT_ID:-}" ]]; then
gh api \
--method PATCH \
"repos/$REPO/issues/comments/$COMMENT_ID" \
--input - <<< "$BODY_JSON" >/dev/null
echo "Updated existing primary review comment: $COMMENT_ID"
else
gh api \
--method POST \
"repos/$REPO/issues/$PR_NUMBER/comments" \
--input - <<< "$BODY_JSON" >/dev/null
echo "Created new primary review comment."
fi
- name: Fallback job summary on failure
if: failure()
shell: bash
run: |
set -euo pipefail
if [[ -f .claude-review/output.md ]] && [[ -s .claude-review/output.md ]]; then
{
echo "## Claude Code Review"
echo
cat .claude-review/output.md
} >> "$GITHUB_STEP_SUMMARY"
fi