Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ tone_instructions: >-
Prioritize correctness, security, data loss, lifecycle, and regressions; avoid speculative style
comments and unrelated refactors.

chat:
allow_non_org_members: false

knowledge_base:
web_search:
enabled: true
Expand All @@ -24,6 +27,7 @@ reviews:
enabled: false
drafts: false
auto_incremental_review: true
auto_pause_after_reviewed_commits: 0
labels:
- "coderabbit-review-active"

Expand Down Expand Up @@ -125,6 +129,7 @@ reviews:
and deprioritize prose-only nits that do not affect correctness or usability.

pre_merge_checks:
override_requested_reviewers_only: true
custom_checks:
- name: Regression evidence
mode: warning
Expand Down
69 changes: 47 additions & 22 deletions .github/workflows/label-pr-review-state.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ on:
types: [opened, reopened, ready_for_review, synchronize, review_requested, labeled, unlabeled]
pull_request_review:
types: [submitted, dismissed]
# Fork review events have a read-only token. CodeRabbit's status-comment update
# provides a trusted base-repository event that can reconcile those PRs promptly.
issue_comment:
types: [created, edited]
workflow_run:
workflows: ["Code QA Roo Code", "E2E Tests (Mocked)", "Webview Visual Regression", "CodeQL Advanced"]
types: [completed]

