11// Script to trigger CodeRabbit plan for intermediate and advanced issues
22
3- const marker = '<!-- CodeRabbit Plan Trigger -->' ;
3+ const CODERABBIT_MARKER = '<!-- CodeRabbit Plan Trigger -->' ;
44
5- async function triggerCodeRabbitPlan ( github , owner , repo , issue , marker ) {
5+ async function triggerCodeRabbitPlan ( github , owner , repo , issue , marker = CODERABBIT_MARKER ) {
66 const comment = `${ marker } @coderabbitai plan` ;
77
88 try {
@@ -15,41 +15,64 @@ async function triggerCodeRabbitPlan(github, owner, repo, issue, marker) {
1515 console . log ( `Triggered CodeRabbit plan for issue #${ issue . number } ` ) ;
1616 return true ;
1717 } catch ( commentErr ) {
18- console . log ( `Failed to trigger CodeRabbit plan for issue #${ issue . number } :` , commentErr . message || commentErr ) ;
18+ console . log ( 'Failed to trigger CodeRabbit plan:' , {
19+ message : commentErr ?. message ,
20+ status : commentErr ?. status ,
21+ owner,
22+ repo,
23+ issueNumber : issue ?. number ,
24+ } ) ;
1925 return false ;
2026 }
2127}
2228
2329function hasBeginnerOrHigherLabel ( issue , label ) {
2430 // Check if issue has beginner, intermediate or advanced label (case-insensitive)
25-
26- const allowed = [ 'beginner' , 'intermediate' , "advanced" ] ;
31+ const allowed = [ 'beginner' , 'intermediate' , 'advanced' ] ;
2732
2833 const hasAllowedLabel = issue . labels ?. some ( l => allowed . includes ( l ?. name ?. toLowerCase ( ) ) ) ;
2934
30- // Also check if newly added label is intermediate/advanced
31-
35+ // Also check if newly added label is beginner/intermediate/advanced
3236 const isNewLabelAllowed = allowed . includes ( label ?. name ?. toLowerCase ( ) ) ;
3337
3438 return hasAllowedLabel || isNewLabelAllowed ;
35-
3639}
3740
3841async function hasExistingCodeRabbitPlan ( github , owner , repo , issueNumber ) {
3942 // Check for existing CodeRabbit plan comment (limited to first 500 comments)
40- const comments = [ ] ;
41- const iterator = github . paginate . iterator ( github . rest . issues . listComments , {
42- owner, repo, issue_number : issueNumber , per_page : 100
43- } ) ;
44-
45- let count = 0 ;
46- for await ( const { data : page } of iterator ) {
47- comments . push ( ...page ) ;
48- count += page . length ;
49- if ( count >= 500 ) break ; // Hard upper bound to prevent unbounded pagination
43+ // Uses marker-based detection to avoid false positives from quoted text
44+ try {
45+ const comments = [ ] ;
46+ const iterator = github . paginate . iterator ( github . rest . issues . listComments , {
47+ owner,
48+ repo,
49+ issue_number : issueNumber ,
50+ per_page : 100 ,
51+ } ) ;
52+
53+ let count = 0 ;
54+ for await ( const { data : page } of iterator ) {
55+ comments . push ( ...page ) ;
56+ count += page . length ;
57+ if ( count >= 500 ) break ; // Hard upper bound to prevent unbounded pagination
58+ }
59+
60+ // Check for marker-based comment OR @coderabbitai plan text
61+ return comments . some ( c =>
62+ typeof c ?. body === 'string' &&
63+ ( c . body . includes ( CODERABBIT_MARKER ) || c . body . includes ( '@coderabbitai plan' ) )
64+ ) ;
65+ } catch ( error ) {
66+ console . log ( 'Failed to check existing CodeRabbit plan comments:' , {
67+ message : error ?. message ,
68+ status : error ?. status ,
69+ owner,
70+ repo,
71+ issueNumber,
72+ } ) ;
73+ // Return false to allow plan trigger attempt (fail-open for better UX)
74+ return false ;
5075 }
51-
52- return comments . some ( c => c . body ?. includes ( '@coderabbitai plan' ) ) ;
5376}
5477
5578function logSummary ( owner , repo , issue ) {
@@ -60,27 +83,42 @@ function logSummary(owner, repo, issue) {
6083 console . log ( `Labels: ${ issue . labels ?. map ( l => l . name ) . join ( ', ' ) || 'none' } ` ) ;
6184}
6285
63- module . exports = async ( { github, context } ) => {
86+ // Main workflow handler (default export for workflow usage)
87+ async function main ( { github, context } ) {
6488 try {
6589 const { owner, repo } = context . repo ;
6690 const { issue, label } = context . payload ;
6791
6892 // Validations
6993 if ( ! issue ?. number ) return console . log ( 'No issue in payload' ) ;
70-
94+
7195 if ( ! hasBeginnerOrHigherLabel ( issue , label ) ) {
72- return console . log ( 'Issue does not have intermediate or advanced label' ) ;
96+ return console . log ( 'Issue does not have beginner/ intermediate/ advanced label' ) ;
7397 }
7498
7599 if ( await hasExistingCodeRabbitPlan ( github , owner , repo , issue . number ) ) {
76100 return console . log ( `CodeRabbit plan already triggered for #${ issue . number } ` ) ;
77101 }
78102
79103 // Post CodeRabbit plan trigger
80- await triggerCodeRabbitPlan ( github , owner , repo , issue , marker ) ;
104+ await triggerCodeRabbitPlan ( github , owner , repo , issue , CODERABBIT_MARKER ) ;
81105
82106 logSummary ( owner , repo , issue ) ;
83107 } catch ( err ) {
84- console . log ( '❌ Error:' , err . message ) ;
108+ console . log ( '❌ Error:' , {
109+ message : err ?. message ,
110+ status : err ?. status ,
111+ owner : context ?. repo ?. owner ,
112+ repo : context ?. repo ?. repo ,
113+ issueNumber : context ?. payload ?. issue ?. number ,
114+ } ) ;
85115 }
86- } ;
116+ }
117+
118+ // Default export for workflow usage: await script({ github, context })
119+ module . exports = main ;
120+
121+ // Named exports for reuse by other scripts (e.g., GFI assignment bot)
122+ module . exports . triggerCodeRabbitPlan = triggerCodeRabbitPlan ;
123+ module . exports . hasExistingCodeRabbitPlan = hasExistingCodeRabbitPlan ;
124+ module . exports . CODERABBIT_MARKER = CODERABBIT_MARKER ;
0 commit comments