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
83 changes: 83 additions & 0 deletions .github/scripts/coderabbit_plan_trigger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Script to trigger CodeRabbit plan for intermediate and advanced issues

const marker = '<!-- CodeRabbit Plan Trigger -->';

async function triggerCodeRabbitPlan(github, owner, repo, issue, marker) {
const comment = `${marker} @coderabbitai plan`;

try {
await github.rest.issues.createComment({
owner,
repo,
issue_number: issue.number,
body: comment,
});
console.log(`Triggered CodeRabbit plan for issue #${issue.number}`);
return true;
} catch (commentErr) {
console.log(`Failed to trigger CodeRabbit plan for issue #${issue.number}:`, commentErr.message || commentErr);
return false;
}
}

function hasIntermediateOrAdvancedLabel(issue, label) {
// Check if issue has intermediate or advanced label (case-insensitive)
const hasIntermediateLabel = issue.labels?.some(l => l?.name?.toLowerCase() === 'intermediate');
const hasAdvancedLabel = issue.labels?.some(l => l?.name?.toLowerCase() === 'advanced');

// Also check if newly added label is intermediate/advanced
const isNewLabelIntermediate = label?.name?.toLowerCase() === 'intermediate';
const isNewLabelAdvanced = label?.name?.toLowerCase() === 'advanced';

return hasIntermediateLabel || hasAdvancedLabel || isNewLabelIntermediate || isNewLabelAdvanced;
}

async function hasExistingCodeRabbitPlan(github, owner, repo, issueNumber) {
// Check for existing CodeRabbit plan comment (limited to first 500 comments)
const comments = [];
const iterator = github.paginate.iterator(github.rest.issues.listComments, {
owner, repo, issue_number: issueNumber, per_page: 100
});

let count = 0;
for await (const { data: page } of iterator) {
comments.push(...page);
count += page.length;
if (count >= 500) break; // Hard upper bound to prevent unbounded pagination
}

return comments.some(c => c.body?.includes('@coderabbitai plan'));
}

function logSummary(owner, repo, issue) {
console.log('=== Summary ===');
console.log(`Repository: ${owner}/${repo}`);
console.log(`Issue Number: ${issue.number}`);
console.log(`Issue Title: ${issue.title || '(no title)'}`);
console.log(`Labels: ${issue.labels?.map(l => l.name).join(', ') || 'none'}`);
}

module.exports = async ({ github, context }) => {
try {
const { owner, repo } = context.repo;
const { issue, label } = context.payload;

// Validations
if (!issue?.number) return console.log('No issue in payload');

if (!hasIntermediateOrAdvancedLabel(issue, label)) {
return console.log('Issue does not have intermediate or advanced label');
}

if (await hasExistingCodeRabbitPlan(github, owner, repo, issue.number)) {
return console.log(`CodeRabbit plan already triggered for #${issue.number}`);
}

// Post CodeRabbit plan trigger
await triggerCodeRabbitPlan(github, owner, repo, issue, marker);

logSummary(owner, repo, issue);
} catch (err) {
console.log('❌ Error:', err.message);
}
};
43 changes: 43 additions & 0 deletions .github/workflows/bot-coderabbit-plan-trigger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow automatically triggers CodeRabbit's plan feature for intermediate and advanced issues.
name: CodeRabbit Plan Trigger
on:
issues:
types: [opened, labeled]

permissions:
issues: write
contents: read

jobs:
coderabbit_plan_trigger:
runs-on: ubuntu-latest
concurrency:
group: coderabbit-plan-${{ github.event.issue.number }}
cancel-in-progress: false
# Only run for issues labeled with 'intermediate' or 'advanced' (case-insensitive)
if: >
(github.event_name == 'issues' && (
contains(github.event.issue.labels.*.name, 'intermediate') ||
contains(github.event.issue.labels.*.name, 'advanced') ||
contains(github.event.issue.labels.*.name, 'Intermediate') ||
contains(github.event.issue.labels.*.name, 'Advanced') ||
(github.event.label && (github.event.label.name == 'intermediate' || github.event.label.name == 'advanced' || github.event.label.name == 'Intermediate' || github.event.label.name == 'Advanced'))
))

steps:
- name: Harden the runner
uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with:
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1

- name: Trigger CodeRabbit Plan
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0
with:
script: |
const script = require('./.github/scripts/coderabbit_plan_trigger.js');
await script({ github, context});
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Added method chaining examples to the developer training guide (`docs/sdk_developers/training/coding_token_transactions.md`) (#1194)
- Added documentation explaining how to pin GitHub Actions to specific commit SHAs (`docs/sdk_developers/how-to-pin-github-actions.md`)(#1211)
- examples/mypy.ini for stricter type checking in example scripts
- Formatted examples/tokens directory using black code formatter for consistent code style
- Added `.github/workflows/bot-coderabbit-plan-trigger.yml` to automatically invoke CodeRabbit's plan feature on intermediate and advanced issues, providing implementation guidance to help contributors assess complexity and understand requirements. (#1289)
- Added a GitHub Actions workflow that reminds contributors to link pull requests to issues.
- Added `__str__` and `__repr__` methods to `AccountInfo` class for improved logging and debugging experience (#1098)
- Added Good First Issue (GFI) management and frequency documentation to clarify maintainer expectations and SDK-level GFI governance.
Expand Down