permissions:
pull-requests: write
# This privileged workflow only reads PR/check metadata and writes issue labels,
# comments, and commit statuses. All unspecified permissions, including contents,
# are none; no fork code or configuration is checked out or executed.
pull-requests: read
issues: write
checks: read
statuses: write
Expand All @@ -32,6 +39,9 @@ concurrency:
jobs:
reconcile:
name: Zoo Code / reconcile PR review state
if: >-
github.event_name != 'issue_comment' ||
(github.event.issue.pull_request && github.event.comment.user.login == 'coderabbitai[bot]')
runs-on: ubuntu-latest
steps:
- name: Reconcile PR review state labels
Expand All @@ -52,17 +62,17 @@ jobs:
{
name: 'awaiting-coderabbit',
color: '5319e7',
description: 'Waiting for CodeRabbit to approve the latest commit',
description: 'Waiting for automated review of the latest commit',
},
{
name: 'awaiting-ready',
color: '1d76db',
description: 'CodeRabbit approved; waiting for the draft to be marked ready',
description: 'Automated review complete; waiting for the draft to be marked ready',
},
{
name: 'awaiting-maintainer',
color: '0e8a16',
description: 'CodeRabbit approved; waiting for a human maintainer',
description: 'Waiting for fresh human maintainer or CODEOWNER approval',
},
{
name: 'coderabbit-review-active',
Expand All @@ -77,12 +87,21 @@ jobs:
const reviewGateName = 'Zoo Code / PR review gate';
const reconciliationCheckName = 'Zoo Code / reconcile PR review state';

if (context.eventName === 'issue_comment' &&
(!context.payload.issue?.pull_request ||
context.payload.comment?.user?.login?.toLowerCase() !== codeRabbitLogin)) {
core.info('Ignoring untrusted issue comment event');
return;
}

// When triggered by a single PR event, only reconcile that PR.
// The hourly schedule and workflow_dispatch reconcile all open PRs.
let prs;
let eventPrNumbers = [];
if (context.payload.pull_request?.number) {
eventPrNumbers = [context.payload.pull_request.number];
} else if (context.eventName === 'issue_comment') {
eventPrNumbers = [context.payload.issue.number];
} else if (context.eventName === 'workflow_dispatch') {
eventPrNumbers = [Number(context.payload.inputs.pull_request_number)];
} else if (context.payload.workflow_run?.pull_requests) {
Expand Down Expand Up @@ -305,16 +324,16 @@ jobs:

function phaseMessage(phase) {
const messages = {
draft: 'Mark the PR ready to start CodeRabbit after required CI passes.',
draft: 'Mark the PR ready. Required CI must pass before CodeRabbit starts.',
conflict: 'Resolve the merge conflicts. The review sequence resumes after the branch is mergeable.',
'ci-pending': 'Wait for the required CI checks to finish.',
'ci-failed': 'Fix the failing required CI checks and push an update.',
'ci-pending': 'Wait for required CI checks; awaiting-maintainer requires CI and automated review completion.',
'ci-failed': 'Fix the failing required CI checks; awaiting-maintainer requires CI and automated review completion.',
'configuration-error': 'Repository rules must not require this advisory workflow\'s own gate or reconciliation job.',
'coderabbit-changes': 'Address CodeRabbit findings and push an update. Review restarts after CI passes.',
coderabbit: 'Required CI passed. Wait for CodeRabbit to approve the latest commit.',
'draft-approved': 'CodeRabbit approved the latest commit. Mark the draft ready.',
'maintainer-changes': 'Address the maintainer feedback, push an update, and request another review.',
maintainer: 'Ready for human maintainer review and approval.',
'coderabbit-changes': 'Address automated review findings and push fixes.',
coderabbit: 'Required CI passed. Waiting for automated review of the latest commit.',
'draft-approved': 'Automated review complete for the latest commit. Mark the draft ready.',
'maintainer-changes': 'Address maintainer or CODEOWNER feedback, then push an update.',
maintainer: 'Awaiting fresh human maintainer or CODEOWNER approval.',
approved: 'The required review sequence passed. Remaining merge requirements apply.',
};
return messages[phase];
Expand Down Expand Up @@ -373,12 +392,18 @@ jobs:
? `\n${codeRabbitLabelMarkerPrefix}${pr.head.sha}${activationPending ? ':pending' : ''} -->`
: '';

return `${guideMarker}\n### Review process\n\n${authorNote}\n\n` +
'1. Required CI checks pass.\n' +
'2. The workflow starts CodeRabbit automatically.\n' +
'3. For eligible human-authored PRs, CodeRabbit reviews and approves the latest commit.\n' +
'4. A human maintainer reviews and approves after CodeRabbit.\n\n' +
`**Current step:** ${phaseMessage(phase)}${labelMarker}`;
const phaseHelp = phase === 'coderabbit-changes'
? '\n\nAfter fixes are pushed and required CI passes, automated review restarts.'
: phase === 'coderabbit'
? '\n\nIf automated review does not start, a maintainer must restart it.'
: phase === 'maintainer' && !automatedAuthor
? '\n\nAutomated review is complete for the latest commit but does not replace human approval.'
: '';

return `${guideMarker}\n### Review status\n\n${authorNote}\n\n` +
`**Current step:** ${phaseMessage(phase)}${phaseHelp}\n\n` +
'Review-state labels are managed by this workflow; do not edit them manually.' +
labelMarker;
}

async function updateReviewGuide(pr, phase, existingGuide = null, activationPending = false) {
Expand Down Expand Up @@ -627,12 +652,12 @@ jobs:
review => review.state === 'CHANGES_REQUESTED'
);
const automatedAuthor = pr.user?.type === 'Bot';
const codeRabbitApproved = freshCodeRabbitReview?.state === 'APPROVED';
const codeRabbitReviewComplete = freshCodeRabbitReview?.state === 'APPROVED';
const codeRabbitChangesRequested = freshCodeRabbitReview?.state === 'CHANGES_REQUESTED';
const maintainerApproval = freshMaintainerReviews
.filter(review => review.state === 'APPROVED')
.sort((a, b) => b.id - a.id)[0];
const maintainerApprovedAfterCodeRabbit = codeRabbitApproved &&
const maintainerApprovedAfterAutomatedReview = codeRabbitReviewComplete &&
maintainerApproval &&
maintainerApproval.id > freshCodeRabbitReview.id;

Expand All @@ -654,7 +679,7 @@ jobs:
desiredLabel = null;
phase = 'approved';
}
} else if (!codeRabbitApproved) {
} else if (!codeRabbitReviewComplete) {
if (pr.draft) {
desiredLabel = null;
phase = 'draft';
Expand All @@ -667,7 +692,7 @@ jobs:
} else if (pr.draft) {
desiredLabel = 'awaiting-ready';
phase = 'draft-approved';
} else if (!maintainerApprovedAfterCodeRabbit) {
} else if (!maintainerApprovedAfterAutomatedReview) {
desiredLabel = 'awaiting-maintainer';
phase = 'maintainer';
} else {
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ pnpm install

### Review Process

Ready-for-review PRs must pass required CI checks, address actionable review feedback, and receive maintainer approval. Automated review may add a guidance comment and managed state labels; contributors should follow the indicated next step rather than editing those labels directly. New commits may reset the review state for the updated code.
Ready-for-review PRs must pass required CI checks, address actionable review feedback, and receive fresh maintainer or CODEOWNER approval after automated review completes for the latest commit. Automated review may add a guidance comment and managed state labels; contributors should follow the indicated next step rather than editing those labels directly. New commits reset review state for the updated code.

Automated review supports maintainers but does not replace their judgment. Warnings are advisory unless repository policy says otherwise, and native GitHub required-check and review protections remain authoritative for merging.
Automated review supports maintainers but does not replace human approval. Outside contributors cannot direct CodeRabbit through comments; eligible reviews restart automatically after required CI passes, and maintainers handle any exceptional restart. Warnings are advisory unless repository policy says otherwise, and native GitHub required-check, CODEOWNER, and review protections remain authoritative for merging.

- **Daily Triage:** Quick checks by maintainers.
- **Weekly In-depth Review:** Comprehensive assessment.
Expand Down
Loading
Loading