Skip to content

Commit 09cafe8

Browse files
committed
Fixed up Component Detection/Submission
1 parent 3c40bc2 commit 09cafe8

File tree

2 files changed

+50
-40
lines changed

2 files changed

+50
-40
lines changed

src/componentDetection.ts

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Octokit } from "octokit"
1+
import { Octokit } from "@octokit/core";
22
import {
33
PackageCache,
44
Package,
@@ -11,19 +11,30 @@ import path from 'path';
1111
import { tmpdir } from 'os';
1212
import { StringDecoder } from 'node:string_decoder';
1313

14-
export default class ComponentDetection {
15-
public static componentDetectionPath = process.platform === "win32" ? './component-detection.exe' : './component-detection';
16-
public static outputPath = (() => {
17-
const tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'component-detection-'));
18-
return path.join(tmpDir, 'output.json');
19-
})();
14+
export default class ComponentDetection {
15+
public componentDetectionPath: string = process.platform === "win32" ? './component-detection.exe' : './component-detection';
16+
public outputPath: string;
17+
octokit: Octokit;
18+
baseUrl: string;
2019

21-
// This is the default entry point for this class.
22-
// If executablePath is provided, use it directly and skip download.
23-
static async scanAndGetManifests(path: string, executablePath?: string): Promise<Manifest[] | undefined> {
20+
constructor(octokit: Octokit, baseUrl: string, executablePath?: string) {
21+
this.octokit = octokit;
22+
this.baseUrl = baseUrl;
2423
if (executablePath) {
2524
this.componentDetectionPath = executablePath;
26-
} else {
25+
}
26+
27+
// Set the output path
28+
this.outputPath = (() => {
29+
const tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'component-detection-'));
30+
return path.join(tmpDir, 'output.json');
31+
})();
32+
}
33+
34+
// This is the default entry point for this class.
35+
// If executablePath is provided, use it directly and skip download.
36+
async scanAndGetManifests(path: string): Promise<Manifest[] | undefined> {
37+
if (!this.componentDetectionPath) {
2738
await this.downloadLatestRelease();
2839
}
2940

@@ -37,7 +48,7 @@ export default class ComponentDetection {
3748
return await this.getManifestsFromResults(this.outputPath, path);
3849
}
3950
// Get the latest release from the component-detection repo, download the tarball, and extract it
40-
public static async downloadLatestRelease() {
51+
public async downloadLatestRelease() {
4152
try {
4253
const statResult = fs.statSync(this.componentDetectionPath);
4354
if (statResult && statResult.isFile()) {
@@ -64,7 +75,7 @@ export default class ComponentDetection {
6475
}
6576

6677
// Run the component-detection CLI on the path specified
67-
public static runComponentDetection(path: string): Promise<boolean> {
78+
public runComponentDetection(path: string): Promise<boolean> {
6879
console.debug(`Running component-detection on ${path}`);
6980

7081
console.debug(`Writing to output file: ${this.outputPath}`);
@@ -105,7 +116,7 @@ export default class ComponentDetection {
105116
});
106117
}
107118

108-
public static async getManifestsFromResults(file: string, path: string): Promise<Manifest[] | undefined> {
119+
public async getManifestsFromResults(file: string, path: string): Promise<Manifest[] | undefined> {
109120
console.debug(`Reading results from ${file}`);
110121
const results = await fs.readFileSync(file, 'utf8');
111122
const json: any = JSON.parse(results);
@@ -115,7 +126,7 @@ export default class ComponentDetection {
115126
return this.processComponentsToManifests(json.componentsFound, dependencyGraphs);
116127
}
117128

118-
public static processComponentsToManifests(componentsFound: any[], dependencyGraphs: DependencyGraphs): Manifest[] {
129+
public processComponentsToManifests(componentsFound: any[], dependencyGraphs: DependencyGraphs): Manifest[] {
119130
// Parse the result file and add the packages to the package cache
120131
const packageCache = new PackageCache();
121132
const packages: Array<ComponentDetectionPackage> = [];
@@ -196,7 +207,7 @@ export default class ComponentDetection {
196207
return manifests;
197208
}
198209

199-
private static addPackagesToManifests(packages: Array<ComponentDetectionPackage>, manifests: Array<Manifest>, dependencyGraphs: DependencyGraphs): void {
210+
private addPackagesToManifests(packages: Array<ComponentDetectionPackage>, manifests: Array<Manifest>, dependencyGraphs: DependencyGraphs): void {
200211
packages.forEach((pkg: ComponentDetectionPackage) => {
201212
pkg.locationsFoundAt.forEach((location: any) => {
202213
// Use the normalized path (remove leading slash if present)
@@ -277,28 +288,23 @@ export default class ComponentDetection {
277288
}
278289
}
279290

280-
private static async getLatestReleaseURL(): Promise<string> {
281-
let githubToken = process.env.GITHUB_TOKEN || "";
282-
283-
const githubAPIURL = process.env.GITHUB_API_URL || 'https://api.github.com';
284-
285-
let ghesMode = process.env.GITHUB_API_URL != githubAPIURL;
286-
// If the we're running in GHES, then use an empty string as the token
287-
if (ghesMode) {
288-
githubToken = "";
291+
private async getLatestReleaseURL(): Promise<string> {
292+
let octokit: Octokit = this.octokit;
293+
294+
if (this.baseUrl != 'https://api.github.com') {
295+
octokit = new Octokit({
296+
auth: "", request: { fetch: fetch }, log: {
297+
debug: console.debug,
298+
info: console.info,
299+
warn: console.warn,
300+
error: console.error
301+
},
302+
});
289303
}
290-
const octokit = new Octokit({
291-
auth: githubToken, baseUrl: githubAPIURL, request: { fetch: fetch }, log: {
292-
debug: console.debug,
293-
info: console.info,
294-
warn: console.warn,
295-
error: console.error
296-
},
297-
});
298304

299305
const owner = "microsoft";
300306
const repo = "component-detection";
301-
console.debug("Attempting to download latest release from " + githubAPIURL);
307+
console.debug(`Attempting to download latest release from ${owner}/${repo}`);
302308

303309
try {
304310
const latestRelease = await octokit.request("GET /repos/{owner}/{repo}/releases/latest", { owner, repo });
@@ -328,7 +334,7 @@ export default class ComponentDetection {
328334
* @param filePathInput The filePath input (relative or absolute) from the action configuration.
329335
* @returns A new DependencyGraphs object with relative path keys.
330336
*/
331-
public static normalizeDependencyGraphPaths(
337+
public normalizeDependencyGraphPaths(
332338
dependencyGraphs: DependencyGraphs,
333339
filePathInput: string
334340
): DependencyGraphs {

src/componentSubmission.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ export async function submitSnapshotIfPossible(opts: SubmitOpts): Promise<boolea
6363
throw new Error('Octokit instance is required in opts.octokit');
6464
}
6565

66+
const tmp = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'cd-submission-'));
67+
6668
try {
6769
const intersect = await getLanguageIntersection(opts.octokit, opts.owner, opts.repo, opts.languages);
6870
// Create temp dir and sparse checkout only manifest files according to selected languages
69-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'cd-submission-'));
71+
7072
console.debug(chalk.green(`Sparse checkout into ${tmp} for languages: ${intersect.join(', ')}`));
7173

7274
const sha = await sparseCheckout(opts.owner, opts.repo, opts.branch, tmp, intersect, opts.baseUrl);
@@ -81,6 +83,9 @@ export async function submitSnapshotIfPossible(opts: SubmitOpts): Promise<boolea
8183
} catch (e) {
8284
if (!opts.quiet) console.error(chalk.red(`Component Detection failed: ${(e as Error).message}`));
8385
return false;
86+
} finally {
87+
// Clean up temp dir
88+
await fs.promises.rm(tmp, { recursive: true, force: true });
8489
}
8590
}
8691

@@ -142,10 +147,9 @@ async function execGit(args: string[], opts: { cwd: string, quiet?: boolean }):
142147

143148
export async function run(octokit: Octokit, tmpDir: string, owner: string, repo: string, sha: string, ref: string, componentDetectionBinPath?: string) {
144149

145-
let manifests = await ComponentDetection.scanAndGetManifests(
146-
tmpDir,
147-
componentDetectionBinPath
148-
);
150+
const componentDetection = new ComponentDetection(octokit, '', componentDetectionBinPath);
151+
152+
let manifests = await componentDetection.scanAndGetManifests(tmpDir);
149153

150154
// Get detector configuration inputs
151155
const detectorName = "Component Detection in GitHub SBOM Toolkit: advanced-security/github-sbom-toolkit";

0 commit comments

Comments
 (0)