Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 52 additions & 15 deletions componentDetection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ describe("ComponentDetection.processComponentsToManifests", () => {
},
isDevelopmentDependency: false,
topLevelReferrers: [], // Empty = direct dependency
locationsFoundAt: ["/package.json"]
locationsFoundAt: ["package.json"]
}
];

const dependencyGraphs: DependencyGraphs = {
"/package.json": {
"package.json": {
graph: { "test-package": null },
explicitlyReferencedComponentIds: ["test-package 1.0.0 - npm"],
developmentDependencies: [],
Expand All @@ -102,7 +102,7 @@ describe("ComponentDetection.processComponentsToManifests", () => {
const manifests = ComponentDetection.processComponentsToManifests(componentsFound, dependencyGraphs);

expect(manifests).toHaveLength(1);
expect(manifests[0].name).toBe("/package.json");
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);
Expand Down Expand Up @@ -135,12 +135,12 @@ describe("ComponentDetection.processComponentsToManifests", () => {
}
}
],
locationsFoundAt: ["/package.json"]
locationsFoundAt: ["package.json"]
}
];

const dependencyGraphs: DependencyGraphs = {
"/package.json": {
"package.json": {
graph: { "parent-package": null },
explicitlyReferencedComponentIds: [],
developmentDependencies: [],
Expand All @@ -151,7 +151,7 @@ describe("ComponentDetection.processComponentsToManifests", () => {
const manifests = ComponentDetection.processComponentsToManifests(componentsFound, dependencyGraphs);

expect(manifests).toHaveLength(1);
expect(manifests[0].name).toBe("/package.json");
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);
Expand Down Expand Up @@ -184,10 +184,10 @@ describe('normalizeDependencyGraphPaths', () => {
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 });
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 });
});
});

Expand All @@ -197,13 +197,50 @@ describe('normalizeDependencyGraphPaths with real output.json', () => {
const dependencyGraphs = output.dependencyGraphs;
// Use the same filePath as the action default (".")
const normalized = ComponentDetection.normalizeDependencyGraphPaths(dependencyGraphs, 'test');
// Should contain /package.json and /package-lock.json as keys
expect(Object.keys(normalized)).toContain('/package.json');
expect(Object.keys(normalized)).toContain('/package-lock.json');
// All keys should now be relative to the repo root (cwd) and start with '/'

// 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(true);
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);
17 changes: 9 additions & 8 deletions componentDetection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,28 +153,31 @@ export default class ComponentDetection {
private static addPackagesToManifests(packages: Array<ComponentDetectionPackage>, manifests: Array<Manifest>, dependencyGraphs: DependencyGraphs): void {
packages.forEach((pkg: ComponentDetectionPackage) => {
pkg.locationsFoundAt.forEach((location: any) => {
if (!manifests.find((manifest: Manifest) => manifest.name == location)) {
const manifest = new Manifest(location, location);
// Use the normalized path (remove leading slash if present)
const normalizedLocation = location.startsWith('/') ? location.substring(1) : location;

if (!manifests.find((manifest: Manifest) => manifest.name == normalizedLocation)) {
const manifest = new Manifest(normalizedLocation, normalizedLocation);
manifests.push(manifest);
}

const depGraphEntry = dependencyGraphs[location];
const depGraphEntry = dependencyGraphs[normalizedLocation];
if (!depGraphEntry) {
core.warning(`No dependency graph entry found for manifest location: ${location}`);
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 == location)
.find((manifest: Manifest) => manifest.name == normalizedLocation)
?.addDirectDependency(
pkg,
ComponentDetection.getDependencyScope(pkg)
);
} else {
manifests
.find((manifest: Manifest) => manifest.name == location)
.find((manifest: Manifest) => manifest.name == normalizedLocation)
?.addIndirectDependency(
pkg,
ComponentDetection.getDependencyScope(pkg)
Expand Down Expand Up @@ -283,8 +286,6 @@ export default class ComponentDetection {
for (const absPath in dependencyGraphs) {
// Make the path relative to the baseDir
let relPath = path.relative(baseDir, absPath).replace(/\\/g, '/');
// Ensure leading slash to represent repo root
if (!relPath.startsWith('/')) relPath = '/' + relPath;
normalized[relPath] = dependencyGraphs[absPath];
}
return normalized;
Expand Down
17 changes: 8 additions & 9 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions test/nested/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions test/nested/package.json
Original file line number Diff line number Diff line change
@@ -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.21"
},
"devDependencies": {
"jest": "^29.0.0"
}
}
Loading