chore: validate licenses (#9873)
This commit is contained in:
parent
ad7bbaebef
commit
f6ef167b0f
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -37,6 +37,8 @@ jobs:
|
|||||||
run: npm run check
|
run: npm run check
|
||||||
- name: Lint code
|
- name: Lint code
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
|
- name: Validate licenses
|
||||||
|
run: npm run validate-licenses
|
||||||
- name: Lint commits
|
- name: Lint commits
|
||||||
run: npm run commitlint
|
run: npm run commitlint
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
|
1119
package-lock.json
generated
1119
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,8 @@
|
|||||||
"test:firefox:headful": "wireit",
|
"test:firefox:headful": "wireit",
|
||||||
"test:firefox:headless": "wireit",
|
"test:firefox:headless": "wireit",
|
||||||
"test:firefox": "wireit",
|
"test:firefox": "wireit",
|
||||||
"test": "cross-env PUPPETEER_DEFERRED_PROMISE_DEBUG_TIMEOUT=20000 node tools/mochaRunner/lib/main.js"
|
"test": "cross-env PUPPETEER_DEFERRED_PROMISE_DEBUG_TIMEOUT=20000 node tools/mochaRunner/lib/main.js",
|
||||||
|
"validate-licenses": "tsx tools/third_party/validate-licenses.ts"
|
||||||
},
|
},
|
||||||
"wireit": {
|
"wireit": {
|
||||||
"build": {
|
"build": {
|
||||||
@ -157,10 +158,11 @@
|
|||||||
"eslint-plugin-unused-imports": "2.0.0",
|
"eslint-plugin-unused-imports": "2.0.0",
|
||||||
"esprima": "4.0.1",
|
"esprima": "4.0.1",
|
||||||
"expect": "29.4.3",
|
"expect": "29.4.3",
|
||||||
"glob": "9.3.1",
|
"glob": "8.1.0",
|
||||||
"gts": "4.0.0",
|
"gts": "4.0.0",
|
||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"jpeg-js": "0.4.4",
|
"jpeg-js": "0.4.4",
|
||||||
|
"license-checker": "25.0.1",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"minimist": "1.2.8",
|
"minimist": "1.2.8",
|
||||||
"mocha": "10.2.0",
|
"mocha": "10.2.0",
|
||||||
@ -170,11 +172,11 @@
|
|||||||
"pngjs": "7.0.0",
|
"pngjs": "7.0.0",
|
||||||
"prettier": "2.8.4",
|
"prettier": "2.8.4",
|
||||||
"puppeteer": "file:packages/puppeteer",
|
"puppeteer": "file:packages/puppeteer",
|
||||||
"rimraf": "4.4.0",
|
|
||||||
"rollup": "3.18.0",
|
"rollup": "3.18.0",
|
||||||
"semver": "7.3.8",
|
"semver": "7.3.8",
|
||||||
"sinon": "15.0.1",
|
"sinon": "15.0.1",
|
||||||
"source-map-support": "0.5.21",
|
"source-map-support": "0.5.21",
|
||||||
|
"spdx-satisfies": "5.0.1",
|
||||||
"text-diff": "1.0.1",
|
"text-diff": "1.0.1",
|
||||||
"tsd": "0.26.0",
|
"tsd": "0.26.0",
|
||||||
"tsx": "3.12.3",
|
"tsx": "3.12.3",
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
import {nodeResolve} from '@rollup/plugin-node-resolve';
|
import {nodeResolve} from '@rollup/plugin-node-resolve';
|
||||||
import {globIterateSync} from 'glob';
|
import glob from 'glob';
|
||||||
|
|
||||||
export default ['cjs', 'esm'].flatMap(outputType => {
|
export default ['cjs', 'esm'].flatMap(outputType => {
|
||||||
const configs = [];
|
const configs = [];
|
||||||
// Note we don't use path.join here. We cannot since `glob` does not support
|
// Note we don't use path.join here. We cannot since `glob` does not support
|
||||||
// the backslash path separator.
|
// the backslash path separator.
|
||||||
for (const file of globIterateSync(`lib/${outputType}/third_party/**/*.js`)) {
|
for (const file of glob.sync(`lib/${outputType}/third_party/**/*.js`)) {
|
||||||
configs.push({
|
configs.push({
|
||||||
input: file,
|
input: file,
|
||||||
output: {
|
output: {
|
||||||
|
@ -44,7 +44,10 @@
|
|||||||
"assets"
|
"assets"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "9.3.1",
|
"glob": "8.1.0",
|
||||||
"mocha": "10.2.0"
|
"mocha": "10.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/glob": "8.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@
|
|||||||
import {dirname, join, resolve} from 'path';
|
import {dirname, join, resolve} from 'path';
|
||||||
import {fileURLToPath} from 'url';
|
import {fileURLToPath} from 'url';
|
||||||
|
|
||||||
import {globIterateSync} from 'glob';
|
import glob from 'glob';
|
||||||
|
|
||||||
export const PUPPETEER_CORE_PACKAGE_PATH = resolve(
|
export const PUPPETEER_CORE_PACKAGE_PATH = resolve(
|
||||||
globIterateSync('puppeteer-core-*.tgz').next().value!
|
glob.sync('puppeteer-core-*.tgz')[0]!
|
||||||
);
|
);
|
||||||
export const PUPPETEER_PACKAGE_PATH = resolve(
|
export const PUPPETEER_PACKAGE_PATH = resolve(
|
||||||
globIterateSync('puppeteer-[0-9]*.tgz').next().value!
|
glob.sync('puppeteer-[0-9]*.tgz')[0]!
|
||||||
);
|
);
|
||||||
export const ASSETS_DIR = join(
|
export const ASSETS_DIR = join(
|
||||||
dirname(fileURLToPath(import.meta.url)),
|
dirname(fileURLToPath(import.meta.url)),
|
||||||
|
@ -4,7 +4,7 @@ import {mkdir, readFile, stat, writeFile} from 'fs/promises';
|
|||||||
import {tmpdir} from 'os';
|
import {tmpdir} from 'os';
|
||||||
import {dirname, join} from 'path';
|
import {dirname, join} from 'path';
|
||||||
|
|
||||||
import {globSync, hasMagic} from 'glob';
|
import glob from 'glob';
|
||||||
|
|
||||||
interface JobContext {
|
interface JobContext {
|
||||||
name: string;
|
name: string;
|
||||||
@ -41,8 +41,8 @@ class JobBuilder {
|
|||||||
|
|
||||||
inputs(inputs: string[]): JobBuilder {
|
inputs(inputs: string[]): JobBuilder {
|
||||||
this.#inputs = inputs.flatMap(value => {
|
this.#inputs = inputs.flatMap(value => {
|
||||||
if (hasMagic(value)) {
|
if (glob.hasMagic(value)) {
|
||||||
return globSync(value);
|
return glob.sync(value);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
153
tools/third_party/validate-licenses.ts
vendored
Normal file
153
tools/third_party/validate-licenses.ts
vendored
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// The MIT License
|
||||||
|
|
||||||
|
// Copyright (c) 2010-2022 Google LLC. http://angular.io/license
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
// this software and associated documentation files (the "Software"), to deal in
|
||||||
|
// the Software without restriction, including without limitation the rights to
|
||||||
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
// subject to the following conditions:
|
||||||
|
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
// Taken and adapted from https://github.com/angular/angular-cli/blob/173823d/scripts/validate-licenses.ts.
|
||||||
|
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
import checker from 'license-checker';
|
||||||
|
import spdxSatisfies from '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 allowedLicenses = [
|
||||||
|
// Regular valid open source licenses supported by Google.
|
||||||
|
'MIT',
|
||||||
|
'ISC',
|
||||||
|
'Apache-2.0',
|
||||||
|
'Python-2.0',
|
||||||
|
'Artistic-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',
|
||||||
|
'CC0-1.0',
|
||||||
|
'0BSD',
|
||||||
|
|
||||||
|
// Combinations.
|
||||||
|
'(AFL-2.1 OR BSD-2-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',
|
||||||
|
'Apache v2': '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 = [
|
||||||
|
// * Development only
|
||||||
|
'spdx-license-ids@3.0.5', // CC0 but it's content only (index.json, no code) and not distributed.
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if a license is accepted by an array of accepted licenses
|
||||||
|
function _passesSpdx(licenses: string[], accepted: string[]) {
|
||||||
|
try {
|
||||||
|
return spdxSatisfies(licenses.join(' AND '), accepted.join(' OR '));
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(): Promise<number> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const startFolder = path.join(__dirname, '..', '..');
|
||||||
|
checker.init(
|
||||||
|
{start: startFolder, excludePrivatePackages: true},
|
||||||
|
(err: Error, json: object) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Something happened:\n${err.message}`);
|
||||||
|
resolve(1);
|
||||||
|
} else {
|
||||||
|
console.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: ([] as string[])
|
||||||
|
.concat((json[key] as {licenses: string[]}).licenses)
|
||||||
|
// `*` is used when the license is guessed.
|
||||||
|
.map(x => {
|
||||||
|
return x.replace(/\*$/, '');
|
||||||
|
})
|
||||||
|
.map(x => {
|
||||||
|
return x in licenseReplacements
|
||||||
|
? licenseReplacements[x]
|
||||||
|
: x;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(pkg => {
|
||||||
|
return !_passesSpdx(pkg.licenses, allowedLicenses);
|
||||||
|
})
|
||||||
|
.filter(pkg => {
|
||||||
|
return !ignoredPackages.find(ignored => {
|
||||||
|
return ignored === pkg.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Report packages with bad licenses
|
||||||
|
if (badLicensePackages.length > 0) {
|
||||||
|
console.error('Invalid package licences found:');
|
||||||
|
badLicensePackages.forEach(pkg => {
|
||||||
|
console.error(`${pkg.id}: ${JSON.stringify(pkg.licenses)}`);
|
||||||
|
});
|
||||||
|
console.error(
|
||||||
|
`\n${badLicensePackages.length} total packages with invalid licenses.`
|
||||||
|
);
|
||||||
|
resolve(2);
|
||||||
|
} else {
|
||||||
|
console.info('All package licenses are valid.');
|
||||||
|
resolve(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main().then(code => {
|
||||||
|
return process.exit(code);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user