Skip to content

Commit 68bc9e7

Browse files
committed
Scripts: Add support for license ignore
1 parent d0cb647 commit 68bc9e7

4 files changed

Lines changed: 67 additions & 6 deletions

File tree

packages/scripts/CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 2.3.0 (Unreleased)
2+
3+
### Improvements
4+
5+
- New flag `--ignore` for `check-licenses` script
6+
17
## 2.2.1 (2018-09-05)
28

39
### Bug Fix
@@ -8,7 +14,6 @@
814

915
- Updated dependencies: `jest`, `npm-package-json-lint` and `read-pkg-up`
1016

11-
1217
## 2.0.0 (2018-07-12)
1318

1419
### Breaking Change

packages/scripts/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,27 @@ This is how you execute those scripts using the presented setup:
6767
* `npm run test:help` - prints all available options to configure unit tests runner.
6868
* `npm run test:watch` - runs all unit tests in the watch mode.
6969

70+
### `wp-scripts check-licenses`
71+
72+
Validates that all dependencies of a project are compatible with the project's own license.
73+
74+
_Example:_
75+
76+
```json
77+
{
78+
"scripts": {
79+
"check-licenses": "wp-scripts check-licenses --prod --gpl2 --ignore=abab",
80+
}
81+
}
82+
```
83+
84+
_Flags_:
85+
86+
- `--prod` (or `--production`): When present, validates only `dependencies` and not `devDependencies`
87+
- `--dev` (or `--development`): When present, validates both `dependencies` and `devDependencies`
88+
- `--gpl2`: Validates against [GPLv2 license compatibility](https://www.gnu.org/licenses/license-list.en.html)
89+
- `--ignore=a,b,c`: A comma-separated set of package names to ignore for validation. This is intended to be used primarily in cases where a dependency's `license` field is malformed. It's assumed that any `ignored` package argument would be manually vetted for compatibility by the project owner.
90+
7091
## Inspiration
7192

7293
This is inspired by [react-scripts](https://www.npmjs.com/package/react-scripts) and [kcd-scripts](https://www.npmjs.com/package/kcd-scripts).

packages/scripts/scripts/check-licenses.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
*/
44
const spawn = require( 'cross-spawn' );
55
const { existsSync, readFileSync } = require( 'fs' );
6+
const { sep } = require( 'path' );
67
const chalk = require( 'chalk' );
78

89
/**
910
* Internal dependencies
1011
*/
11-
const { hasCliArg } = require( '../utils' );
12+
const { getCliArg, hasCliArg } = require( '../utils' );
1213

1314
/*
1415
* WARNING: Changes to this file may inadvertently cause us to distribute code that
@@ -24,6 +25,13 @@ const ERROR = chalk.reset.inverse.bold.red( ' ERROR ' );
2425
const prod = hasCliArg( '--prod' ) || hasCliArg( '--production' );
2526
const dev = hasCliArg( '--dev' ) || hasCliArg( '--development' );
2627
const gpl2 = hasCliArg( '--gpl2' );
28+
const ignored = hasCliArg( '--ignore' ) ?
29+
getCliArg( '--ignore' )
30+
// "--ignore=a, b" -> "[ 'a', ' b' ]"
31+
.split( ',' )
32+
// "[ 'a', ' b' ]" -> "[ 'a', 'b' ]"
33+
.map( ( moduleName ) => moduleName.trim() ) :
34+
[];
2735

2836
/*
2937
* A list of license strings that we've found to be GPL2 compatible.
@@ -155,6 +163,23 @@ const checkLicense = ( allowedLicense, licenseType ) => {
155163
return undefined !== subLicenseTypes.find( ( subLicenseType ) => checkLicense( allowedLicense, subLicenseType ) );
156164
};
157165

166+
/**
167+
* Returns true if the given module path is not to be ignored for consideration
168+
* in license validation, or false otherwise.
169+
*
170+
* @param {string} moduleName Module path.
171+
*
172+
* @return {boolean} Whether module path is not to be ignored.
173+
*/
174+
const isNotIgnoredModule = ( moduleName ) => (
175+
! ignored.some( ( ignoredItem ) => (
176+
// `moduleName` is a file path to the module directory. Assume CLI arg
177+
// is passed as basename of package (directory(s) after node_modules).
178+
// Prefix with sep to avoid false-positives on prefixing variations.
179+
moduleName.endsWith( sep + ignoredItem )
180+
) )
181+
);
182+
158183
// Use `npm ls` to grab a list of all the packages.
159184
const child = spawn.sync( 'npm', [
160185
'ls',
@@ -163,7 +188,10 @@ const child = spawn.sync( 'npm', [
163188
...( dev ? [ '--dev' ] : [] ),
164189
] );
165190

166-
const modules = child.stdout.toString().split( '\n' );
191+
const modules = child.stdout
192+
.toString()
193+
.split( '\n' )
194+
.filter( isNotIgnoredModule );
167195

168196
modules.forEach( ( path ) => {
169197
if ( ! path ) {

packages/scripts/utils/index.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@ const path = require( 'path' );
1111
const { getPackagePath, hasPackageProp } = require( './package' );
1212
const { exit, getCliArgs } = require( './process' );
1313

14-
const first = ( list ) => list[ 0 ];
14+
const getCliArg = ( arg ) => {
15+
for ( const cliArg of getCliArgs() ) {
16+
const [ name, value ] = cliArg.split( '=' );
17+
if ( name === arg ) {
18+
return value || null;
19+
}
20+
}
21+
};
1522

16-
const hasCliArg = ( arg ) => getCliArgs()
17-
.some( ( value ) => first( value.split( '=' ) ) === arg );
23+
const hasCliArg = ( arg ) => getCliArg( arg ) !== undefined;
1824

1925
const fromProjectRoot = ( fileName ) =>
2026
path.join( path.dirname( getPackagePath() ), fileName );
@@ -86,6 +92,7 @@ module.exports = {
8692
fromConfigRoot,
8793
getCliArgs,
8894
hasCliArg,
95+
getCliArg,
8996
hasProjectFile,
9097
hasPackageProp,
9198
spawnScript,

0 commit comments

Comments
 (0)