From 7b5fa84cfcb67839b0649ae5c652d657a9912cf6 Mon Sep 17 00:00:00 2001 From: Stefan Petrushevski Date: Fri, 19 May 2023 10:47:59 +0200 Subject: [PATCH] added tests; docs and cleanup --- __tests__/licenses.test.ts | 54 ++++++++++++++++++++++++++++++++++++++ src/licenses.ts | 15 ++++------- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/__tests__/licenses.test.ts b/__tests__/licenses.test.ts index 66c7cc1..ae9f3f0 100644 --- a/__tests__/licenses.test.ts +++ b/__tests__/licenses.test.ts @@ -49,6 +49,32 @@ const rubyChange: Change = { ] } +const pipChange: Change = { + change_type: 'added', + manifest: 'requirements.txt', + ecosystem: 'pip', + name: 'package-1', + version: '1.1.1', + package_url: 'pkg:pip/package-1@1.1.1', + license: 'MIT', + source_repository_url: 'github.com/some-repo', + scope: 'runtime', + vulnerabilities: [ + { + severity: 'moderate', + advisory_ghsa_id: 'second-random_string', + advisory_summary: 'not so dangerous', + advisory_url: 'github.com/future-funk' + }, + { + severity: 'low', + advisory_ghsa_id: 'third-random_string', + advisory_summary: 'dont page me', + advisory_url: 'github.com/future-funk' + } + ] +} + jest.mock('@actions/core') const mockOctokit = { @@ -153,6 +179,34 @@ test('it adds all licenses to unresolved if it is unable to determine the validi expect(invalidLicenses.unresolved.length).toEqual(2) }) +test('it does not filter out changes that are on the exclusions list', async () => { + const changes: Changes = [pipChange, npmChange, rubyChange] + const licensesConfig = { + allow: ['BSD'], + licenseExclusions: ['pkg:pip/package-1@1.1.1', 'pkg:npm/reeuhq@1.0.2'] + } + const invalidLicenses = await getInvalidLicenseChanges( + changes, + licensesConfig + ) + expect(invalidLicenses.forbidden.length).toEqual(0) +}) + +test('it does filters out changes if they are not on the exclusions list', async () => { + const changes: Changes = [pipChange, npmChange, rubyChange] + const licensesConfig = { + allow: ['BSD'], + licenseExclusions: ['pkg:pip/notmypackage-1@1.1.1', 'pkg:npm/alsonot@1.0.2'] + } + const invalidLicenses = await getInvalidLicenseChanges( + changes, + licensesConfig + ) + expect(invalidLicenses.forbidden.length).toEqual(2) + expect(invalidLicenses.forbidden[0]).toBe(pipChange) + expect(invalidLicenses.forbidden[1]).toBe(npmChange) +}) + describe('GH License API fallback', () => { test('it calls licenses endpoint if atleast one of the changes has null license and valid source_repository_url', async () => { const nullLicenseChange = { diff --git a/src/licenses.ts b/src/licenses.ts index 5d365fb..859234f 100644 --- a/src/licenses.ts +++ b/src/licenses.ts @@ -6,13 +6,14 @@ import {PackageURL} from 'packageurl-js' /** * Loops through a list of changes, filtering and returning the * ones that don't conform to the licenses allow/deny lists. + * It will also filter out the changes which are defined in the licenseExclusions list. * * Keep in mind that we don't let users specify both an allow and a deny * list in their config files, so this code works under the assumption that * one of the two list parameters will be empty. If both lists are provided, * we will ignore the deny list. * @param {Change[]} changes The list of changes to filter. - * @param { { allow?: string[], deny?: string[]}} licenses An object with `allow`/`deny` keys, each containing a list of licenses. + * @param { { allow?: string[], deny?: string[], licenseExclusions?: string[]}} licenses An object with `allow`/`deny`/`licenseExclusions` keys, each containing a list of licenses. * @returns {Promise<{Object.>}} A promise to a Record Object. The keys are strings, unlicensed, unresolved and forbidden. The values are a list of changes */ export type InvalidLicenseChangeTypes = @@ -40,15 +41,9 @@ export async function getInvalidLicenseChanges( // Takes the changes from the groupedChanges object and filters out the ones that are part of the exclusions list // It does by creating a new PackageURL object from the change and comparing it to the exclusions list groupedChanges.licensed = groupedChanges.licensed.filter(change => { - const changeAsPackageURL = new PackageURL( - change.ecosystem, - null, - change.name, - change.version, - null, - null - ) - // We want to find if the licenseExclussion list contains the PackageURL of the change + const changeAsPackageURL = PackageURL.fromString(change.package_url) + + // We want to find if the licenseExclussion list contains the PackageURL of the Change // If it does, we want to filter it out and therefore return false // If it doesn't, we want to keep it and therefore return true if (