@@ -34,6 +34,8 @@ export interface CollectorOptions {
3434 forceSubmission ?: boolean ; // always submit snapshot for branches prior to diff
3535 submitLanguages ?: string [ ] ; // limit submission to these languages
3636 componentDetectionBinPath ?: string ; // optional path to component-detection executable
37+ snapshotIngestionDelayMs ?: number ; // delay after snapshot submission to allow ingestion before dependency review (default: 1500ms)
38+ retryIngestionDelayMs ?: number ; // delay after snapshot submission before retrying dependency review on 404 (default: 3000ms)
3739}
3840
3941export class SbomCollector {
@@ -85,7 +87,9 @@ export class SbomCollector {
8587 submitOnMissingSnapshot : o . submitOnMissingSnapshot ?? false ,
8688 forceSubmission : o . forceSubmission ?? false ,
8789 submitLanguages : o . submitLanguages ?? undefined ,
88- componentDetectionBinPath : o . componentDetectionBinPath
90+ componentDetectionBinPath : o . componentDetectionBinPath ,
91+ snapshotIngestionDelayMs : o . snapshotIngestionDelayMs ?? 1500 ,
92+ retryIngestionDelayMs : o . retryIngestionDelayMs ?? 3000
8993 } as Required < CollectorOptions > ;
9094
9195 if ( this . opts . token ) {
@@ -319,8 +323,9 @@ export class SbomCollector {
319323 try {
320324 console . debug ( chalk . blue ( `Force-submission enabled: submitting component snapshot for ${ fullName } branch ${ b . name } ...` ) ) ;
321325 if ( await submitSnapshotIfPossible ( { octokit : this . octokit , owner : org , repo : repo . name , branch : b . name , languages : this . opts . submitLanguages , quiet : this . opts . quiet , componentDetectionBinPath : this . opts . componentDetectionBinPath } ) ) {
322- // brief delay to allow snapshot ingestion
323- await new Promise ( r => setTimeout ( r , 1500 ) ) ;
326+ // Brief delay to allow GitHub to ingest the submitted snapshot before attempting dependency review.
327+ // This prevents race conditions where the review diff is requested before the snapshot is available.
328+ await new Promise ( r => setTimeout ( r , this . opts . snapshotIngestionDelayMs ) ) ;
324329 }
325330 } catch ( subErr ) {
326331 console . error ( chalk . red ( `Force submission failed for ${ fullName } branch ${ b . name } : ${ ( subErr as Error ) . message } ` ) ) ;
@@ -538,8 +543,10 @@ export class SbomCollector {
538543 try {
539544 const ok = await submitSnapshotIfPossible ( { octokit : this . octokit , owner : org , repo : repo , branch : head , languages : this . opts . submitLanguages , quiet : this . opts . quiet , componentDetectionBinPath : this . opts . componentDetectionBinPath } ) ;
540545 if ( ok ) {
541- console . log ( chalk . blue ( `Snapshot submission attempted; waiting 3 seconds before retrying dependency review diff for ${ org } /${ repo } ${ base } ...${ head } ...` ) ) ;
542- await new Promise ( r => setTimeout ( r , 3000 ) ) ;
546+ // Delay after snapshot submission to allow GitHub to ingest and process the snapshot
547+ // before retrying the dependency review API. This helps avoid 404 errors on retry.
548+ console . log ( chalk . blue ( `Snapshot submission attempted; waiting ${ this . opts . retryIngestionDelayMs } ms before retrying dependency review diff for ${ org } /${ repo } ${ base } ...${ head } ...` ) ) ;
549+ await new Promise ( r => setTimeout ( r , this . opts . retryIngestionDelayMs ) ) ;
543550 return await this . fetchDependencyReviewDiff ( org , repo , base , head , retries - 1 , latestCommit ) ;
544551 }
545552 } catch ( subErr ) {
0 commit comments