Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 21213e825c | |||
| 5b46420b3f | |||
| 48ae13709e | |||
| 7efb859132 | |||
| 50b9449a2f | |||
| 56ef6dcc04 | |||
| 6531c188bd | |||
| 0797d4eff6 | |||
| 7ba820f614 | |||
| bd71948983 | |||
| 630165e704 | |||
| 332c61add4 | |||
| 933761652d | |||
| 9aece0e09c | |||
| 41bb53a1db | |||
| 4f00d77f0c | |||
| 1a454445fe | |||
| cf04b7bb63 | |||
| d177d7847a | |||
| d041cfd4c5 | |||
| f7f30e1366 | |||
| 8270e9ad5f | |||
| fe72234f00 | |||
| 65d132c09c | |||
| 4407dda41e | |||
| 79573619af | |||
| 32fc958bc4 | |||
| 9c110eb34d | |||
| fe416ae93b | |||
| 1a936f4a73 | |||
| 602785199a | |||
| 386aa5c154 | |||
| 7422d90ed9 | |||
| 026ce8b4fe | |||
| 516a3ad139 | |||
| 12d34de864 | |||
| 489141f5b6 | |||
| ea95fe51c8 | |||
| c2b8a66dd5 | |||
| bbaabfd2f9 | |||
| 130f5c0c4b | |||
| 0307c61e06 | |||
| b73d1f638b | |||
| c4dbaddd5a | |||
| 51ff88ad10 | |||
| d93866d127 | |||
| 7dde1e29d3 | |||
| 98ddec4efe | |||
| 6ca39f38ce | |||
| 333866abe4 | |||
| f59e294eca | |||
| 376d6250d1 | |||
| caf2b08649 | |||
| eb91e65da4 | |||
| 3517f8f1f0 | |||
| 9b429e3d82 | |||
| d434719693 | |||
| ec00348b72 | |||
| c7cb2bbc93 | |||
| 601c613aa3 | |||
| 374343effe | |||
| 5a79ab0fa4 | |||
| 0c3e582042 | |||
| d433c2f467 | |||
| 96c59aebfe | |||
| 6dd7b2dc55 | |||
| 496691092b | |||
| e6ad22924a | |||
| 0b0b651777 | |||
| 914cb6dc5e | |||
| 28905c6bc0 | |||
| f89d41905d | |||
| 4e2fbd91ff | |||
| 6d25ae13f5 | |||
| 7d147e8b5f | |||
| 5789c204e4 | |||
| 98b7e66125 | |||
| b2779b0030 | |||
| 876b304ec0 | |||
| 3104f6d51c | |||
| 5d8c040f29 | |||
| 64db6d9d15 | |||
| a44e08867f | |||
| fc216b239a | |||
| 5b2736e4f4 | |||
| bbe83e8988 | |||
| c936885d12 | |||
| 5f4db12f7b | |||
| 466989c808 | |||
| 67f3292117 | |||
| 3f420ae88d | |||
| b242ddf67a | |||
| 3349f8c032 | |||
| 2517c7a607 | |||
| 2efc7af7df | |||
| 6d56d2b42c | |||
| 0de0af1352 | |||
| 4daccf7142 | |||
| caa69e181f | |||
| ef571d5a84 | |||
| 0eb73668fa | |||
| 7a168cbdc4 | |||
| 04aaaf6193 | |||
| 0f3b6aecc6 | |||
| 348257c874 | |||
| 779e8387fd | |||
| d5fd67e101 | |||
| 27e6d82755 | |||
| 3d11e5a0f7 | |||
| e0dcc85667 | |||
| 4f5a06217d | |||
| 81fde650c2 | |||
| 786fb5fe93 | |||
| 550b6f27ed | |||
| 51ef6b3995 |
@@ -1,8 +1,8 @@
|
||||
# Component detection dependency submission action
|
||||
|
||||
This GitHub Action runs the [microsoft/component-detection](https://github.com/microsoft/component-detection) library to automate dependency extraction at build time. It uses a combination of static and dynamic scanning to build a dependency tree and then uploads that to GitHub's dependency graph via the dependency submission API. This gives you more accurate Dependabot alerts, and support for a bunch of additional ecosystems.
|
||||
This GitHub Action runs the [microsoft/component-detection](https://github.com/microsoft/component-detection) library to automate dependency extraction at build time. It uses a combination of static and dynamic scanning to build a dependency tree and then uploads that to GitHub's dependency graph via the dependency submission API. This gives you more accurate Dependabot alerts, and support for a bunch of additional ecosystems.
|
||||
|
||||
### Example workflow
|
||||
### Example workflows
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -12,7 +12,7 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
permissions:
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
@@ -21,19 +21,47 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Component detection
|
||||
uses: advanced-security/component-detection-dependency-submission-action@v0.0.3
|
||||
```
|
||||
- name: Component detection
|
||||
uses: advanced-security/component-detection-dependency-submission-action@v0.1.1
|
||||
```
|
||||
|
||||
Additional `Experimental` and `DefaultOff` detectors:
|
||||
- For a list of experimental and default-off detectors that require explicit enablement, see the [Detectors README](https://github.com/microsoft/component-detection/blob/main/docs/detectors/README.md). See [enable-default-off.md](https://github.com/microsoft/component-detection/blob/main/docs/enable-default-off.md) for more details.
|
||||
|
||||
```yaml
|
||||
name: Component Detection
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
dependency-submission:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Component detection
|
||||
uses: advanced-security/component-detection-dependency-submission-action@v0.1.1
|
||||
with:
|
||||
# Experimental detectors: Poetry, UvLock, NpmLockfile3, Ivy
|
||||
# Default-off detectors: ConanLock, CondaLock, Dockerfile, Pip, SimplePip, Spdx22, SwiftResolved
|
||||
detectorArgs: Poetry=EnableIfDefaultOff,UvLock=EnableIfDefaultOff,NpmLockfile3=EnableIfDefaultOff,Ivy=EnableIfDefaultOff,ConanLock=EnableIfDefaultOff,CondaLock=EnableIfDefaultOff,Dockerfile=EnableIfDefaultOff,Pip=EnableIfDefaultOff,SimplePip=EnableIfDefaultOff,Spdx22=EnableIfDefaultOff,SwiftResolved=EnableIfDefaultOff
|
||||
```
|
||||
|
||||
### Configuration options
|
||||
|
||||
| Parameter | Description | Example |
|
||||
| --- | --- | --- |
|
||||
| Parameter | Description | Example |
|
||||
| --- | --- | --- |
|
||||
filePath | The path to the directory containing the environment files to upload. Defaults to Actions working directory. | `'.'`
|
||||
directoryExclusionList | Filters out specific directories following a minimatch pattern. | `test`
|
||||
detectorArgs | Comma separated list of properties that can affect the detectors execution, like EnableIfDefaultOff that allows a specific detector that is in beta to run, the format for this property is DetectorId=EnableIfDefaultOff, for example Pip=EnableIfDefaultOff. | `Pip=EnableIfDefaultOff`
|
||||
dockerImagesToScan |Comma separated list of docker image names or hashes to execute container scanning on | ubuntu:16.04,56bab49eef2ef07505f6a1b0d5bd3a601dfc3c76ad4460f24c91d6fa298369ab |
|
||||
detectorArgs | Comma separated list of properties that can affect the detectors execution, like EnableIfDefaultOff that allows a specific detector that is `Experimental` or `DefaultOff` to run, the format for this property is DetectorId=EnableIfDefaultOff, for example Pip=EnableIfDefaultOff. | `Pip=EnableIfDefaultOff`
|
||||
dockerImagesToScan |Comma separated list of docker image names or hashes to execute container scanning on | ubuntu:16.04,56bab49eef2ef07505f6a1b0d5bd3a601dfc3c76ad4460f24c91d6fa298369ab |
|
||||
detectorsFilter | A comma separated list with the identifiers of the specific detectors to be used. | `Pip, RustCrateDetector`
|
||||
detectorsCategories | A comma separated list with the categories of components that are going to be scanned. The detectors that are going to run are the ones that belongs to the categories. | `NuGet,Npm`
|
||||
correlator | An optional identifier to distinguish between multiple dependency snapshots of the same type. Defaults to the [job_id](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_id) of the current job | `csharp-backend`
|
||||
|
||||
For more information: https://github.com/microsoft/component-detection
|
||||
|
||||
+20
-3
@@ -5,7 +5,7 @@ inputs:
|
||||
description: "GitHub Personal Access Token (PAT). Defaults to PAT provided by Actions runner."
|
||||
required: false
|
||||
default: ${{ github.token }}
|
||||
filePath:
|
||||
filePath:
|
||||
description: 'The path to the directory containing the environment files to upload. Defaults to Actions working directory.'
|
||||
required: false
|
||||
default: '.'
|
||||
@@ -18,12 +18,29 @@ inputs:
|
||||
dockerImagesToScan:
|
||||
description: 'Comma separated list of docker image names or hashes to execute container scanning on, ex: ubuntu:16.04,56bab49eef2ef07505f6a1b0d5bd3a601dfc3c76ad4460f24c91d6fa298369ab'
|
||||
required: false
|
||||
detectorsFilter:
|
||||
detectorsFilter:
|
||||
description: 'A comma separated list with the identifiers of the specific detectors to be used. This is meant to be used for testing purposes only.'
|
||||
required: false
|
||||
detectorsCategories:
|
||||
description: 'A comma separated list with the categories of components that are going to be scanned. The detectors that are going to run are the ones that belongs to the categories. The possible values are: Npm, NuGet, Maven, RubyGems, Cargo, Pip, GoMod, CocoaPods, Linux.'
|
||||
required: false
|
||||
correlator:
|
||||
description: 'An optional identifier to distinguish between multiple dependency snapshots of the same type.'
|
||||
type: string
|
||||
required: false
|
||||
detector-name:
|
||||
description: 'The name of the detector. If provided, detector-version and detector-url must also be provided.'
|
||||
required: false
|
||||
detector-version:
|
||||
description: 'The version of the detector. If provided, detector-name and detector-url must also be provided.'
|
||||
required: false
|
||||
detector-url:
|
||||
description: 'The URL of the detector. If provided, detector-name and detector-version must also be provided.'
|
||||
required: false
|
||||
snapshot-sha:
|
||||
description: 'The SHA of the commit to associate with the snapshot. If provided, snapshot-ref must also be provided.'
|
||||
required: false
|
||||
snapshot-ref:
|
||||
description: 'The Git reference to associate with the snapshot. If provided, snapshot-sha must also be provided.'
|
||||
required: false
|
||||
runs:
|
||||
using: 'node20'
|
||||
|
||||
+215
-1
@@ -1,4 +1,4 @@
|
||||
import ComponentDetection from "./componentDetection";
|
||||
import ComponentDetection, { DependencyGraphs } from "./componentDetection";
|
||||
import fs from "fs";
|
||||
|
||||
test("Downloads CLI", async () => {
|
||||
@@ -68,3 +68,217 @@ describe("ComponentDetection.makePackageUrl", () => {
|
||||
expect(packageUrl).toBe("");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ComponentDetection.processComponentsToManifests", () => {
|
||||
test("adds package as direct dependency when it is listed as an explicitlyReferencedComponentIds", () => {
|
||||
const componentsFound = [
|
||||
{
|
||||
component: {
|
||||
name: "test-package",
|
||||
version: "1.0.0",
|
||||
packageUrl: {
|
||||
Scheme: "pkg",
|
||||
Type: "npm",
|
||||
Name: "test-package",
|
||||
Version: "1.0.0"
|
||||
},
|
||||
id: "test-package 1.0.0 - npm"
|
||||
},
|
||||
isDevelopmentDependency: false,
|
||||
topLevelReferrers: [], // Empty = direct dependency
|
||||
locationsFoundAt: ["package.json"]
|
||||
}
|
||||
];
|
||||
|
||||
const dependencyGraphs: DependencyGraphs = {
|
||||
"package.json": {
|
||||
graph: { "test-package": null },
|
||||
explicitlyReferencedComponentIds: ["test-package 1.0.0 - npm"],
|
||||
developmentDependencies: [],
|
||||
dependencies: []
|
||||
}
|
||||
};
|
||||
|
||||
const manifests = ComponentDetection.processComponentsToManifests(componentsFound, dependencyGraphs);
|
||||
|
||||
expect(manifests).toHaveLength(1);
|
||||
expect(manifests[0].name).toBe("package.json");
|
||||
expect(manifests[0].directDependencies()).toHaveLength(1);
|
||||
expect(manifests[0].indirectDependencies()).toHaveLength(0);
|
||||
expect(manifests[0].countDependencies()).toBe(1);
|
||||
});
|
||||
|
||||
test("adds package as indirect dependency when it is not in explicitlyReferencedComponentIds", () => {
|
||||
const componentsFound = [
|
||||
{
|
||||
component: {
|
||||
name: "test-package",
|
||||
version: "1.0.0",
|
||||
packageUrl: {
|
||||
Scheme: "pkg",
|
||||
Type: "npm",
|
||||
Name: "test-package",
|
||||
Version: "1.0.0"
|
||||
},
|
||||
id: "test-package 1.0.0 - npm"
|
||||
},
|
||||
isDevelopmentDependency: false,
|
||||
topLevelReferrers: [
|
||||
{
|
||||
name: "parent-package",
|
||||
version: "1.0.0",
|
||||
packageUrl: {
|
||||
Scheme: "pkg",
|
||||
Type: "npm",
|
||||
Name: "parent-package",
|
||||
Version: "1.0.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
locationsFoundAt: ["package.json"]
|
||||
}
|
||||
];
|
||||
|
||||
const dependencyGraphs: DependencyGraphs = {
|
||||
"package.json": {
|
||||
graph: { "parent-package": null },
|
||||
explicitlyReferencedComponentIds: [],
|
||||
developmentDependencies: [],
|
||||
dependencies: []
|
||||
}
|
||||
};
|
||||
|
||||
const manifests = ComponentDetection.processComponentsToManifests(componentsFound, dependencyGraphs);
|
||||
|
||||
expect(manifests).toHaveLength(1);
|
||||
expect(manifests[0].name).toBe("package.json");
|
||||
expect(manifests[0].directDependencies()).toHaveLength(0);
|
||||
expect(manifests[0].indirectDependencies()).toHaveLength(1);
|
||||
expect(manifests[0].countDependencies()).toBe(1);
|
||||
});
|
||||
|
||||
test("un-escapes URL-encoded locationsFoundAt", () => {
|
||||
const componentsFound = [
|
||||
{
|
||||
component: {
|
||||
name: "test-package",
|
||||
version: "1.0.0",
|
||||
packageUrl: {
|
||||
Scheme: "pkg",
|
||||
Type: "nuget",
|
||||
Name: "test-package",
|
||||
Version: "1.0.0"
|
||||
},
|
||||
id: "test-package 1.0.0 - nuget"
|
||||
},
|
||||
isDevelopmentDependency: false,
|
||||
topLevelReferrers: [], // Empty = direct dependency
|
||||
locationsFoundAt: ["/my%20project/my%20project.csproj"]
|
||||
}
|
||||
];
|
||||
|
||||
const dependencyGraphs: DependencyGraphs = {
|
||||
"my project/my project.csproj": {
|
||||
graph: { "test-package": null },
|
||||
explicitlyReferencedComponentIds: ["test-package 1.0.0 - nuget"],
|
||||
developmentDependencies: [],
|
||||
dependencies: []
|
||||
}
|
||||
};
|
||||
|
||||
const manifests = ComponentDetection.processComponentsToManifests(componentsFound, dependencyGraphs);
|
||||
|
||||
expect(manifests).toHaveLength(1);
|
||||
expect(manifests[0].name).toBe("my project/my project.csproj");
|
||||
expect(manifests[0].directDependencies()).toHaveLength(1);
|
||||
expect(manifests[0].indirectDependencies()).toHaveLength(0);
|
||||
expect(manifests[0].countDependencies()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizeDependencyGraphPaths', () => {
|
||||
test('converts absolute paths to relative paths based on filePath input', () => {
|
||||
// Simulate a repo at /repo and a scan root at /repo/packages
|
||||
const fakeCwd = '/workspaces';
|
||||
const filePathInput = 'my-super-cool-repo';
|
||||
const absBase = '/workspaces/my-super-cool-repo';
|
||||
const dependencyGraphs: DependencyGraphs = {
|
||||
'/workspaces/my-super-cool-repo/a/package.json': {
|
||||
graph: { 'foo': null },
|
||||
explicitlyReferencedComponentIds: [],
|
||||
developmentDependencies: [],
|
||||
dependencies: []
|
||||
},
|
||||
'/workspaces/my-super-cool-repo/b/package.json': {
|
||||
graph: { 'bar': null },
|
||||
explicitlyReferencedComponentIds: [],
|
||||
developmentDependencies: [],
|
||||
dependencies: []
|
||||
}
|
||||
};
|
||||
// Patch process.cwd for this test
|
||||
const originalCwd = process.cwd;
|
||||
(process as any).cwd = () => fakeCwd;
|
||||
const normalized = ComponentDetection.normalizeDependencyGraphPaths(dependencyGraphs, filePathInput);
|
||||
// Restore process.cwd
|
||||
(process as any).cwd = originalCwd;
|
||||
expect(Object.keys(normalized)).toContain('a/package.json');
|
||||
expect(Object.keys(normalized)).toContain('b/package.json');
|
||||
expect(normalized['a/package.json'].graph).toEqual({ 'foo': null });
|
||||
expect(normalized['b/package.json'].graph).toEqual({ 'bar': null });
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizeDependencyGraphPaths with real output.json', () => {
|
||||
test('converts absolute paths in output.json to relative paths using current cwd and filePath', () => {
|
||||
const output = JSON.parse(fs.readFileSync('./output.json', 'utf8'));
|
||||
const dependencyGraphs = output.dependencyGraphs;
|
||||
// Use the same filePath as the action default (".")
|
||||
const normalized = ComponentDetection.normalizeDependencyGraphPaths(dependencyGraphs, 'test');
|
||||
|
||||
// Should contain root level manifests without leading slashes
|
||||
expect(Object.keys(normalized)).toContain('package.json');
|
||||
expect(Object.keys(normalized)).toContain('package-lock.json');
|
||||
|
||||
// Should contain nested manifests with relative paths (no leading slashes)
|
||||
expect(Object.keys(normalized)).toContain('nested/package.json');
|
||||
expect(Object.keys(normalized)).toContain('nested/package-lock.json');
|
||||
|
||||
// All keys should be relative paths without leading slashes
|
||||
for (const key of Object.keys(normalized)) {
|
||||
expect(key.startsWith('/')).toBe(false); // No leading slashes
|
||||
expect(key).not.toMatch(/^\w:\\|^\/\/|^\.{1,2}\//); // Not windows absolute, not network, not relative
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('full action scan creates manifests with correct names and file source locations', async () => {
|
||||
await ComponentDetection.downloadLatestRelease();
|
||||
const manifests = await ComponentDetection.scanAndGetManifests('./test');
|
||||
|
||||
expect(manifests).toBeDefined();
|
||||
expect(manifests!.length).toBeGreaterThan(0);
|
||||
|
||||
for (const manifest of manifests!) {
|
||||
expect(manifest.name.startsWith('/')).toBe(false);
|
||||
}
|
||||
|
||||
const expectedManifestNames = [
|
||||
'package.json',
|
||||
'package-lock.json',
|
||||
'nested/package.json',
|
||||
'nested/package-lock.json',
|
||||
];
|
||||
|
||||
const manifestsByName = manifests!.reduce((acc, manifest) => {
|
||||
acc[manifest.name] = manifest;
|
||||
return acc;
|
||||
}, {} as Record<string, any>);
|
||||
|
||||
for (const expectedName of expectedManifestNames) {
|
||||
const manifest = manifestsByName[expectedName];
|
||||
expect(manifest).toBeDefined();
|
||||
expect(manifest.name).toBe(expectedName);
|
||||
expect(manifest.file?.source_location).toBe(expectedName);
|
||||
}
|
||||
}, 15000);
|
||||
|
||||
+111
-23
@@ -7,22 +7,22 @@ import {
|
||||
Package,
|
||||
Snapshot,
|
||||
Manifest,
|
||||
submitSnapshot
|
||||
submitSnapshot,
|
||||
} from '@github/dependency-submission-toolkit'
|
||||
import fetch from 'cross-fetch'
|
||||
import tar from 'tar'
|
||||
import fs from 'fs'
|
||||
import * as exec from '@actions/exec';
|
||||
import dotenv from 'dotenv'
|
||||
import { Context } from '@actions/github/lib/context'
|
||||
import { unmockedModulePathPatterns } from './jest.config'
|
||||
import path from 'path';
|
||||
dotenv.config();
|
||||
|
||||
export default class ComponentDetection {
|
||||
public static componentDetectionPath = process.platform === "win32" ? './component-detection.exe' : './component-detection';
|
||||
public static outputPath = './output.json';
|
||||
|
||||
// This is the default entry point for this class.
|
||||
// This is the default entry point for this class.
|
||||
static async scanAndGetManifests(path: string): Promise<Manifest[] | undefined> {
|
||||
await this.downloadLatestRelease();
|
||||
await this.runComponentDetection(path);
|
||||
@@ -61,20 +61,25 @@ export default class ComponentDetection {
|
||||
parameters += (core.getInput('directoryExclusionList')) ? ` --DirectoryExclusionList ${core.getInput('directoryExclusionList')}` : "";
|
||||
parameters += (core.getInput('detectorArgs')) ? ` --DetectorArgs ${core.getInput('detectorArgs')}` : "";
|
||||
parameters += (core.getInput('detectorsFilter')) ? ` --DetectorsFilter ${core.getInput('detectorsFilter')}` : "";
|
||||
parameters += (core.getInput('detectorsCategories')) ? ` --DetectorCategories ${core.getInput('detectorsCategories')}` : "";
|
||||
parameters += (core.getInput('dockerImagesToScan')) ? ` --DockerImagesToScan ${core.getInput('dockerImagesToScan')}` : "";
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public static async getManifestsFromResults(): Promise<Manifest[] | undefined> {
|
||||
core.info("Getting manifests from results");
|
||||
const results = await fs.readFileSync(this.outputPath, 'utf8');
|
||||
var json: any = JSON.parse(results);
|
||||
let dependencyGraphs: DependencyGraphs = this.normalizeDependencyGraphPaths(json.dependencyGraphs, core.getInput('filePath'));
|
||||
return this.processComponentsToManifests(json.componentsFound, dependencyGraphs);
|
||||
}
|
||||
|
||||
public static processComponentsToManifests(componentsFound: any[], dependencyGraphs: DependencyGraphs): Manifest[] {
|
||||
// Parse the result file and add the packages to the package cache
|
||||
const packageCache = new PackageCache();
|
||||
const packages: Array<ComponentDetectionPackage> = [];
|
||||
|
||||
const results = await fs.readFileSync(this.outputPath, 'utf8');
|
||||
|
||||
var json: any = JSON.parse(results);
|
||||
json.componentsFound.forEach(async (component: any) => {
|
||||
componentsFound.forEach(async (component: any) => {
|
||||
// Skip components without packageUrl
|
||||
if (!component.component.packageUrl) {
|
||||
core.debug(`Skipping component detected without packageUrl: ${JSON.stringify({
|
||||
@@ -86,7 +91,7 @@ export default class ComponentDetection {
|
||||
}
|
||||
|
||||
const packageUrl = ComponentDetection.makePackageUrl(component.component.packageUrl);
|
||||
|
||||
|
||||
// Skip if the packageUrl is empty (indicates an invalid or missing packageUrl)
|
||||
if (!packageUrl) {
|
||||
core.debug(`Skipping component with invalid packageUrl: ${component.component.id}`);
|
||||
@@ -110,17 +115,22 @@ export default class ComponentDetection {
|
||||
core.debug(`Skipping referrer without packageUrl for component: ${pkg.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const referrerUrl = ComponentDetection.makePackageUrl(referrer.packageUrl);
|
||||
|
||||
referrer.packageUrlString = referrerUrl
|
||||
|
||||
// Skip if the generated packageUrl is empty
|
||||
if (!referrerUrl) {
|
||||
core.debug(`Skipping referrer with invalid packageUrl for component: ${pkg.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const referrerPackage = packageCache.lookupPackage(referrerUrl);
|
||||
if (referrerPackage === pkg) {
|
||||
core.debug(`Skipping self-reference for package: ${pkg.id}`);
|
||||
return; // Skip self-references
|
||||
}
|
||||
if (referrerPackage) {
|
||||
referrerPackage.dependsOn(pkg);
|
||||
}
|
||||
@@ -134,20 +144,48 @@ export default class ComponentDetection {
|
||||
const manifests: Array<Manifest> = [];
|
||||
|
||||
// Check the locationsFoundAt for every package and add each as a manifest
|
||||
packages.forEach(async (pkg: ComponentDetectionPackage) => {
|
||||
pkg.locationsFoundAt.forEach(async (location: any) => {
|
||||
if (!manifests.find((manifest: Manifest) => manifest.name == location)) {
|
||||
const manifest = new Manifest(location, location);
|
||||
this.addPackagesToManifests(packages, manifests, dependencyGraphs);
|
||||
|
||||
return manifests;
|
||||
}
|
||||
|
||||
private static addPackagesToManifests(packages: Array<ComponentDetectionPackage>, manifests: Array<Manifest>, dependencyGraphs: DependencyGraphs): void {
|
||||
packages.forEach((pkg: ComponentDetectionPackage) => {
|
||||
pkg.locationsFoundAt.forEach((location: any) => {
|
||||
// Use the normalized path (remove leading slash if present)
|
||||
let normalizedLocation = location.startsWith('/') ? location.substring(1) : location;
|
||||
// Unescape the path, as upstream ComponentDetection emits locationsFoundAt in URL-encoded form
|
||||
normalizedLocation = decodeURIComponent(normalizedLocation);
|
||||
|
||||
if (!manifests.find((manifest: Manifest) => manifest.name == normalizedLocation)) {
|
||||
const manifest = new Manifest(normalizedLocation, normalizedLocation);
|
||||
manifests.push(manifest);
|
||||
}
|
||||
if (pkg.topLevelReferrers.length == 0) {
|
||||
manifests.find((manifest: Manifest) => manifest.name == location)?.addDirectDependency(pkg, ComponentDetection.getDependencyScope(pkg));
|
||||
|
||||
const depGraphEntry = dependencyGraphs[normalizedLocation];
|
||||
if (!depGraphEntry) {
|
||||
core.warning(`No dependency graph entry found for manifest location: ${normalizedLocation}`);
|
||||
return; // Skip this location if not found in dependencyGraphs
|
||||
}
|
||||
|
||||
const directDependencies = depGraphEntry.explicitlyReferencedComponentIds;
|
||||
if (directDependencies.includes(pkg.id)) {
|
||||
manifests
|
||||
.find((manifest: Manifest) => manifest.name == normalizedLocation)
|
||||
?.addDirectDependency(
|
||||
pkg,
|
||||
ComponentDetection.getDependencyScope(pkg)
|
||||
);
|
||||
} else {
|
||||
manifests.find((manifest: Manifest) => manifest.name == location)?.addIndirectDependency(pkg, ComponentDetection.getDependencyScope(pkg));
|
||||
manifests
|
||||
.find((manifest: Manifest) => manifest.name == normalizedLocation)
|
||||
?.addIndirectDependency(
|
||||
pkg,
|
||||
ComponentDetection.getDependencyScope(pkg)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
return manifests;
|
||||
}
|
||||
|
||||
private static getDependencyScope(pkg: ComponentDetectionPackage) {
|
||||
@@ -195,10 +233,10 @@ export default class ComponentDetection {
|
||||
private static async getLatestReleaseURL(): Promise<string> {
|
||||
let githubToken = core.getInput('token') || process.env.GITHUB_TOKEN || "";
|
||||
|
||||
const githubAPIURL = 'https://api.github.com'
|
||||
const githubAPIURL = 'https://api.github.com'
|
||||
|
||||
let ghesMode = github.context.apiUrl != githubAPIURL;
|
||||
// If the we're running in GHES, then use an empty string as the token
|
||||
// If the we're running in GHES, then use an empty string as the token
|
||||
if (ghesMode) {
|
||||
githubToken = "";
|
||||
}
|
||||
@@ -213,7 +251,7 @@ export default class ComponentDetection {
|
||||
const repo = "component-detection";
|
||||
core.debug("Attempting to download latest release from " + githubAPIURL);
|
||||
|
||||
try {
|
||||
try {
|
||||
const latestRelease = await octokit.request("GET /repos/{owner}/{repo}/releases/latest", {owner, repo});
|
||||
|
||||
var downloadURL: string = "";
|
||||
@@ -229,19 +267,69 @@ export default class ComponentDetection {
|
||||
core.error(error);
|
||||
core.debug(error.message);
|
||||
core.debug(error.stack);
|
||||
throw new Error("Failed to download latest release");
|
||||
throw new Error("Failed to download latest release");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the keys of a DependencyGraphs object to be relative paths from the resolved filePath input.
|
||||
* @param dependencyGraphs The DependencyGraphs object to normalize.
|
||||
* @param filePathInput The filePath input (relative or absolute) from the action configuration.
|
||||
* @returns A new DependencyGraphs object with relative path keys.
|
||||
*/
|
||||
public static normalizeDependencyGraphPaths(
|
||||
dependencyGraphs: DependencyGraphs,
|
||||
filePathInput: string
|
||||
): DependencyGraphs {
|
||||
// Resolve the base directory from filePathInput (relative to cwd if not absolute)
|
||||
const baseDir = path.resolve(process.cwd(), filePathInput);
|
||||
const normalized: DependencyGraphs = {};
|
||||
for (const absPath in dependencyGraphs) {
|
||||
// Make the path relative to the baseDir
|
||||
let relPath = path.relative(baseDir, absPath).replace(/\\/g, '/');
|
||||
normalized[relPath] = dependencyGraphs[absPath];
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentDetectionPackage extends Package {
|
||||
public packageUrlString: string;
|
||||
|
||||
constructor(packageUrl: string, public id: string, public isDevelopmentDependency: boolean, public topLevelReferrers: [],
|
||||
public locationsFoundAt: [], public containerDetailIds: [], public containerLayerIds: []) {
|
||||
super(packageUrl);
|
||||
this.packageUrlString = packageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Types for the dependencyGraphs section of output.json
|
||||
*/
|
||||
export type DependencyGraph = {
|
||||
/**
|
||||
* The dependency graph: keys are component IDs, values are either null (no dependencies) or an array of component IDs (dependencies)
|
||||
*/
|
||||
graph: Record<string, string[] | null>;
|
||||
/**
|
||||
* Explicitly referenced component IDs
|
||||
*/
|
||||
explicitlyReferencedComponentIds: string[];
|
||||
/**
|
||||
* Development dependencies
|
||||
*/
|
||||
developmentDependencies: string[];
|
||||
/**
|
||||
* Regular dependencies
|
||||
*/
|
||||
dependencies: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* The top-level dependencyGraphs object: keys are manifest file paths, values are DependencyGraph objects
|
||||
*/
|
||||
export type DependencyGraphs = Record<string, DependencyGraph>;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+34
@@ -7,7 +7,41 @@ export default class ComponentDetection {
|
||||
static runComponentDetection(path: string): Promise<void>;
|
||||
private static getComponentDetectionParameters;
|
||||
static getManifestsFromResults(): Promise<Manifest[] | undefined>;
|
||||
static processComponentsToManifests(componentsFound: any[], dependencyGraphs: DependencyGraphs): Manifest[];
|
||||
private static addPackagesToManifests;
|
||||
private static getDependencyScope;
|
||||
static makePackageUrl(packageUrlJson: any): string;
|
||||
private static getLatestReleaseURL;
|
||||
/**
|
||||
* Normalizes the keys of a DependencyGraphs object to be relative paths from the resolved filePath input.
|
||||
* @param dependencyGraphs The DependencyGraphs object to normalize.
|
||||
* @param filePathInput The filePath input (relative or absolute) from the action configuration.
|
||||
* @returns A new DependencyGraphs object with relative path keys.
|
||||
*/
|
||||
static normalizeDependencyGraphPaths(dependencyGraphs: DependencyGraphs, filePathInput: string): DependencyGraphs;
|
||||
}
|
||||
/**
|
||||
* Types for the dependencyGraphs section of output.json
|
||||
*/
|
||||
export type DependencyGraph = {
|
||||
/**
|
||||
* The dependency graph: keys are component IDs, values are either null (no dependencies) or an array of component IDs (dependencies)
|
||||
*/
|
||||
graph: Record<string, string[] | null>;
|
||||
/**
|
||||
* Explicitly referenced component IDs
|
||||
*/
|
||||
explicitlyReferencedComponentIds: string[];
|
||||
/**
|
||||
* Development dependencies
|
||||
*/
|
||||
developmentDependencies: string[];
|
||||
/**
|
||||
* Regular dependencies
|
||||
*/
|
||||
dependencies: string[];
|
||||
};
|
||||
/**
|
||||
* The top-level dependencyGraphs object: keys are manifest file paths, values are DependencyGraph objects
|
||||
*/
|
||||
export type DependencyGraphs = Record<string, DependencyGraph>;
|
||||
|
||||
+66885
-3888
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -13,27 +13,65 @@ import {
|
||||
import ComponentDetection from './componentDetection';
|
||||
|
||||
async function run() {
|
||||
let manifests = await ComponentDetection.scanAndGetManifests(core.getInput('filePath'));
|
||||
const correlatorInput = core.getInput('correlator')?.trim() || github.context.job;
|
||||
|
||||
let snapshot = new Snapshot({
|
||||
name: "Component Detection",
|
||||
version: "0.0.1",
|
||||
url: "https://github.com/advanced-security/component-detection-dependency-submission-action",
|
||||
},
|
||||
github.context,
|
||||
{
|
||||
let manifests = await ComponentDetection.scanAndGetManifests(
|
||||
core.getInput("filePath")
|
||||
);
|
||||
const correlatorInput =
|
||||
core.getInput("correlator")?.trim() || github.context.job;
|
||||
|
||||
// Get detector configuration inputs
|
||||
const detectorName = core.getInput("detector-name")?.trim();
|
||||
const detectorVersion = core.getInput("detector-version")?.trim();
|
||||
const detectorUrl = core.getInput("detector-url")?.trim();
|
||||
|
||||
// Validate that if any detector config is provided, all must be provided
|
||||
const hasAnyDetectorInput = detectorName || detectorVersion || detectorUrl;
|
||||
const hasAllDetectorInputs = detectorName && detectorVersion && detectorUrl;
|
||||
|
||||
if (hasAnyDetectorInput && !hasAllDetectorInputs) {
|
||||
core.setFailed(
|
||||
"If any detector configuration is provided (detector-name, detector-version, detector-url), all three must be provided."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use provided detector config or defaults
|
||||
const detector = hasAllDetectorInputs
|
||||
? {
|
||||
name: detectorName,
|
||||
version: detectorVersion,
|
||||
url: detectorUrl,
|
||||
}
|
||||
: {
|
||||
name: "Component Detection",
|
||||
version: "0.0.1",
|
||||
url: "https://github.com/advanced-security/component-detection-dependency-submission-action",
|
||||
};
|
||||
|
||||
let snapshot = new Snapshot(detector, github.context, {
|
||||
correlator: correlatorInput,
|
||||
id: github.context.runId.toString()
|
||||
id: github.context.runId.toString(),
|
||||
});
|
||||
|
||||
core.debug(`Manifests: ${manifests?.length}`);
|
||||
|
||||
manifests?.forEach(manifest => {
|
||||
manifests?.forEach((manifest) => {
|
||||
core.debug(`Manifest: ${JSON.stringify(manifest)}`);
|
||||
snapshot.addManifest(manifest);
|
||||
});
|
||||
|
||||
// Override snapshot ref and sha if provided
|
||||
const snapshotSha = core.getInput("snapshot-sha")?.trim();
|
||||
const snapshotRef = core.getInput("snapshot-ref")?.trim();
|
||||
|
||||
if (snapshotSha) {
|
||||
snapshot.sha = snapshotSha;
|
||||
}
|
||||
|
||||
if (snapshotRef) {
|
||||
snapshot.ref = snapshotRef;
|
||||
}
|
||||
|
||||
submitSnapshot(snapshot);
|
||||
}
|
||||
|
||||
|
||||
Generated
+9756
-5625
File diff suppressed because it is too large
Load Diff
+15
-16
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "component-detection-action",
|
||||
"version": "1.0.0",
|
||||
"version": "0.1.0",
|
||||
"description": "Component detection action",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
@@ -26,26 +26,25 @@
|
||||
},
|
||||
"homepage": "https://github.com/advanced-security/component-detection-dependency-submission-action#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/github": "^6.0.1",
|
||||
"@actions/core": "^3.0.0",
|
||||
"@actions/github": "^9.0.0",
|
||||
"@github/dependency-submission-toolkit": "^2.0.5",
|
||||
"cross-fetch": "^4.1.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"dotenv": "^17.3.1",
|
||||
"fs": "^0.0.1-security",
|
||||
"octokit": "^4.1.3",
|
||||
"tar": "^7.4.3",
|
||||
"yaml": "^2.7.1"
|
||||
"octokit": "^5.0.5",
|
||||
"tar": "^7.5.10",
|
||||
"yaml": "^2.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.27.2",
|
||||
"@babel/preset-typescript": "^7.27.1",
|
||||
"@eslint/js": "^9.26.0",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"eslint": "^9.26.0",
|
||||
"jest": "^29.7.0",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@vercel/ncc": "^0.38.4",
|
||||
"eslint": "^10.0.2",
|
||||
"jest": "^30.2.0",
|
||||
"jest-transform-stub": "^2.0.0",
|
||||
"ts-jest": "^29.3.2"
|
||||
"ts-jest": "^29.4.6"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "nested-test-package",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "nested-test-package",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^29.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
|
||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"jest": "bin/jest.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "nested-test-package",
|
||||
"version": "1.0.0",
|
||||
"description": "A nested test package for component detection testing",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^29.0.0"
|
||||
}
|
||||
}
|
||||
Generated
+103
-148
@@ -15,7 +15,7 @@
|
||||
"cross-fetch": "^3.1.5",
|
||||
"dotenv": "^16.0.3",
|
||||
"fs": "^0.0.1-security",
|
||||
"tar": "^6.2.1",
|
||||
"tar": "^7.5.8",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -685,9 +685,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -754,6 +754,17 @@
|
||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||
"dependencies": {
|
||||
"minipass": "^7.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||
@@ -1880,11 +1891,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/ci-info": {
|
||||
@@ -2273,9 +2284,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -2532,28 +2543,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -3541,9 +3530,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
@@ -3727,9 +3716,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@@ -3739,45 +3728,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
|
||||
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
@@ -4402,19 +4368,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.8.tgz",
|
||||
"integrity": "sha512-SYkBtK99u0yXa+IWL0JRzzcl7RxNpvX/U08Z+8DKnysfno7M+uExnTZH8K+VGgShf2qFPKtbNr9QBl8n7WBP6Q==",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
"minipass": "^7.1.2",
|
||||
"minizlib": "^3.1.0",
|
||||
"yallist": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/yallist": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/test-exclude": {
|
||||
@@ -4783,7 +4756,8 @@
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.2.2",
|
||||
@@ -5338,9 +5312,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -5388,6 +5362,14 @@
|
||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||
"dev": true
|
||||
},
|
||||
"@isaacs/fs-minipass": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||
"requires": {
|
||||
"minipass": "^7.0.4"
|
||||
}
|
||||
},
|
||||
"@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||
@@ -6276,9 +6258,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "3.7.0",
|
||||
@@ -6538,9 +6520,9 @@
|
||||
}
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -6767,24 +6749,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
|
||||
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -7525,9 +7489,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
@@ -7669,43 +7633,27 @@
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
|
||||
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
|
||||
"requires": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
}
|
||||
"minipass": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@@ -8143,16 +8091,22 @@
|
||||
"dev": true
|
||||
},
|
||||
"tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.8.tgz",
|
||||
"integrity": "sha512-SYkBtK99u0yXa+IWL0JRzzcl7RxNpvX/U08Z+8DKnysfno7M+uExnTZH8K+VGgShf2qFPKtbNr9QBl8n7WBP6Q==",
|
||||
"requires": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
"minipass": "^7.1.2",
|
||||
"minizlib": "^3.1.0",
|
||||
"yallist": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-exclude": {
|
||||
@@ -8408,7 +8362,8 @@
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"yaml": {
|
||||
"version": "2.2.2",
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
"cross-fetch": "^3.1.5",
|
||||
"dotenv": "^16.0.3",
|
||||
"fs": "^0.0.1-security",
|
||||
"tar": "^6.2.1",
|
||||
"tar": "^7.5.8",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"target": "ES2022", /* Specify ECMAScript target version */
|
||||
"module": "ES2022", /* Specify module code generation */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' or 'classic'. */
|
||||
"outDir": "./dist", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
|
||||
Reference in New Issue
Block a user