Commit 84da9103 authored by Fatih Acet's avatar Fatih Acet

Merge branch '13079-parse-v1-1-report' into 'master'

Display software packages with multiple software licenses correctly

See merge request gitlab-org/gitlab!19333
parents 309b1b10 0027c7dc
......@@ -4,6 +4,10 @@ export const LICENSE_APPROVAL_STATUS = {
BLACKLISTED: 'blacklisted',
};
export const VERSION_1_0 = '1.0';
export const VERSION_1_1 = '1.1';
export const VERSION_2_0 = '2.0';
export const KNOWN_LICENSES = [
'AGPL-1.0',
'AGPL-3.0',
......
......@@ -56,9 +56,10 @@ const getLicenseStatusByName = (managedLicenses = [], licenseName) =>
managedLicenses.find(license => caseInsensitiveMatch(license.name, licenseName)) || {};
const getDependenciesByLicenseName = (dependencies = [], licenseName) =>
dependencies.filter(dependencyItem =>
caseInsensitiveMatch(dependencyItem.license.name, licenseName),
);
dependencies.filter(dependencyItem => {
const licenses = dependencyItem.licenses || [dependencyItem.license];
return licenses.find(license => caseInsensitiveMatch(license.name, licenseName));
});
/**
*
......@@ -104,6 +105,7 @@ export const parseLicenseReportMetrics = (headMetrics, baseMetrics, managedLicen
const { id, approvalStatus } = getLicenseStatusByName(managedLicenseList, name);
const dependencies = getDependenciesByLicenseName(headDependencies, name);
const url =
license.url ||
(dependencies && dependencies[0] && dependencies[0].license && dependencies[0].license.url) ||
'';
......
import { byLicenseNameComparator } from './store/utils';
import { VERSION_1_1 } from './constants';
export default class V2Report {
constructor(report) {
......@@ -9,6 +10,7 @@ export default class V2Report {
toV1Schema() {
return {
version: VERSION_1_1,
licenses: this.licenses,
dependencies: this.report.dependencies.map(v2Dependency =>
this.mapFromDependency(v2Dependency),
......@@ -33,12 +35,15 @@ export default class V2Report {
}
mapFromDependency({ name, description, url, licenses }) {
const convertedLicenses = [];
const combinedLicense = this.combine(licenses, license => {
this.incrementCountFor(license.name);
convertedLicenses.push(license);
});
return {
license: combinedLicense,
licenses: convertedLicenses,
dependency: { name, url, description },
};
}
......
---
title: Display packages with multiple licenses
merge_request: 19333
author:
type: fixed
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
import {
LICENSE_APPROVAL_STATUS,
VERSION_1_0,
VERSION_1_1,
VERSION_2_0,
} from 'ee/vue_shared/license_management/constants';
const urlFor = ({ scheme = 'https', host = 'www.example.org', path = '/' }) =>
`${scheme}://${host}${path}`;
......@@ -7,6 +12,7 @@ const licenseUrlFor = name =>
const dependencyUrlFor = name => urlFor({ path: `/${name}` });
const normalizeV1License = ({ name, url = licenseUrlFor(name) }) => ({ name, url });
const V1 = {
template: () => ({ licenses: [], dependencies: [] }),
normalizeLicenseSummary: ({ name, url = licenseUrlFor(name), count = 0 }) => ({
name,
url,
......@@ -19,7 +25,22 @@ const V1 = {
license = {},
}) => ({ dependency: { name, url, description }, license: normalizeV1License(license) }),
};
const V1_1 = Object.assign(V1, {
template: () => ({ version: VERSION_1_1, licenses: [], dependencies: [] }),
normalizeDependency: ({
name,
url = dependencyUrlFor(name),
description = name.toUpperCase(),
license = {},
licenses = [normalizeV1License(license)],
}) => ({
dependency: { name, url, description },
license: normalizeV1License(license),
licenses,
}),
});
const V2 = {
template: () => ({ version: VERSION_2_0, licenses: [], dependencies: [] }),
normalizeLicenseSummary: ({ id, name, url = licenseUrlFor(id) }) => ({ id, name, url }),
normalizeDependency: ({
name,
......@@ -30,20 +51,29 @@ const V2 = {
};
export class Builder {
static for(version, template = { licenses: [], dependencies: [] }) {
return new Builder(version, template);
static for(version) {
switch (version) {
case VERSION_1_0:
return new Builder(V1);
case VERSION_1_1:
return new Builder(V1_1);
case VERSION_2_0:
return new Builder(V2);
default:
return new Builder(V1);
}
}
static forV1() {
return this.for(V1);
static forV1(minor = '0') {
return this.for(`1.${minor}`);
}
static forV2() {
return this.for(V2, { version: '2.0', licenses: [], dependencies: [] });
static forV2(minor = '0') {
return this.for(`2.${minor}`);
}
constructor(version, template = { licenses: [], dependencies: [] }) {
this.report = template;
constructor(version) {
this.report = version.template();
this.version = version;
}
......
......@@ -18,6 +18,25 @@ describe('build', () => {
});
});
it('creates a v1.1 report', () => {
const result = Builder.forV1('1')
.addLicense({ name: 'MIT License' })
.addDependency({ name: 'rails', license: { name: 'MIT License' } })
.build();
expect(result).toMatchObject({
version: '1.1',
licenses: [{ name: 'MIT License', url: 'https://opensource.org/licenses/MIT', count: 0 }],
dependencies: [
{
license: { name: 'MIT License', url: 'https://opensource.org/licenses/MIT' },
licenses: [{ name: 'MIT License', url: 'https://opensource.org/licenses/MIT' }],
dependency: { name: 'rails', description: 'RAILS', url: 'https://www.example.org/rails' },
},
],
});
});
it('creates a v2 report', () => {
const result = Builder.forV2()
.addLicense({ id: 'MIT', name: 'MIT License' })
......
......@@ -8,7 +8,7 @@ describe('mapFrom', () => {
subject = new ReportMapper(true);
});
it('converts a v2 schema report to v1', () => {
it('converts a v2 schema report to v1.1', () => {
const report = Builder.forV2()
.addLicense({ id: 'MIT', name: 'MIT License' })
.addLicense({ id: 'BSD', name: 'BSD License' })
......@@ -19,12 +19,16 @@ describe('mapFrom', () => {
const result = subject.mapFrom(report);
expect(result).toMatchObject(
Builder.forV1()
Builder.forV1('1')
.addLicense({ name: 'BSD License', count: 2 })
.addLicense({ name: 'MIT License', count: 2 })
.addDependency({ name: 'x', license: { name: 'MIT License' } })
.addDependency({ name: 'y', license: { name: 'BSD License' } })
.addDependency({ name: 'z', license: { name: 'BSD License, MIT License', url: '' } })
.addDependency({
name: 'z',
license: { name: 'BSD License, MIT License', url: '' },
licenses: [{ name: 'BSD License' }, { name: 'MIT License' }],
})
.build(),
);
});
......
......@@ -37,7 +37,7 @@ describe('utils', () => {
const result = parseLicenseReportMetrics(licenseHeadIssues, licenseBaseIssues);
expect(result[0].name).toBe(licenseHeadIssues.licenses[0].name);
expect(result[0].url).toBe(licenseHeadIssues.dependencies[0].license.url);
expect(result[0].url).toBe(licenseHeadIssues.licenses[0].url);
});
it('should omit issues from base report', () => {
......@@ -90,7 +90,10 @@ describe('utils', () => {
status: 'failed',
name: 'BSD License',
url: 'https://opensource.org/licenses/BSD',
packages: [{ name: 'y', url: 'https://www.example.org/y', description: 'Y' }],
packages: [
{ name: 'y', url: 'https://www.example.org/y', description: 'Y' },
{ name: 'z', url: 'https://www.example.org/z', description: 'Z' },
],
}),
);
});
......@@ -108,14 +111,15 @@ describe('utils', () => {
const headReport = Builder.forV2()
.addLicense({ id: 'MIT', name: 'MIT License' })
.addLicense({ id: 'BSD', name: 'BSD License' })
.addLicense({ id: 'MPL-1.1', name: 'Mozilla Public License 1.1' })
.addDependency({ name: 'x', licenses: ['MIT'] })
.addDependency({ name: 'y', licenses: ['BSD'] })
.addDependency({ name: 'z', licenses: ['BSD', 'MIT'] })
.addDependency({ name: 'z', licenses: ['BSD', 'MIT', 'MPL-1.1'] })
.build();
const result = parseLicenseReportMetrics(headReport, baseReport, policies);
expect(result.length).toBe(1);
expect(result.length).toBe(2);
expect(result[0]).toEqual(
jasmine.objectContaining({
id: 101,
......@@ -124,7 +128,22 @@ describe('utils', () => {
status: 'failed',
name: 'BSD License',
url: 'https://opensource.org/licenses/BSD',
packages: [{ name: 'y', url: 'https://www.example.org/y', description: 'Y' }],
packages: [
{ name: 'y', url: 'https://www.example.org/y', description: 'Y' },
{ name: 'z', url: 'https://www.example.org/z', description: 'Z' },
],
}),
);
expect(result[1]).toEqual(
jasmine.objectContaining({
id: undefined,
approvalStatus: undefined,
count: 1,
status: 'neutral',
name: 'Mozilla Public License 1.1',
url: 'https://opensource.org/licenses/MPL-1.1',
packages: [{ name: 'z', url: 'https://www.example.org/z', description: 'Z' }],
}),
);
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment