11import { getOctokit } from '@/lib/github' ;
22
33const COMMENT_MARKER = '<!-- ci-report-comment -->' ;
4- const SECTION_REGEX = / < ! - - s e c t i o n : ( \w + ) - - > \n ( [ \s \S ] * ?) < ! - - \/ s e c t i o n : \1 - - > / g;
5- const HEADER_REGEX = / < ! - - h e a d e r - - > \n ( [ \s \S ] * ?) < ! - - \/ h e a d e r - - > / ;
6- const FOOTER_REGEX = / < ! - - f o o t e r - - > \n ( [ \s \S ] * ?) < ! - - \/ f o o t e r - - > / ;
7-
8- function parseSections ( body : string ) : Record < string , string > {
9- const sections : Record < string , string > = { } ;
10- for ( const match of body . matchAll ( SECTION_REGEX ) ) {
11- sections [ match [ 1 ] ] = match [ 2 ] . trim ( ) ;
12- }
13- return sections ;
14- }
15-
16- function parseHeader ( body : string ) : string | null {
17- const match = HEADER_REGEX . exec ( body ) ;
18- return match ? match [ 1 ] . trim ( ) : null ;
19- }
20-
21- function parseFooter ( body : string ) : string | null {
22- const match = FOOTER_REGEX . exec ( body ) ;
23- return match ? match [ 1 ] . trim ( ) : null ;
24- }
25-
26- function renderComment (
27- header : string | null ,
28- sections : Record < string , string > ,
29- footer : string | null ,
30- ) : string {
31- const parts : string [ ] = [ COMMENT_MARKER ] ;
32-
33- if ( header ) {
34- parts . push ( `<!-- header -->\n${ header } \n<!-- /header -->` ) ;
35- }
36-
37- const sectionEntries = Object . entries ( sections ) ;
38- if ( sectionEntries . length > 0 ) {
39- parts . push (
40- sectionEntries
41- . map ( ( [ id , content ] ) => `<!-- section:${ id } -->\n${ content } \n<!-- /section:${ id } -->` )
42- . join ( '\n\n' ) ,
43- ) ;
44- }
45-
46- if ( footer ) {
47- parts . push ( `<!-- footer -->\n${ footer } \n<!-- /footer -->` ) ;
48- }
49-
50- return parts . join ( '\n\n' ) ;
51- }
524
535/**
546 * Recursively searches for a comment containing the comment marker.
@@ -76,32 +28,19 @@ async function findComment(owner: string, repoName: string, prNumber: number, pa
7628 return findComment ( owner , repoName , prNumber , page + 1 ) ;
7729}
7830
79- export interface UpsertPrCommentOptions {
80- header ?: string ;
81- footer ?: string ;
82- defaultSections ?: Record < string , string > ;
83- }
84-
8531const pendingUpdates = new Map < string , Promise < void > > ( ) ;
8632
8733/**
88- * Creates or updates a comment on a pull request with section-based content.
89- * Each section is independently updatable — only the provided sections are
90- * modified, others are preserved.
34+ * Creates or updates the CI report comment on a pull request.
9135 *
9236 * Concurrent calls for the same PR are serialized to prevent race conditions.
9337 */
94- export function upsertPrComment (
95- repo : string ,
96- prNumber : number ,
97- sections : Record < string , string > ,
98- options ?: UpsertPrCommentOptions ,
99- ) : Promise < void > {
38+ export function upsertPrComment ( repo : string , prNumber : number , body : string ) : Promise < void > {
10039 const key = `${ repo } /${ prNumber } ` ;
10140 const prev = pendingUpdates . get ( key ) ?? Promise . resolve ( ) ;
10241 const next = prev
10342 . catch ( ( ) => { } )
104- . then ( ( ) => doUpsert ( repo , prNumber , sections , options ) )
43+ . then ( ( ) => doUpsert ( repo , prNumber , body ) )
10544 . finally ( ( ) => {
10645 if ( pendingUpdates . get ( key ) === next ) {
10746 pendingUpdates . delete ( key ) ;
@@ -111,12 +50,7 @@ export function upsertPrComment(
11150 return next ;
11251}
11352
114- async function doUpsert (
115- repo : string ,
116- prNumber : number ,
117- sections : Record < string , string > ,
118- options ?: UpsertPrCommentOptions ,
119- ) : Promise < void > {
53+ async function doUpsert ( repo : string , prNumber : number , body : string ) : Promise < void > {
12054 const [ owner , repoName ] = repo . split ( '/' ) ;
12155
12256 if ( ! owner || ! repoName ) {
@@ -125,32 +59,21 @@ async function doUpsert(
12559
12660 const octokit = getOctokit ( ) ;
12761 const existingComment = await findComment ( owner , repoName , prNumber ) ;
62+ const commentBody = `${ COMMENT_MARKER } \n\n${ body } ` ;
12863
12964 if ( existingComment ) {
130- const existingBody = existingComment . body ?? '' ;
131- const existingSections = parseSections ( existingBody ) ;
132- const mergedSections = {
133- ...options ?. defaultSections ,
134- ...existingSections ,
135- ...sections ,
136- } ;
137- const mergedHeader = options ?. header ?? parseHeader ( existingBody ) ;
138- const mergedFooter = options ?. footer ?? parseFooter ( existingBody ) ;
139-
14065 await octokit . issues . updateComment ( {
14166 owner,
14267 repo : repoName ,
14368 comment_id : existingComment . id ,
144- body : renderComment ( mergedHeader , mergedSections , mergedFooter ) ,
69+ body : commentBody ,
14570 } ) ;
14671 } else {
147- const mergedSections = { ...options ?. defaultSections , ...sections } ;
148-
14972 await octokit . issues . createComment ( {
15073 owner,
15174 repo : repoName ,
15275 issue_number : prNumber ,
153- body : renderComment ( options ?. header ?? null , mergedSections , options ?. footer ?? null ) ,
76+ body : commentBody ,
15477 } ) ;
15578 }
15679}
0 commit comments