1
0
mirror of https://github.com/angular/angular-cli.git synced 2025-05-26 01:01:13 +08:00

docs: clarified licenses and renamed spdx variable to what it is

The Spdx list is the list of licenses understood by SPDX, not necessarily agreed on
by our team and/or Google. That variable is really a whitelist.
This commit is contained in:
Hans Larsen 2017-09-20 08:04:43 -07:00 committed by Mike Brocchi
parent f2ee98d303
commit b79549dc5f
3 changed files with 2114 additions and 1171 deletions

3110
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -121,12 +121,13 @@
"@types/semver": "^5.3.30",
"@types/source-map": "^0.5.0",
"@types/webpack": "^3.0.5",
"conventional-changelog": "^1.1.0",
"conventional-changelog": "1.1.0",
"dtsgenerator": "^0.9.1",
"eslint": "^3.11.0",
"express": "^4.14.0",
"jasmine": "^2.6.0",
"jasmine-spec-reporter": "^4.1.0",
"license-checker": "^14.0.0",
"minimist": "^1.2.0",
"mock-fs": "^4.0.0",
"npm-run": "^4.1.0",

@ -1,7 +1,6 @@
require('../lib/bootstrap-local');
const path = require('path');
const glob = require('glob');
const chalk = require('chalk');
const spdxSatisfies = require('spdx-satisfies');
const Logger = require('@ngtools/logger').Logger;
@ -30,121 +29,102 @@ logger
process.exit(1);
});
// SPDX defined licenses, see https://spdx.org/licenses/.
// TODO(hansl): confirm this list
const acceptedSpdxLicenses = [
/**
* 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',
'Beerware',
'Unlicense'
// 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)',
];
// Name variations of SPDX licenses that some packages have.
// Licenses not included in SPDX but accepted will be converted to MIT.
// TODO(hansl): make sure all of these are ok
const licenseReplacements = [
{ name: 'Apache License, Version 2.0', replacement: 'Apache-2.0' },
{ name: 'AFLv2.1', replacement: 'AFL-2.1' },
// I guess these are kinda the same?
{ name: 'BSD', replacement: 'BSD-2-Clause' },
{ name: 'BSD-like', replacement: 'BSD-2-Clause' },
{ name: 'MIT/X11', replacement: 'MIT' },
// Not sure how to deal with public domain.
// http://wiki.spdx.org/view/Legal_Team/Decisions/Dealing_with_Public_Domain_within_SPDX_Files
{ name: 'Public Domain', replacement: 'MIT' }
];
const licenseReplacements = {
// 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',
'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.
// TODO(hansl): review these
const ignoredPackages = [
'async-foreach@0.1.3', // MIT, but doesn't list it in package.json
'buffer-indexof@1.1.0', // MIT, but doesn't list it in package.json.
'directory-encoder@0.7.2', // MIT, but doesn't list it in package.json
'domelementtype@1.1.3', // Looks like MIT
'domelementtype@1.3.0', // Looks like MIT
'domhandler@2.1.0', // Looks like MIT
'domutils@1.5.1', // Looks like MIT
'domutils@1.1.6', // Looks like MIT
'extsprintf@1.0.2', // Looks like MIT
'indexof@0.0.1', // MIT, but doesn't list it in package.json
'jschardet@1.5.1', // LGPL-2.1, listed as LGPL-2.1+.
'spdx-license-ids@2.0.1', // CC0 but it's content only (index.json, no code) and not distributed.
'map-stream@0.1.0', // MIT, license but it's not listed in package.json.
'pause-stream@0.0.11', // MIT AND Apache-2.0, but broken license field in package.json lists.
'progress@1.1.8', // MIT, but doesn't list it in package.json
'stdout-stream@1.4.0', // MIT, but doesn't list it in package.json
'thunky@0.1.0', // MIT, but doesn't list it in package.json.
'uglify-js@2.3.6', // BSD, but doesn't list it in package.json
'undefined@undefined', // Test package with no name nor version.
'verror@1.3.6', // Looks like MIT
'xmldom@0.1.27' // LGPL,MIT but has a broken licenses array
'xmldom@0.1.27', // LGPL,MIT but has a broken licenses array.
'jsonify@0.0.0', // 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.
];
const root = path.resolve(__dirname, '../');
// Find all folders directly under a `node_modules` that have a package.json.
const allPackages = glob.sync(path.join(root, '**/node_modules/*/package.json'), { nodir: true })
.map(packageJsonPath => {
const packageJson = require(packageJsonPath);
return {
id: `${packageJson.name}@${packageJson.version}`,
path: path.dirname(packageJsonPath),
packageJson: packageJson
};
})
// Figure out what kind of license the package uses.
.map(pkg => {
let license = null;
if (pkg.packageJson.license) {
// Use license field if present
if (typeof pkg.packageJson.license === 'string') {
license = replace(pkg.packageJson.license);
} else if (typeof pkg.packageJson.license === 'object' && typeof pkg.packageJson.type) {
license = replace(pkg.packageJson.license.type);
}
} else if (Array.isArray(pkg.packageJson.licenses)) {
// If there's an (outdated) licenses array use that joined by OR.
// TODO verify multiple licenses is OR and not AND
license = pkg.packageJson.licenses
.map(license => replace(license.type))
.join(' OR ');
const checker = require('license-checker');
checker.init({ start: path.join(__dirname, '..') }, (err, json) => {
if (err) {
logger.fatal(`Something happened:\n${err.message}`);
} 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 => {
return {
id: key,
licenses: []
.concat(json[key].licenses)
.map(x => x.replace(/\*$/, '')) // `*` is used when the license is guessed.
.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.`);
} else {
logger.info('All package licenses are valid.');
}
pkg.license = license;
return pkg;
})
logger.info(`Testing ${allPackages.length} packages.\n`)
// Packages with bad licenses are those that neither pass SPDX nor are ignored.
const badLicensePackages = allPackages
.filter(pkg => !passesSpdx(pkg.license, acceptedSpdxLicenses))
.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} (${pkg.path}): ${pkg.license}`));
logger.fatal(`\n${badLicensePackages.length} total packages with invalid licenses.`);
} else {
logger.info('All package licenses are valid.');
}
}
});
// Check if a license is accepted by an array of accepted licenses
function passesSpdx(license, accepted) {
try {
return spdxSatisfies(license, `(${accepted.join(' OR ')})`)
} catch (_) {
return false;
}
}
// Apply license name replacement if any
function replace(license) {
const match = licenseReplacements.find(rpl => rpl.name === license);
return match ? match.replacement : license;
function passesSpdx(licenses, accepted) {
return accepted.some(l => {
try {
return spdxSatisfies(licenses.join(' AND '), l);
} catch (_) {
return false;
}
});
}