Skip to content

enable blockwise FP8 quantization on rocm #75

enable blockwise FP8 quantization on rocm

enable blockwise FP8 quantization on rocm #75

name: Claude PR Action
# Single workflow: PR review or summary, triggered by label, comment, or manually.
#
# Triggers:
# - Label `claude-review` / `claude-summary` on a PR
# - Comment `/claude review` / `/claude summary` from a writer on a PR
# - Manual workflow_dispatch (re-runs)
#
# Auth model:
# - Anthropic: subscription via CLAUDE_CODE_OAUTH_TOKEN.
# - GitHub: workflow's GITHUB_TOKEN passed as `github_token` to
# claude-code-action. This skips the Anthropic OIDC App-token
# exchange (which rejects pull_request_target / issue_comment
# subjects), so this workflow can run directly on those events
# with no repository_dispatch indirection and no PAT. Cost:
# comments post as `github-actions[bot]` instead of
# `claude[bot]`. Dedup across runs uses an HTML marker
# (`<!-- by:claude -->`) appended to every Claude-posted
# comment, so the filter is login-agnostic.
#
# Migrating to a custom GitHub App later: replace `secrets.GITHUB_TOKEN` in
# the two `github_token:` inputs (and the `GH_TOKEN` env on those steps) with
# an installation token from `actions/create-github-app-token@v1`. No other
# changes needed — the marker-based dedup keeps working across the swap.
#
# Note: We pin commits for all actions used here to avoid accidental breakage
# from upstream changes.
on:
pull_request_target:
types: [labeled]
issue_comment:
types: [created]
workflow_dispatch:
inputs:
action:
description: 'review or summary'
required: true
type: choice
options: [review, summary]
pr_number:
description: 'PR number'
required: true
type: number
base:
description: 'PR base branch (default: repo default branch)'
required: false
type: string
permissions:
contents: read
pull-requests: write
issues: write
jobs:
resolve:
# Fast dispatcher: parse the event, decide whether to act, ack the user.
# Kept lightweight so PR label/comment churn doesn't queue heavy jobs.
runs-on: ubuntu-latest
if: >
github.event_name == 'workflow_dispatch' ||
github.event_name == 'pull_request_target' ||
(github.event_name == 'issue_comment' && github.event.issue.pull_request != null)
outputs:
action: ${{ steps.resolve.outputs.action }}
pr: ${{ steps.resolve.outputs.pr }}
base: ${{ steps.resolve.outputs.base }}
help: ${{ steps.resolve.outputs.help }}
steps:
- name: Resolve action, PR number, and base branch
id: resolve
env:
GH_TOKEN: ${{ github.token }}
EVENT_NAME: ${{ github.event_name }}
LABEL_NAME: ${{ github.event.label.name }}
COMMENT_BODY: ${{ github.event.comment.body }}
AUTHOR_ASSOC: ${{ github.event.comment.author_association }}
PR_FROM_LABEL: ${{ github.event.pull_request.number }}
PR_FROM_COMMENT: ${{ github.event.issue.number }}
BASE_FROM_LABEL: ${{ github.event.pull_request.base.ref }}
INPUT_ACTION: ${{ inputs.action }}
INPUT_PR: ${{ inputs.pr_number }}
INPUT_BASE: ${{ inputs.base }}
run: |
set -euo pipefail
action=""; pr=""; base=""
case "$EVENT_NAME" in
pull_request_target)
case "$LABEL_NAME" in
claude-review) action="review" ;;
claude-summary) action="summary" ;;
esac
pr="$PR_FROM_LABEL"
base="$BASE_FROM_LABEL"
;;
issue_comment)
# Only writers can trigger — drop bots and outside contributors.
case "$AUTHOR_ASSOC" in
OWNER|MEMBER|COLLABORATOR) ;;
*) echo "Ignoring comment from $AUTHOR_ASSOC"; exit 0 ;;
esac
# Look at the first whitespace-separated token. If it's not
# `/claude`, this isn't addressed to us — stay silent.
first=$(printf '%s' "$COMMENT_BODY" | awk 'NR==1 {print $1}')
if [[ "$first" != "/claude" ]]; then
echo "Not a /claude command; ignoring."
exit 0
fi
# Second token is the subcommand. Unknown/missing → post help.
cmd=$(printf '%s' "$COMMENT_BODY" | awk 'NR==1 {print $2}')
case "$cmd" in
review) action="review" ;;
summary) action="summary" ;;
*)
echo "Unknown /claude subcommand: '${cmd:-<empty>}'"
echo "help=1" >> "$GITHUB_OUTPUT"
exit 0
;;
esac
pr="$PR_FROM_COMMENT"
;;
workflow_dispatch)
action="$INPUT_ACTION"
pr="$INPUT_PR"
base="$INPUT_BASE"
;;
esac
if [[ -z "$action" ]]; then
echo "No matching action; nothing to do."
exit 0
fi
if [[ -z "$pr" ]]; then
echo "::error::pr_number is required" >&2
exit 1
fi
# Comment triggers (and workflow_dispatch w/o base) — look up the
# PR's actual merge target so the worker diffs against it.
if [[ -z "$base" ]]; then
base=$(gh pr view "$pr" \
--repo "${{ github.repository }}" \
--json baseRefName -q .baseRefName)
fi
echo "action=$action" >> "$GITHUB_OUTPUT"
echo "pr=$pr" >> "$GITHUB_OUTPUT"
echo "base=$base" >> "$GITHUB_OUTPUT"
- name: React to comment (acknowledge)
if: steps.resolve.outputs.action != '' && github.event_name == 'issue_comment'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api \
-H "Accept: application/vnd.github+json" \
--method POST \
"/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
-f content=eyes || true
- name: Post help comment (invalid /claude command)
if: steps.resolve.outputs.help == '1'
env:
GH_TOKEN: ${{ github.token }}
run: |
# React with confused emoji so the user sees immediate feedback,
# then post a one-shot usage reply.
gh api \
-H "Accept: application/vnd.github+json" \
--method POST \
"/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
-f content=confused || true
gh pr comment "${{ github.event.issue.number }}" \
--repo "${{ github.repository }}" \
--body-file - <<'EOF'
**Claude PR commands**
- `/claude review` — request a code review of this PR
- `/claude summary` — generate (or update) a walkthrough comment
You can also add a label to the PR: `claude-review` or `claude-summary`.
<!-- by:claude -->
EOF
claude:
needs: resolve
if: needs.resolve.outputs.action != ''
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
# One Claude job per (PR, action) at a time; cancel superseded runs.
group: claude-pr-${{ needs.resolve.outputs.pr }}-${{ needs.resolve.outputs.action }}
cancel-in-progress: true
env:
ACTION: ${{ needs.resolve.outputs.action }}
PR_NUMBER: ${{ needs.resolve.outputs.pr }}
BASE_REF: ${{ needs.resolve.outputs.base }}
steps:
# SECURITY GATE — must run before any step that materializes PR code.
# pull_request_target grants this job write-scoped GITHUB_TOKEN and the
# CLAUDE_CODE_OAUTH_TOKEN secret. If we then check out the fork's tree
# and let Claude run `git diff` etc. on it, a malicious PR can hijack
# those credentials (e.g. via a `.gitattributes` textconv driver).
# Restrict fork PRs to authors with write/maintain/admin on the base
# repo; same-repo PRs and workflow_dispatch already require write perms
# to reach this point.
- name: Block fork PRs from non-collaborators
if: github.event_name == 'pull_request_target'
env:
GH_TOKEN: ${{ github.token }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
run: |
set -euo pipefail
if [[ "$HEAD_REPO" == "${{ github.repository }}" ]]; then
echo "Same-repo PR; collaborator check not required."
exit 0
fi
perm=$(gh api "repos/${{ github.repository }}/collaborators/$PR_AUTHOR/permission" \
--jq .permission 2>/dev/null || echo none)
case "$perm" in
admin|maintain|write)
echo "Fork PR author $PR_AUTHOR has $perm; allowing."
;;
*)
echo "::error::Fork PR from $PR_AUTHOR ($HEAD_REPO) lacks write access (perm=$perm); refusing to run on untrusted code."
exit 1
;;
esac
# refs/pull/<n>/merge is GitHub's synthetic merge commit (base tip
# merged with PR head). Checking it out gives us both parents in one
# shot: HEAD^1 = base tip, HEAD^2 = PR head — no separate base fetch
# needed. Caveat: the merge ref only exists when the PR is mergeable;
# if it's missing/stale, the workflow will fail fast on checkout, which
# is the right behavior for an unreviewable PR.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/pull/${{ env.PR_NUMBER }}/merge
# Skills live in .github/agent-skills/.
# Stage them into .claude/skills/ at runtime so Claude Code discovers
# them via its default `.claude/skills/<name>/SKILL.md` lookup. Source
# from the repo default branch so a release-branch PR (which may not
# carry the skills) still gets the latest set.
- name: Stage Claude skills
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
set -euo pipefail
git fetch origin "$DEFAULT_BRANCH"
mkdir -p .claude/skills
# `git archive | tar -x` materializes the skills from the default
# branch even if the PR branch deleted or doesn't carry them.
if git cat-file -e "origin/$DEFAULT_BRANCH:.github/agent-skills" 2>/dev/null; then
git archive "origin/$DEFAULT_BRANCH" .github/agent-skills \
| tar -x --strip-components=2 -C .claude/skills
else
echo "::warning::No .github/agent-skills/ on origin/$DEFAULT_BRANCH; review will run skill-less."
fi
ls -la .claude/skills/ || true
# Workaround mirrored from ROCm/xla: pre-install Claude Code so the
# action does not hang during first-run init.
- name: Install and warm up Claude Code
timeout-minutes: 2
env:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
run: |
curl -fsSL https://claude.ai/install.sh | bash
export PATH="$HOME/.local/bin:$PATH"
claude --version
# Run the warmup in a clean directory so Claude Code does not
# auto-discover CLAUDE.md / .claude/ from the (untrusted) PR tree
# at $GITHUB_WORKSPACE. The OAUTH token is in env at this step,
# and a malicious workspace CLAUDE.md could otherwise prompt-inject
# the warmup invocation into echoing it.
warmup_dir=$(mktemp -d)
( cd "$warmup_dir" && timeout 60 claude --print -p "Say OK" ) || echo "Warmup complete"
rm -rf "$warmup_dir"
# claude-code-action only auto-configures the inline-comment MCP server
# for pull_request* events. Wire it up manually so it works regardless
# of trigger event.
- name: Configure inline-comment MCP
id: mcp
run: |
set -euo pipefail
server=$(find "$(dirname "$RUNNER_WORKSPACE")/_actions/anthropics/claude-code-action" \
-name "github-inline-comment-server.ts" 2>/dev/null | head -1)
cat > /tmp/mcp-config.json <<EOF
{
"mcpServers": {
"github_inline_comment": {
"command": "bun",
"args": ["run", "$server"],
"env": {
"REPO_OWNER": "${{ github.repository_owner }}",
"REPO_NAME": "${{ github.event.repository.name }}",
"PR_NUMBER": "${{ env.PR_NUMBER }}",
"GITHUB_API_URL": "${{ github.api_url }}"
}
}
}
}
EOF
echo "file=/tmp/mcp-config.json" >> "$GITHUB_OUTPUT"
# ---- REVIEW ----
- name: Run Claude — Code Review
id: review
if: env.ACTION == 'review'
timeout-minutes: 30
uses: anthropics/claude-code-action@dde2242db6af13460b916652159b6ba19a598f30 # v1.0.120
env:
# Same token is exposed to the model's `gh` subprocess so it can
# comment on the PR. Mirrors the `github_token:` input below.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Setting github_token short-circuits the Anthropic OIDC → App-token
# exchange in claude-code-action (src/github/token.ts). Without this
# the action would try to exchange the workflow's OIDC subject for
# the official `claude[bot]` App token, which Anthropic rejects on
# pull_request_target / issue_comment events. Trade-off: comments
# post as github-actions[bot]. Dedup uses the HTML marker in the
# prompt rather than the bot login, so this is identity-portable.
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_bots: "github-actions[bot]"
show_full_output: true
# Strict allowlist for Bash(...) and MCP tools (no disallowedTools).
# The matcher splits chained commands on `;`/`&&`/`|` and checks
# each segment, so `Bash(git diff *)` covers `BASE=…; git diff …`
# but `Bash(echo *)` is still needed for the `echo "---"` segment.
# Built-in tools (Read, Grep, Glob, Skill, TodoWrite, ToolSearch,
# Write, Edit) bypass --allowedTools enforcement, but Read/Grep/
# Glob/Skill are listed for documentation. Patterns are verified
# against past run transcripts; widen only when a transcript shows
# a needed command being denied — never to `Bash(gh *)`/`Bash(git
# *)`/`Bash(*)`.
claude_args: |
--model claude-opus-4-7 --effort xhigh --allowedTools "Skill,mcp__github_inline_comment__create_inline_comment,Bash(gh pr view *),Bash(gh pr comment *),Bash(gh pr diff *),Bash(gh api repos/*),Bash(gh api /repos/*),Bash(gh api --paginate repos/*),Bash(gh api --paginate /repos/*),Bash(git diff *),Bash(git log *),Bash(git show *),Bash(git cat-file *),Bash(git ls-files *),Bash(git rev-parse *),Bash(git rev-list *),Bash(git ls-remote *),Bash(git merge-base *),Bash(git fetch *),Bash(git status),Bash(git status *),Bash(jq *),Bash(head *),Bash(grep *),Bash(echo *),Bash(ls),Bash(ls *),Read,Grep,Glob" --mcp-config ${{ steps.mcp.outputs.file }}
settings: |
{ "hasCompletedOnboarding": true }
prompt: |
REPO: ${{ github.repository }}
PR: ${{ env.PR_NUMBER }}
BASE: ${{ env.BASE_REF }} # PR's actual merge target (label only)
The synthetic merge commit `refs/pull/${{ env.PR_NUMBER }}/merge`
is checked out, so `HEAD^1` is the base tip (the PR's merge
target) and `HEAD^2` is the PR head. Use `HEAD^1` for every
diff/comparison — this works regardless of whether the merge
target is the default branch or a release branch.
## Identity & dedup
This workflow posts as `github-actions[bot]` (until a dedicated
GitHub App is provisioned). To make prior-Claude lookups robust
across that future swap, every Claude-posted comment carries the
HTML marker `<!-- by:claude -->`. You MUST append that marker on
its own line at the end of every comment you post in step 3.
## 1. Gather prior context
Use `gh` to enumerate signals that should shape this review:
a. Prior Claude inline comments (top-level only):
```
gh api --paginate "repos/${{ github.repository }}/pulls/${{ env.PR_NUMBER }}/comments" \
| jq -s 'add // [] | [.[] | select((.body | test("<!-- by:claude -->")) and .in_reply_to_id == null)]'
```
b. Prior human reviews and review comments — note any unresolved
threads or themes already raised by reviewers; do not duplicate.
c. Top-level PR comments containing `<!-- by:claude -->` (prior
summaries / review verdicts).
## 2. Produce findings
Run BOTH skills below and merge their findings before posting. Each
covers a distinct concern; neither subsumes the other.
**2a. Code review** — `/review-pr` (vendored in `.claude/skills/`).
Pass the PR number and base ref so it scopes the diff correctly:
`/review-pr ${{ env.PR_NUMBER }} --base HEAD^1`
If a prior Claude review exists (step 1a returned non-empty),
instruct the skill to focus on commits added since the most recent
marker-tagged inline-comment timestamp — re-reading the entire
diff is wasteful and produces duplicate noise.
**2b. Copyright header audit** — `/copyright-check` (vendored in
`.claude/skills/`). This is the AMD-side counterpart to
`qa/L0_license/copyright_checker.py` and verifies that ROCm-modified
and ROCm-introduced files carry correct AMD headers with up-to-date
year ranges, without altering preserved NVIDIA copyrights:
`/copyright-check HEAD^1`
Run this on every review (initial and re-review). Copyright
findings are typically actionable on a single line, so prefer
inline comments on the offending header line for each finding.
Do NOT post anything to GitHub yet; collect findings from both
skills in memory and dedupe against step 1 before posting.
## 3. Post results
- For each finding (from 2a or 2b), call
`mcp__github_inline_comment__create_inline_comment` on the
relevant diff line. End every comment body with a newline and
`<!-- by:claude -->` so subsequent runs can identify it.
Skip findings that duplicate any comment from step 1
(Claude's or a human reviewer's).
- Post ONE short top-level summary via `gh pr comment` describing
what was reviewed and the high-level verdict; end with
`<!-- by:claude -->`. Mention the copyright audit result as a
single line (e.g. "Copyright headers: OK" or "Copyright
headers: 3 files need updates — see inline comments"). Do not
repeat individual findings.
- If this is a re-review and there are no new findings, post a
brief top-level comment saying so (still with the marker).
- Do NOT post intermediate analysis or thinking to the PR.
# ---- SUMMARY / WALKTHROUGH ----
- name: Run Claude — Summary & Walkthrough
id: summary
if: env.ACTION == 'summary'
timeout-minutes: 20
uses: anthropics/claude-code-action@dde2242db6af13460b916652159b6ba19a598f30 # v1.0.120
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# See the review step above for why github_token is set explicitly.
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_bots: "github-actions[bot]"
show_full_output: true
# Strict allowlist for Bash(...) and MCP (see review step for the
# full rationale). Summary additionally needs:
# - `gh api -X{POST,PATCH} repos/*/issues/*/comments` to create
# or update the walkthrough top-level comment (past runs use
# either `gh api -F body=@-` or `gh pr comment --body-file`);
# - `cat *` for `cat > /tmp/walkthrough.md <<EOF` heredocs the
# model uses to stage the body before posting;
# - `git fetch *` / `git merge-base *` for shallow-clone deepening
# when the synthetic merge commit's parents aren't reachable.
# Review intentionally does NOT allow POST/PATCH against the issues
# comments endpoint; it posts inline via the MCP tool instead.
claude_args: |
--model claude-opus-4-7 --effort xhigh --allowedTools "Skill,Bash(gh pr view *),Bash(gh pr comment *),Bash(gh pr diff *),Bash(gh api repos/*),Bash(gh api /repos/*),Bash(gh api --paginate repos/*),Bash(gh api --paginate /repos/*),Bash(gh api --method POST repos/*),Bash(gh api --method POST /repos/*),Bash(gh api -X POST repos/*),Bash(gh api -X POST /repos/*),Bash(gh api --method PATCH repos/*),Bash(gh api --method PATCH /repos/*),Bash(gh api -X PATCH repos/*),Bash(gh api -X PATCH /repos/*),Bash(git diff *),Bash(git log *),Bash(git show *),Bash(git cat-file *),Bash(git ls-files *),Bash(git rev-parse *),Bash(git rev-list *),Bash(git merge-base *),Bash(git fetch *),Bash(git status),Bash(git status *),Bash(jq *),Bash(echo *),Bash(cat *),Bash(ls),Bash(ls *),Read,Grep,Glob"
settings: |
{ "hasCompletedOnboarding": true }
prompt: |
REPO: ${{ github.repository }}
PR: ${{ env.PR_NUMBER }}
BASE: ${{ env.BASE_REF }} # PR's actual merge target (label only)
The synthetic merge commit `refs/pull/${{ env.PR_NUMBER }}/merge`
is checked out, so `HEAD^1` is the base tip and `HEAD^2` is the
PR head. Use `HEAD^1` for any diff or comparison.
## Goal
Produce ONE top-level PR comment that helps a reader understand
this change without reading every line of the diff. This is an
explanatory artifact, NOT a review — do not flag issues here.
## 1. Check for prior summaries
This workflow posts as `github-actions[bot]`; prior Claude
artifacts are tagged with the HTML marker `<!-- by:claude -->`.
```
gh api --paginate "repos/${{ github.repository }}/issues/${{ env.PR_NUMBER }}/comments" \
| jq -s 'add // [] | [.[] | select(.body | test("<!-- by:claude -->")) | select(.body | test("Claude Walkthrough"))]'
```
If a prior summary exists, edit it (gh api PATCH on the comment
id from the response above) instead of posting a new one — keep
one canonical walkthrough that reflects the current state of the
PR. Otherwise, post a new one.
## 2. Build the walkthrough
Read the PR title/description and `git diff HEAD^1...HEAD^2`.
Use `Grep`/`Read` to ground claims in the actual code.
Format the comment exactly as:
```markdown
## Claude Walkthrough
**Intent.** 1–3 sentences on what problem this PR solves and why,
inferred from the description and the diff.
**Key changes.**
- Bullet per logically distinct change. Reference files as
`path/to/file.py:LINE` when pointing to a specific construct.
**Walkthrough.**
File-by-file (or component-by-component) prose for the non-trivial
changes. Skip pure renames, formatting, and generated files.
Explain *why* a change was made when it is not self-evident.
**Testing.** What tests were added/changed, and what behavior
they cover. If no tests were added, say so.
**Notes for reviewers.** Anything subtle: invariants relied on,
backwards-compat concerns, perf implications, follow-ups deferred.
---
_Generated by Claude. To request a code review, comment `/claude review`._
<!-- by:claude -->
```
Keep it tight. A reader should be able to skim it in under a minute
and know whether they need to dive deeper. Do NOT post inline
comments and do NOT post anything other than this single top-level
comment.
- name: Upload Claude execution log
if: always() && (steps.review.outputs.execution_file != '' || steps.summary.outputs.execution_file != '')
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: claude-${{ env.ACTION }}-pr${{ env.PR_NUMBER }}-log
path: ${{ steps.review.outputs.execution_file || steps.summary.outputs.execution_file }}
- name: Remove trigger label
if: always() && github.event_name == 'pull_request_target'
env:
GH_TOKEN: ${{ github.token }}
run: |
label="claude-${{ env.ACTION }}"
gh api --method DELETE \
"/repos/${{ github.repository }}/issues/${{ env.PR_NUMBER }}/labels/$label" \
|| true