b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
151 lines
6.2 KiB
YAML
151 lines
6.2 KiB
YAML
name: Review PR
|
|
|
|
# /review triggers this workflow. The first word after the trigger picks a
|
|
# model alias from .github/bonk-models.json. Currently registered aliases
|
|
# (see that file for the source of truth):
|
|
#
|
|
# /review -> default model (currently opus)
|
|
# /review opus -> Claude Opus 4.7 (default)
|
|
# /review kimi -> Kimi K2.7 Code (cheap pass for tiny PRs)
|
|
#
|
|
# Add new aliases by editing .github/bonk-models.json.
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
pull_request_review_comment:
|
|
types: [created]
|
|
|
|
# Concurrency is at job level (below) rather than workflow level so it's only
|
|
# evaluated when the `if:` filter passes.
|
|
|
|
jobs:
|
|
review:
|
|
# mentions in this check must match the `mentions` input below.
|
|
# For issue_comment events, require the comment to be on a PR (not an issue).
|
|
if: >-
|
|
github.event.sender.type != 'Bot'
|
|
&& contains(github.event.comment.body, '/review')
|
|
&& contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
|
|
&& (github.event_name != 'issue_comment' || github.event.issue.pull_request != null)
|
|
# Per-workflow group key so /review and /bonk have independent queues
|
|
# per target.
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: false
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
issues: write
|
|
pull-requests: write
|
|
steps:
|
|
- name: Get PR number
|
|
id: pr-number
|
|
env:
|
|
# issue_comment on a PR exposes the number via github.event.issue.number;
|
|
# pull_request_review_comment exposes it via github.event.pull_request.number.
|
|
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
|
|
run: |
|
|
echo "number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Verify PR exists
|
|
id: verify-pr
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
|
|
run: |
|
|
if gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > /dev/null 2>&1; then
|
|
echo "exists=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "exists=false" >> "$GITHUB_OUTPUT"
|
|
echo "::warning::PR #${PR_NUMBER} not found, skipping review"
|
|
fi
|
|
|
|
- name: Checkout repository
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
fetch-depth: 1
|
|
persist-credentials: false
|
|
|
|
- name: Resolve model from comment
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
id: model
|
|
env:
|
|
BODY: ${{ github.event.comment.body }}
|
|
run: node .github/scripts/resolve-bonk-model.mjs
|
|
|
|
- name: Setup pnpm
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
|
|
|
- name: Setup Node.js
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version-file: "package.json"
|
|
cache: "pnpm"
|
|
|
|
- name: Install dependencies
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Get PR details
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
id: pr-details
|
|
run: |
|
|
gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > /tmp/pr_data.json
|
|
# Use heredoc form for every field — PR titles and bodies can contain
|
|
# newlines that would otherwise corrupt $GITHUB_OUTPUT and let a PR
|
|
# author smuggle arbitrary step outputs via their title/body.
|
|
{
|
|
echo 'title<<PR_TITLE_EOF'
|
|
jq -r .title /tmp/pr_data.json
|
|
echo PR_TITLE_EOF
|
|
echo "sha=$(jq -r .head.sha /tmp/pr_data.json)"
|
|
echo 'body<<PR_BODY_EOF'
|
|
jq -r .body /tmp/pr_data.json
|
|
echo PR_BODY_EOF
|
|
} >> "$GITHUB_OUTPUT"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
|
|
|
|
- name: Run Review (${{ steps.model.outputs.alias }})
|
|
if: steps.verify-pr.outputs.exists == 'true'
|
|
uses: ask-bonk/ask-bonk/github@bfd92f4d0abb62d98558b35432534f7b9992f3eb # main as of 2026-04-24
|
|
env:
|
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_AI_GATEWAY_ACCOUNT_ID }}
|
|
CLOUDFLARE_GATEWAY_ID: ${{ secrets.CF_AI_GATEWAY_NAME }}
|
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_AI_GATEWAY_TOKEN }}
|
|
OPENCODE_CONFIG_CONTENT: ${{ steps.model.outputs.opencode_config }}
|
|
with:
|
|
model: ${{ steps.model.outputs.model }}
|
|
mentions: "/review"
|
|
opencode_version: "1.4.11"
|
|
permissions: write
|
|
# NO_PUSH scopes the installation token to contents:read so the
|
|
# reviewer cannot push, even if it tries to commit. Write tools
|
|
# remain enabled in the agent definition so it can scaffold fixes
|
|
# locally to verify reasoning.
|
|
token_permissions: NO_PUSH
|
|
# Custom agent defined in .opencode/agents/auto-reviewer.md.
|
|
# Holds the review philosophy, investigation protocol, and posting
|
|
# protocol so workflows stay small.
|
|
agent: auto-reviewer
|
|
prompt: |
|
|
Review pull request #${{ steps.pr-number.outputs.number }} ("${{ steps.pr-details.outputs.title }}").
|
|
|
|
Follow your agent instructions for investigation, severity calibration, and posting. Post a single review with line-anchored comments via the gh CLI; the summary will be posted as a separate workflow comment.
|
|
|
|
<pr_number>${{ steps.pr-number.outputs.number }}</pr_number>
|
|
<pr_description>
|
|
${{ steps.pr-details.outputs.body }}
|
|
</pr_description>
|
|
|
|
If the PR looks good, respond with only "LGTM!" and skip posting a review.
|