Skip to content

Commit 4efe35e

Browse files
committed
Add more delays to processing
1 parent a502377 commit 4efe35e

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

src/componentSubmission.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ export interface SubmitOpts {
2323
quiet?: boolean;
2424
languages?: string[];
2525
componentDetectionBinPath?: string; // optional path to component-detection executable
26+
lightDelayMs?: number;
2627
}
2728

28-
export async function getLanguageIntersection(octokit: Octokit, owner: string, repo: string, languages: string[] | undefined, quiet: boolean = false): Promise<string[]> {
29+
export async function getLanguageIntersection(octokit: Octokit, owner: string, repo: string, languages: string[] | undefined, quiet: boolean = false, lightDelayMs: number = 0): Promise<string[]> {
2930
const langResp = await octokit.request('GET /repos/{owner}/{repo}/languages', { owner, repo });
31+
32+
await new Promise(r => setTimeout(r, lightDelayMs));
33+
3034
const repoLangs = Object.keys(langResp.data || {});
3135
const wanted = languages;
3236
const intersect = wanted ? repoLangs.filter(l => wanted.some(w => w.toLowerCase() === l.toLowerCase())) : repoLangs;
@@ -37,7 +41,7 @@ export async function getLanguageIntersection(octokit: Octokit, owner: string, r
3741
return intersect;
3842
}
3943

40-
export async function sparseCheckout(owner: string, repo: string, branch: string, destDir: string, intersect: string[], baseUrl?: string) {
44+
export async function sparseCheckout(owner: string, repo: string, branch: string, destDir: string, intersect: string[], baseUrl?: string, lightDelayMs?: number) {
4145
const cwd = destDir;
4246
const repoUrl = (baseUrl && baseUrl.includes('api/v3'))
4347
? baseUrl.replace(/\/api\/v3$/, '') + `/${owner}/${repo}.git`
@@ -52,6 +56,8 @@ export async function sparseCheckout(owner: string, repo: string, branch: string
5256
await execGit(['fetch', '--depth=1', 'origin', branch], { cwd });
5357
await execGit(['checkout', 'FETCH_HEAD'], { cwd });
5458

59+
await new Promise(r => setTimeout(r, lightDelayMs));
60+
5561
const { stdout: shaOut } = await execGit(['rev-parse', 'HEAD'], { cwd: destDir });
5662
const sha = shaOut.trim();
5763
console.debug(`Checked out ${owner}/${repo}@${branch} to ${destDir} at commit ${sha}`);
@@ -66,22 +72,22 @@ export async function submitSnapshotIfPossible(opts: SubmitOpts): Promise<boolea
6672
const tmp = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'cd-submission-'));
6773

6874
try {
69-
const intersect = await getLanguageIntersection(opts.octokit, opts.owner, opts.repo, opts.languages);
75+
const intersect = await getLanguageIntersection(opts.octokit, opts.owner, opts.repo, opts.languages, opts.quiet, opts.lightDelayMs);
7076
// Create temp dir and sparse checkout only manifest files according to selected languages
7177
if (!intersect.length) {
7278
// No matching languages, skip submission
7379
return true;
7480
}
7581
console.debug(chalk.green(`Sparse checkout into ${tmp} for languages: ${intersect.join(', ')}`));
7682

77-
const sha = await sparseCheckout(opts.owner, opts.repo, opts.branch, tmp, intersect, opts.baseUrl);
83+
const sha = await sparseCheckout(opts.owner, opts.repo, opts.branch, tmp, intersect, opts.baseUrl, opts.lightDelayMs);
7884

7985
// Run the ComponentDetection module to detect components and submit snapshot
8086
if (!sha) {
8187
if (!opts.quiet) console.error(chalk.red(`Failed to determine SHA for ${opts.owner}/${opts.repo} on branch ${opts.branch}`));
8288
return false;
8389
}
84-
return await run(opts.octokit, tmp, opts.owner, opts.repo, sha, opts.branch, opts.componentDetectionBinPath);
90+
return await runComponentDetectionAndSubmit(opts.octokit, tmp, opts.owner, opts.repo, sha, opts.branch, opts.componentDetectionBinPath);
8591

8692
} catch (e) {
8793
if (!opts.quiet) console.error(chalk.red(`Component Detection failed: ${(e as Error).message}`));
@@ -150,7 +156,7 @@ async function execGit(args: string[], opts: { cwd: string, quiet?: boolean }):
150156
});
151157
}
152158

153-
export async function run(octokit: Octokit, tmpDir: string, owner: string, repo: string, sha: string, ref: string, componentDetectionBinPath?: string): Promise<boolean> {
159+
export async function runComponentDetectionAndSubmit(octokit: Octokit, tmpDir: string, owner: string, repo: string, sha: string, ref: string, componentDetectionBinPath?: string): Promise<boolean> {
154160

155161
const componentDetection = new ComponentDetection(octokit, '', componentDetectionBinPath);
156162

src/sbomCollector.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,17 +300,24 @@ export class SbomCollector {
300300

301301
try {
302302
const branches = await this.listBranches(org, repo.name);
303+
304+
if (this.opts.lightDelayMs) await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
305+
303306
const nonDefault = branches.filter(b => b.name !== sbom.defaultBranch);
304307
const limited = this.opts.branchLimit && this.opts.branchLimit > 0 ? nonDefault.slice(0, this.opts.branchLimit) : nonDefault;
305308
const branchDiffs: Map<string, BranchDependencyDiff> = new Map();
306309
for (const b of limited) {
307310

308311
// get the commits, compare to the stored diff info. If the latest commit is newer, then fetch diff, otherwise skip
309312
const latestCommit = await this.getLatestCommit(org, repo.name, b.name);
313+
314+
if (this.opts.lightDelayMs) await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
315+
310316
if (!latestCommit) {
311317
console.error(chalk.red(`Failed to get latest commit for ${fullName} branch ${b.name}.`));
312318
continue;
313319
}
320+
314321
const existing = sbom.branchDiffs instanceof Map ? sbom.branchDiffs.get(b.name) : undefined;
315322
if (await this.isCommitNewer(latestCommit, existing) || this.opts.forceSubmission) {
316323
console.debug(chalk.green(`Fetching branch diff for ${fullName} branch ${b.name}...`));
@@ -326,7 +333,6 @@ export class SbomCollector {
326333
const base = this.opts.branchDiffBase || sbom?.defaultBranch;
327334
if (!base) { console.error(chalk.red(`Cannot compute branch diff for ${fullName} branch ${b.name} because base branch is undefined.`)); continue; }
328335

329-
if (this.opts.lightDelayMs) await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
330336
// Optionally perform dependency submission up front for the branch
331337
if (this.opts.forceSubmission) {
332338
try {
@@ -357,7 +363,7 @@ export class SbomCollector {
357363
if (sbom && !sbom.error && this.opts.loadFromDir && this.opts.syncSboms && this.opts.loadFromDir.length) {
358364
try { writeOne(sbom, { outDir: this.opts.loadFromDir }); } catch { /* ignore write errors */ }
359365
}
360-
366+
361367
if (sbom) {
362368
newSboms.push(sbom);
363369
}
@@ -382,6 +388,9 @@ export class SbomCollector {
382388
if (!this.octokit) throw new Error("No Octokit instance");
383389
try {
384390
const resp = await this.octokit.request("GET /repos/{owner}/{repo}/commits", { owner: org, repo, sha: branch });
391+
392+
await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
393+
385394
const commitSha = resp.data?.[0]?.sha;
386395
const commitDate = resp.data?.[0]?.commit?.author?.date;
387396
return { sha: commitSha, commitDate };
@@ -434,6 +443,9 @@ export class SbomCollector {
434443
while (!done) {
435444
try {
436445
const resp = await this.octokit.request("GET /orgs/{org}/repos", { org, per_page, page, type: this.opts.includePrivate ? "all" : "public" });
446+
447+
await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
448+
437449
const items = resp.data as Array<{ name: string; pushed_at?: string; updated_at?: string; default_branch?: string }>;
438450
for (const r of items) {
439451
repos.push({ name: r.name, pushed_at: r.pushed_at, updated_at: r.updated_at, default_branch: r.default_branch });
@@ -453,6 +465,9 @@ export class SbomCollector {
453465

454466
try {
455467
const resp = await this.octokit.request("GET /repos/{owner}/{repo}", { owner: org, repo });
468+
469+
await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
470+
456471
const data = resp.data as { name: string; pushed_at?: string; updated_at?: string; default_branch?: string };
457472
return data;
458473
} catch (e) {
@@ -466,7 +481,6 @@ export class SbomCollector {
466481

467482
const fullName = `${org}/${repo}`;
468483
try {
469-
// TODO: Ensure dependency graph is enabled before requesting SBOM
470484
const resp = await this.octokit.request("GET /repos/{owner}/{repo}/dependency-graph/sbom", { owner: org, repo, headers: { Accept: "application/vnd.github+json" } });
471485
const sbomWrapper = resp.data as { sbom?: Sbom };
472486
const packages: SbomPackage[] = sbomWrapper?.sbom?.packages ?? [];
@@ -505,6 +519,8 @@ export class SbomCollector {
505519
while (!done) {
506520
try {
507521
const resp = await this.octokit.request("GET /repos/{owner}/{repo}/branches", { owner: org, repo, per_page, page });
522+
await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
523+
508524
const data = resp.data as Array<{ name: string; protected?: boolean; commit?: { sha?: string } }>;
509525
branches.push(...data);
510526
if (data.length < per_page) done = true; else page++;
@@ -523,6 +539,8 @@ export class SbomCollector {
523539
try {
524540
const basehead = `${base}...${head}`;
525541
const resp = await this.octokit.request("GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}", { owner: org, repo, basehead, headers: { Accept: "application/vnd.github+json" } });
542+
await new Promise(r => setTimeout(r, this.opts.lightDelayMs));
543+
526544
// Response shape includes change_set array (per docs). We normalize to DependencyReviewPackageChange[]
527545
const raw = resp.data;
528546

0 commit comments

Comments
 (0)