Skip to content

Add replayable closeout evidence gates #316

Add replayable closeout evidence gates

Add replayable closeout evidence gates #316

name: Claude Code Review
on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
jobs:
claude-review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
allowed_bots: "dependabot[bot]"
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request with a focus on:
- Code quality and best practices
- Potential bugs or issues
- Security implications
- Performance considerations
- Portability: shared skills and workflows must stay generic. Flag any
consumer-repo commands, labels, branches, release trackers, or paths
hardcoded in `skills/` or `workflows/` (see AGENTS.md "Editing Rules").
- Shell and Ruby helper safety in `bin/` and `skills/*/bin/`.
Note: The PR branch is already checked out in the current working directory.
Use `gh pr comment` for top-level feedback.
Use `mcp__github_inline_comment__create_inline_comment` to highlight specific code issues.
Only post GitHub comments - don't submit review text as messages.
claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
# The action exits 0 even when the review never ran: token auth failures,
# expired tokens, or exhausted credits can fail before model work starts,
# yet the result still reports a green "pass" and posts no review. Inspect
# the execution output and fail any Claude-level error.
#
# Scoped to outcome == 'success' on purpose. When the action itself fails
# (missing token on Dependabot PRs, the "workflow validation failed" safety
# skip on PRs that edit this file, a real action error) the job is already
# red and the action prints its own message, so re-failing here would only
# add a misleading one. And a successful run that legitimately skips Claude
# (so emits no execution_file/result) is treated as a pass, not a failure.
- name: Verify review completed (fail on Claude error)
if: steps.claude-review.outcome == 'success'
env:
EXECUTION_FILE: ${{ steps.claude-review.outputs.execution_file }}
run: |
set -euo pipefail
TOKEN_HINT="Check CLAUDE_CODE_OAUTH_TOKEN auth, available credits/quota, and the repo secret. Rotate with 'claude setup-token' if needed."
# No execution output: the action skipped Claude (e.g. the workflow-
# validation safety skip). Nothing was claimed to run, so let it pass.
if [ -z "${EXECUTION_FILE:-}" ] || [ ! -f "$EXECUTION_FILE" ]; then
echo "No execution output found; the action skipped Claude. Nothing to verify."
exit 0
fi
# The execution file may be a JSON array or newline-delimited JSON;
# slurp + flatten handles both, then grab the final result record.
result=$(jq -s 'flatten | map(select(type == "object" and .type == "result")) | last' "$EXECUTION_FILE" 2>/dev/null || echo null)
if [ "$result" = "null" ] || [ -z "$result" ]; then
echo "No result record in execution output; nothing to verify."
exit 0
fi
is_error=$(echo "$result" | jq -r '.is_error // false')
cost=$(echo "$result" | jq -r '.total_cost_usd // 0')
turns=$(echo "$result" | jq -r '.num_turns // 0')
echo "Claude review result: is_error=$is_error total_cost_usd=$cost num_turns=$turns"
# is_error=true with $0 cost and a single turn means Claude could not
# start real model work. Nonzero-cost errors mean Claude ran but ended
# in an error state. Either way, no review should be treated as valid.
if [ "$is_error" = "true" ]; then
if [ "$cost" = "0" ] && [ "$turns" -le 1 ]; then
echo "::error::Claude review failed before model work (is_error=true, cost=$cost, turns=$turns). $TOKEN_HINT"
else
echo "::error::Claude review session ended in error (is_error=true, cost=$cost, turns=$turns). Inspect the execution output for details. $TOKEN_HINT"
fi
exit 1
fi