Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
21 changes: 21 additions & 0 deletions componentDetection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,27 @@ test("Parses CLI output", async () => {
expect(manifests?.length == 2);
});

describe("ComponentDetection.makePackageUrl", () => {
test("returns a empty valid package url from null object", () => {
const packageUrl = ComponentDetection.makePackageUrl(null);
expect(packageUrl).toBe("");
});
});

describe("ComponentDetection.makePackageUrl", () => {
test("returns a empty valid package url from null object properties", () => {
const packageUrl = ComponentDetection.makePackageUrl({
Scheme: null,
Type: null,
Namespace: null,
Name: null,
Version: null,
Qualifiers: null
});
expect(packageUrl).toBe("");
});
});

describe("ComponentDetection.makePackageUrl", () => {
test("returns a valid package url from saturated object", () => {
const packageUrl = ComponentDetection.makePackageUrl({
Expand Down
82 changes: 64 additions & 18 deletions componentDetection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,23 @@ export default class ComponentDetection {

var json: any = JSON.parse(results);
json.componentsFound.forEach(async (component: any) => {
// Skip components without packageUrl
if (!component.component.packageUrl) {
core.debug(`Skipping component detected without packageUrl: ${JSON.stringify({
id: component.component.id,
name: component.component.name || 'unnamed',
type: component.component.type || 'unknown'
}, null, 2)}`);
return;
}

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}`);
return;
}

if (!packageCache.hasPackage(packageUrl)) {
const pkg = new ComponentDetectionPackage(packageUrl, component.component.id,
Expand All @@ -89,9 +105,27 @@ export default class ComponentDetection {
core.debug("Sorting out transitive dependencies");
packages.forEach(async (pkg: ComponentDetectionPackage) => {
pkg.topLevelReferrers.forEach(async (referrer: any) => {
const referrerPackage = packageCache.lookupPackage(ComponentDetection.makePackageUrl(referrer.packageUrl));
if (referrerPackage) {
referrerPackage.dependsOn(pkg);
// Skip if referrer doesn't have a valid packageUrl
if (!referrer.packageUrl) {
core.debug(`Skipping referrer without packageUrl for component: ${pkg.id}`);
return;
}

const referrerUrl = ComponentDetection.makePackageUrl(referrer.packageUrl);

// 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) {
referrerPackage.dependsOn(pkg);
}
} catch (error) {
core.debug(`Error looking up referrer package: ${error}`);
}
});
});
Expand Down Expand Up @@ -121,23 +155,35 @@ export default class ComponentDetection {
}

public static makePackageUrl(packageUrlJson: any): string {
var packageUrl = `${packageUrlJson.Scheme}:${packageUrlJson.Type}/`;
if (packageUrlJson.Namespace) {
packageUrl += `${packageUrlJson.Namespace.replaceAll("@", "%40")}/`;
}
packageUrl += `${packageUrlJson.Name.replaceAll("@", "%40")}`;
if (packageUrlJson.Version) {
packageUrl += `@${packageUrlJson.Version}`;
// Handle case when packageUrlJson is null or undefined
if (!packageUrlJson) {
core.debug(`Warning: Received null or undefined packageUrlJson. Unable to create package URL.`);
return ""; // Return a blank string for unknown packages
}
if (typeof packageUrlJson.Qualifiers === "object"
&& packageUrlJson.Qualifiers !== null
&& Object.keys(packageUrlJson.Qualifiers).length > 0) {
const qualifierString = Object.entries(packageUrlJson.Qualifiers)
.map(([key, value]) => `${key}=${value}`)
.join("&");
packageUrl += `?${qualifierString}`;

try {
var packageUrl = `${packageUrlJson.Scheme}:${packageUrlJson.Type}/`;
if (packageUrlJson.Namespace) {
packageUrl += `${packageUrlJson.Namespace.replaceAll("@", "%40")}/`;
}
packageUrl += `${packageUrlJson.Name.replaceAll("@", "%40")}`;
if (packageUrlJson.Version) {
packageUrl += `@${packageUrlJson.Version}`;
}
if (typeof packageUrlJson.Qualifiers === "object"
&& packageUrlJson.Qualifiers !== null
&& Object.keys(packageUrlJson.Qualifiers).length > 0) {
const qualifierString = Object.entries(packageUrlJson.Qualifiers)
.map(([key, value]) => `${key}=${value}`)
.join("&");
packageUrl += `?${qualifierString}`;
}
return packageUrl;
} catch (error) {
core.debug(`Error creating package URL from packageUrlJson: ${JSON.stringify(packageUrlJson, null, 2)}`);
core.debug(`Error details: ${error}`);
return ""; // Return a blank string for error cases
}
return packageUrl;
}

private static async getLatestReleaseURL(): Promise<string> {
Expand Down
82 changes: 62 additions & 20 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.