@@ -22,17 +22,11 @@ type ResolvedCommitInformation = {
22
22
type UnresolvedRepoInformation = Omit < ResolvedCommitInformation , 'commit' > &
23
23
Partial < ResolvedCommitInformation > & { packageVersion ?: string } ;
24
24
25
- const octokit = new Octokit ( {
26
- auth : process . env . GITHUB_TOKEN ,
27
- request : { fetch } ,
28
- } ) ;
29
-
30
25
// Get CodeQL SARIF reports for a single commit in a single repository
31
- async function getSingleCommitSarif ( {
32
- owner,
33
- repo,
34
- commit,
35
- } : ResolvedCommitInformation ) : Promise < unknown [ ] > {
26
+ async function getSingleCommitSarif (
27
+ octokit : Octokit ,
28
+ { owner, repo, commit } : ResolvedCommitInformation
29
+ ) : Promise < unknown [ ] > {
36
30
const reportIds = new Set < number > ( ) ;
37
31
for ( let page = 0 ; ; page ++ ) {
38
32
const { data } = await octokit . codeScanning . listRecentAnalyses ( {
@@ -76,14 +70,14 @@ function repoForPackageJSON(
76
70
: packageJson . repository ?. url ;
77
71
if ( ! repoUrl )
78
72
throw new Error (
79
- `Could not find repostiory information for package.json file at ${ atPath } `
73
+ `Could not find repository information for package.json file at ${ atPath } `
80
74
) ;
81
75
const { owner, repo } =
82
76
repoUrl . match ( / g i t h u b \. c o m \/ (?< owner > [ ^ / ] + ) \/ (?< repo > [ ^ / . ] + ) (?: .g i t ) ? $ / )
83
77
?. groups ?? { } ;
84
78
if ( ! owner || ! repo )
85
79
throw new Error (
86
- `Could not parse repostiory information for package.json file at ${ atPath } `
80
+ `Could not parse repository information for package.json file at ${ atPath } `
87
81
) ;
88
82
return { owner, repo } ;
89
83
}
@@ -119,6 +113,7 @@ declare class AggregateError {
119
113
120
114
// Look up the commit associated with a given tag
121
115
async function resolveVersionSpecifier (
116
+ octokit : Octokit ,
122
117
repo : UnresolvedRepoInformation
123
118
) : Promise < ResolvedCommitInformation > {
124
119
if ( repo . commit ) {
@@ -195,57 +190,58 @@ async function getCurrentRepo(): Promise<ResolvedCommitInformation> {
195
190
return { ...repo , commit } ;
196
191
}
197
192
198
- async function fetchCodeQLResults ( {
199
- dependencyFiles,
200
- excludeRepos,
201
- currentRepo,
202
- sarifDest,
203
- } : {
204
- dependencyFiles : string [ ] ;
205
- excludeRepos : string [ ] ;
206
- currentRepo ?: Partial < ResolvedCommitInformation > ;
207
- sarifDest : string ;
208
- } ) {
193
+ export async function fetchCodeQLResults (
194
+ octokit : Octokit ,
195
+ {
196
+ dependencyFiles,
197
+ excludeRepos,
198
+ currentRepo,
199
+ } : {
200
+ dependencyFiles : string [ ] ;
201
+ excludeRepos : string [ ] ;
202
+ currentRepo ?: Partial < ResolvedCommitInformation > ;
203
+ }
204
+ ) : Promise < unknown > {
209
205
if ( ! dependencyFiles ?. length ) {
210
206
throw new Error ( 'Missing required argument: --dependencies' ) ;
211
207
}
212
- if ( ! sarifDest ) {
213
- throw new Error ( 'Missing required argument: --sarif-dest' ) ;
214
- }
215
208
209
+ // Add the current repository we're in to the list of repos to be scanned
216
210
let resolvedCurrentRepo : ResolvedCommitInformation ;
217
211
if ( ! currentRepo ?. owner || ! currentRepo . repo || ! currentRepo . commit ) {
218
212
resolvedCurrentRepo = { ...( await getCurrentRepo ( ) ) , ...currentRepo } ;
219
213
} else {
220
214
resolvedCurrentRepo = currentRepo as ResolvedCommitInformation ;
221
215
}
222
216
let repos = await listFirstPartyDependencies ( dependencyFiles ) ;
217
+ // Make sure the only entry for the current repo is the one we explicitly add
223
218
excludeRepos . push ( `${ resolvedCurrentRepo . owner } /${ resolvedCurrentRepo . repo } ` ) ;
224
219
repos = repos . filter (
225
220
( repo ) => ! excludeRepos . includes ( `${ repo . owner } /${ repo . repo } ` )
226
221
) ;
227
222
repos . push ( resolvedCurrentRepo ) ;
228
223
repos = deduplicateArray ( repos ) ;
229
224
let resolvedRepos = await Promise . all (
230
- repos . map ( async ( repo ) => await resolveVersionSpecifier ( repo ) )
225
+ repos . map ( async ( repo ) => await resolveVersionSpecifier ( octokit , repo ) )
231
226
) ;
227
+ // scan each [owner, repo, commit] triple only once, even if it appears for e.g. multiple packages
232
228
resolvedRepos = deduplicateArray ( resolvedRepos , [ 'owner' , 'repo' , 'commit' ] ) ;
233
229
234
230
const sarifs = (
235
231
await Promise . all (
236
232
resolvedRepos . map ( async ( repo ) => {
237
233
try {
238
- const reports = await getSingleCommitSarif ( repo ) ;
234
+ const reports = await getSingleCommitSarif ( octokit , repo ) ;
239
235
if ( reports . length === 0 ) {
240
236
throw new Error ( 'Could not find any reports' ) ;
241
237
}
242
238
return reports ;
243
239
} catch ( err : unknown ) {
244
- // @ts -expect-error 'cause' unsupported
245
240
throw new Error (
246
241
`Failed to get SARIF for repository ${ JSON . stringify (
247
242
repo
248
243
) } : ${ String ( err ) } `,
244
+ // @ts -expect-error 'cause' unsupported
249
245
{ cause : err }
250
246
) ;
251
247
}
@@ -316,7 +312,7 @@ async function fetchCodeQLResults({
316
312
timestamp : new Date ( ) . toISOString ( ) ,
317
313
} ,
318
314
} ;
319
- await fs . writeFile ( sarifDest , JSON . stringify ( finalReport , null , 2 ) ) ;
315
+ return finalReport ;
320
316
}
321
317
322
318
function commaSeparatedList ( value : string ) {
@@ -348,10 +344,17 @@ export const command = new Command('fetch-codeql-results')
348
344
)
349
345
. option ( '--sarif-dest <file>' , 'JSON SARIF file output' )
350
346
. action ( async ( options ) => {
351
- await fetchCodeQLResults ( {
352
- dependencyFiles : options . dependencies ,
347
+ const octokit = new Octokit ( {
348
+ auth : process . env . GITHUB_TOKEN ,
349
+ request : { fetch } ,
350
+ } ) ;
351
+ if ( ! options . sarifDest ) {
352
+ throw new Error ( 'Missing required argument: --sarif-dest' ) ;
353
+ }
354
+ const finalReport = await fetchCodeQLResults ( octokit , {
355
+ dependencyFiles : options . despendencies ,
353
356
excludeRepos : options . excludeRepos ,
354
357
currentRepo : options . currentRepo ,
355
- sarifDest : options . sarifDest ,
356
358
} ) ;
359
+ await fs . writeFile ( options . sarifDest , JSON . stringify ( finalReport , null , 2 ) ) ;
357
360
} ) ;
0 commit comments