forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate-licenses.ts
More file actions
138 lines (118 loc) · 5.03 KB
/
validate-licenses.ts
File metadata and controls
138 lines (118 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// tslint:disable:no-implicit-dependencies
import { JsonObject, logging } from '@angular-devkit/core';
require('../lib/bootstrap-local');
const path = require('path');
const spdxSatisfies = require('spdx-satisfies');
/**
* A general note on some black listed specific licenses:
* - CC0
* This is not a valid license. It does not grant copyright of the code/asset, and does not
* resolve patents or other licensed work. The different claims also have no standing in court
* and do not provide protection to or from Google and/or third parties.
* We cannot use nor contribute to CC0 licenses.
* - Public Domain
* Same as CC0, it is not a valid license.
*/
const licensesWhitelist = [
// Regular valid open source licenses supported by Google.
'MIT',
'ISC',
'Apache-2.0',
'BSD-2-Clause',
'BSD-3-Clause',
'BSD-4-Clause',
// All CC-BY licenses have a full copyright grant and attribution section.
'CC-BY-3.0',
'CC-BY-4.0',
// Have a full copyright grant. Validated by opensource team.
'Unlicense',
// Combinations.
'(AFL-2.1 OR BSD-2-Clause)',
'(MIT OR CC-BY-3.0)',
'(MIT OR Apache-2.0)',
'(MIT OR BSD-3-Clause)',
];
// Name variations of SPDX licenses that some packages have.
// Licenses not included in SPDX but accepted will be converted to MIT.
const licenseReplacements: { [key: string]: string } = {
// Just a longer string that our script catches. SPDX official name is the shorter one.
'Apache License, Version 2.0': 'Apache-2.0',
'Apache2': 'Apache-2.0',
'Apache 2.0': 'Apache-2.0',
'AFLv2.1': 'AFL-2.1',
// BSD is BSD-2-clause by default.
'BSD': 'BSD-2-Clause',
};
// Specific packages to ignore, add a reason in a comment. Format: package-name@version.
const ignoredPackages = [
'[email protected]', // CC0 but it's content only (index.json, no code) and not distributed.
'[email protected]', // CC0 but it's content only (index.json, no code) and not distributed.
'[email protected]', // MIT, license but it's not listed in package.json.
'[email protected]', // LGPL,MIT but has a broken licenses array.
'[email protected]', // Apache-2.0 but broken license in package.json
'[email protected]', // MIT but broken license in package.json
'[email protected]', // TODO(hansl): fix this. this is not an acceptable license, but is 8 deps down
// so hard to manage. In talk with owner and users to switch over.
'[email protected]', // TODO(filipesilva): remove this when karma is moved to e2e tests.
// TODO(filipesilva): remove this when spec_large is moved to e2e tests.
'[email protected]', // (OFL-1.1 AND MIT)
'@webassemblyjs/[email protected]', // MIT but no LICENSE file. `license` field in package.json.
'@webassemblyjs/[email protected]', // Apache 2.0 license, but get discovered as "Apache".
'@webassemblyjs/[email protected]', // Apache 2.0 license, but get discovered as "Apache".
];
// Find all folders directly under a `node_modules` that have a package.json.
const checker = require('license-checker');
// Check if a license is accepted by an array of accepted licenses
function _passesSpdx(licenses: string[], accepted: string[]) {
return accepted.some(l => {
try {
return spdxSatisfies(licenses.join(' AND '), l);
} catch (_) {
return false;
}
});
}
export default function (_options: {}, logger: logging.Logger): Promise<number> {
return new Promise(resolve => {
checker.init({ start: path.join(__dirname, '..') }, (err: Error, json: JsonObject) => {
if (err) {
logger.fatal(`Something happened:\n${err.message}`);
resolve(1);
} else {
logger.info(`Testing ${Object.keys(json).length} packages.\n`);
// Packages with bad licenses are those that neither pass SPDX nor are ignored.
const badLicensePackages = Object.keys(json)
.map(key => ({
id: key,
licenses: ([] as string[])
// tslint:disable-next-line:non-null-operator
.concat((json[key] ! as JsonObject).licenses as string[])
// `*` is used when the license is guessed.
.map(x => x.replace(/\*$/, ''))
.map(x => x in licenseReplacements ? licenseReplacements[x] : x),
}))
.filter(pkg => !_passesSpdx(pkg.licenses, licensesWhitelist))
.filter(pkg => !ignoredPackages.find(ignored => ignored === pkg.id));
// Report packages with bad licenses
if (badLicensePackages.length > 0) {
logger.error('Invalid package licences found:');
badLicensePackages.forEach(pkg => {
logger.error(`${pkg.id}: ${JSON.stringify(pkg.licenses)}`);
});
logger.fatal(`\n${badLicensePackages.length} total packages with invalid licenses.`);
resolve(2);
} else {
logger.info('All package licenses are valid.');
resolve(0);
}
}
});
});
}