@@ -14,11 +14,6 @@ const ALERT_TYPES = {
1414 codeq : 'codeql' ,
1515}
1616
17- const UPDATE_TYPE = {
18- addAlertToIssue : 'addAlertToIssue' ,
19- closeTask : 'closeTask'
20- }
21-
2217class SecurityChecker {
2318 constructor ( github , context , issueRepo ) {
2419 this . github = github ;
@@ -29,7 +24,7 @@ class SecurityChecker {
2924 } ;
3025 }
3126
32- async check ( ) {
27+ async check ( ) {
3328 const dependabotAlerts = await this . getDependabotAlerts ( ) ;
3429 const codeqlAlerts = await this . getCodeqlAlerts ( ) ;
3530 const existedIssues = await this . getExistedIssues ( ) ;
@@ -41,13 +36,13 @@ class SecurityChecker {
4136 await this . createCodeqlIssues ( codeqlAlerts ) ;
4237 }
4338
44- async getDependabotAlerts ( ) {
39+ async getDependabotAlerts ( ) {
4540 const { data } = await this . github . rest . dependabot . listAlertsForRepo ( { state : STATES . open , ...this . context } ) ;
4641
4742 return data ;
4843 }
4944
50- async getCodeqlAlerts ( ) {
45+ async getCodeqlAlerts ( ) {
5146 try {
5247 const { data } = await this . github . rest . codeScanning . listAlertsForRepo ( { state : STATES . open , ...this . context } ) ;
5348
@@ -61,7 +56,7 @@ class SecurityChecker {
6156 }
6257 }
6358
64- async getExistedIssues ( ) {
59+ async getExistedIssues ( ) {
6560 const { data : existedIssues } = await this . github . rest . issues . listForRepo ( {
6661 owner : this . context . owner ,
6762 repo : this . issueRepo ,
@@ -72,7 +67,7 @@ class SecurityChecker {
7267 return existedIssues ;
7368 }
7469
75- createAlertDictionary ( existedIssues ) {
70+ createAlertDictionary ( existedIssues ) {
7671 return existedIssues . reduce ( ( res , issue ) => {
7772 const [ , url , type ] = issue . body . match ( / ( h t t p s : .* \/ ( d e p e n d a b o t | c o d e - s c a n n i n g ) \/ ( \d + ) ) / ) ;
7873
@@ -86,40 +81,51 @@ class SecurityChecker {
8681 res . set ( issue . title , { issue, type, cveId, ghsaId } ) ;
8782 }
8883 else
89- res . set ( issue . title , { issue, type } )
90-
84+ res . set ( issue . title , { issue, type } ) ;
9185
9286 return res ;
9387 } , new Map ( ) ) ;
9488 }
9589
96- async closeSpoiledIssues ( ) {
97- const regExpAlertNumber = new RegExp ( `(?<=\`${ this . context . repo } \` - https:.*/dependabot/)\\d+` ) ;
90+ async closeSpoiledIssues ( ) {
91+ const regExpAlertNumbers = new RegExp ( `(?<=\`${ this . context . repo } \` - https:.*/dependabot/)\\d+` , 'g' ) ;
92+
9893 for ( const alert of this . alertDictionary . values ( ) ) {
9994
10095 if ( alert . type === ALERT_TYPES . dependabot ) {
101- const alertNumber = alert . issue . body . match ( regExpAlertNumber ) ;
96+ const alertNumbers = alert . issue . body . match ( regExpAlertNumbers ) ;
10297
103- if ( ! alertNumber )
98+ if ( ! alertNumbers )
10499 continue ;
105100
106- const isAlertOpened = await this . isDependabotAlertOpened ( alertNumber ) ;
101+ const updates = { } ;
102+ let changedBody = alert . issue . body ;
107103
108- if ( isAlertOpened )
109- continue ;
104+ for ( let alertNumber of alertNumbers ) {
105+ const isAlertOpened = await this . isDependabotAlertOpened ( alertNumber ) ;
110106
111- await this . updateIssue ( alert , UPDATE_TYPE . closeTask ) ;
107+ if ( isAlertOpened )
108+ continue ;
109+
110+ changedBody = changedBody . replace ( new RegExp ( `\\[ \\](?= \`${ this . context . repo } \` - https:.*/dependabot/${ alertNumber } )` ) , '[x]' ) ;
111+ }
112+
113+ updates . body = changedBody ;
114+ updates . state = ! changedBody . match ( / \[ \] / ) ? STATES . closed : STATES . open ;
115+ updates . issue_number = alert . issue . number ;
116+
117+ await this . updateIssue ( updates ) ;
112118 }
113119 }
114120 }
115121
116- async isDependabotAlertOpened ( alertNumber ) {
122+ async isDependabotAlertOpened ( alertNumber ) {
117123 const alert = await this . getDependabotAlertInfo ( alertNumber ) ;
118124
119125 return alert . state === STATES . open ;
120126 }
121127
122- async getDependabotAlertInfo ( alertNumber ) {
128+ async getDependabotAlertInfo ( alertNumber ) {
123129 try {
124130 const { data } = await this . github . rest . dependabot . getAlert ( { alert_number : alertNumber , ...this . context } ) ;
125131
@@ -133,24 +139,7 @@ class SecurityChecker {
133139 }
134140 }
135141
136- async updateIssue ( alert , type ) {
137- const updates = { } ;
138-
139- if ( type === UPDATE_TYPE . addAlertToIssue ) {
140- const { issue } = this . alertDictionary . get ( alert . security_advisory . summary ) ;
141-
142- updates . issue_number = issue . number ;
143- updates . body = issue . body . replace ( / (?< = R e p o s i t o r i e s : ) [ \s \S ] * ?(? = # # # # | $ ) / g, ( match ) => {
144- return match + `- [ ] \`${ this . context . repo } \` - ${ alert . html_url } \n` ;
145- } ) ;
146- }
147-
148- if ( type === UPDATE_TYPE . closeTask ) {
149- updates . body = alert . issue . body . replace ( new RegExp ( `\\[ \\](?= \`${ this . context . repo } \`)` ) , '[x]' ) ;
150- updates . state = ! updates . body . match ( / \[ \] / ) ? STATES . closed : STATES . open ;
151- updates . issue_number = alert . issue . number ;
152- }
153-
142+ async updateIssue ( updates ) {
154143 return this . github . rest . issues . update ( {
155144 owner : this . context . owner ,
156145 repo : this . issueRepo ,
@@ -159,10 +148,10 @@ class SecurityChecker {
159148 }
160149
161150
162- async createDependabotlIssues ( dependabotAlerts ) {
151+ async createDependabotlIssues ( dependabotAlerts ) {
163152 for ( const alert of dependabotAlerts ) {
164153 if ( this . needAddAlertToIssue ( alert ) ) {
165- await this . updateIssue ( alert , UPDATE_TYPE . addAlertToIssue ) ;
154+ await this . addAlertToIssue ( alert ) ;
166155 }
167156 else if ( this . needCreateIssue ( alert ) ) {
168157 await this . createIssue ( {
@@ -179,16 +168,31 @@ class SecurityChecker {
179168 }
180169 }
181170
182- needAddAlertToIssue ( alert ) {
183- const existedIssue = this . alertDictionary . get ( alert . security_advisory . summary ) ;
171+ needAddAlertToIssue ( alert ) {
172+ const regExpAlertNumber = new RegExp ( `(?<=\`${ this . context . repo } \` - https:.*/dependabot/)${ alert . html_url . match ( / (?< = h t t p s : .* \/ ) \d + / ) } ` ) ;
173+ const existedIssue = this . alertDictionary . get ( alert . security_advisory . summary ) ;
174+ const alertNumber = existedIssue ?. issue . body . match ( regExpAlertNumber ) ;
175+ const isAlertExisted = existedIssue ?. issue . body . includes ( `\`${ this . context . repo } \`` ) ;
184176
185177 return existedIssue
186178 && existedIssue . cveId === alert . security_advisory . cve_id
187179 && existedIssue . ghsaId === alert . security_advisory . ghsa_id
188- && ! existedIssue . issue . body . includes ( `\`${ this . context . repo } \`` ) ;
180+ && ( ! isAlertExisted || ( isAlertExisted && ! alertNumber ) ) ;
181+ }
182+
183+ async addAlertToIssue ( alert ) {
184+ const updates = { } ;
185+ const { issue } = this . alertDictionary . get ( alert . security_advisory . summary ) ;
186+
187+ updates . issue_number = issue . number ;
188+ updates . body = issue . body . replace ( / (?< = R e p o s i t o r i e s : ) [ \s \S ] * ?(? = # # # # | $ ) / g, ( match ) => {
189+ return match + `- [ ] \`${ this . context . repo } \` - ${ alert . html_url } \n` ;
190+ } ) ;
191+
192+ await this . updateIssue ( updates ) ;
189193 }
190194
191- async createCodeqlIssues ( codeqlAlerts ) {
195+ async createCodeqlIssues ( codeqlAlerts ) {
192196 for ( const alert of codeqlAlerts ) {
193197 if ( ! this . needCreateIssue ( alert , false ) )
194198 continue ;
@@ -203,13 +207,13 @@ class SecurityChecker {
203207 }
204208 }
205209
206- needCreateIssue ( alert , isDependabotAlert = true ) {
210+ needCreateIssue ( alert , isDependabotAlert = true ) {
207211 const dictionaryKey = isDependabotAlert ? alert . security_advisory . summary : `[${ this . context . repo } ] ${ alert . rule . description } ` ;
208212
209213 return ! this . alertDictionary . get ( dictionaryKey ) && Date . now ( ) - new Date ( alert . created_at ) <= 1000 * 60 * 60 * 24 ;
210214 }
211215
212- async createIssue ( { labels, originRepo, summary, description, link, issuePackage = '' , cveId, ghsaId } , isDependabotAlert = true ) {
216+ async createIssue ( { labels, originRepo, summary, description, link, issuePackage = '' , cveId, ghsaId } , isDependabotAlert = true ) {
213217 const title = isDependabotAlert ? `${ summary } ` : `[${ originRepo } ] ${ summary } ` ;
214218 let body = ''
215219 + `#### Repositories:\n`
0 commit comments