build: add tslint rule to verify rollup globals config (#5963)

Adds a custom tslint rule that ensures that we've added all of the necessary external modules to the Rollup config. This is helpful, because forgetting to add a module will log a warning, but it won't break the build necessarily, which is why we occasionally need PRs like #5930.
This commit is contained in:
Kristiyan Kostadinov
2017-07-31 21:13:33 +03:00
committed by tinayuangao
parent bf2336d51f
commit d9e6f7502a
4 changed files with 120 additions and 70 deletions
+71
View File
@@ -0,0 +1,71 @@
{
"tslib": "tslib",
"@angular/animations": "ng.animations",
"@angular/core": "ng.core",
"@angular/common": "ng.common",
"@angular/forms": "ng.forms",
"@angular/http": "ng.http",
"@angular/router": "ng.router",
"@angular/platform-browser": "ng.platformBrowser",
"@angular/platform-server": "ng.platformServer",
"@angular/platform-browser-dynamic": "ng.platformBrowserDynamic",
"@angular/platform-browser/animations": "ng.platformBrowser.animations",
"@angular/core/testing": "ng.core.testing",
"@angular/common/testing": "ng.common.testing",
"@angular/http/testing": "ng.http.testing",
"@angular/material": "ng.material",
"@angular/cdk/a11y": "ng.cdk.a11y",
"@angular/cdk/bidi": "ng.cdk.bidi",
"@angular/cdk/coercion": "ng.cdk.coercion",
"@angular/cdk/keyboard": "ng.cdk.keyboard",
"@angular/cdk/observe-content": "ng.cdk.observeContent",
"@angular/cdk/platform": "ng.cdk.platform",
"@angular/cdk/portal": "ng.cdk.portal",
"@angular/cdk/rxjs": "ng.cdk.rxjs",
"@angular/cdk/table": "ng.cdk.table",
"@angular/cdk": "ng.cdk",
"@angular/cdk/testing": "ng.cdk.testing",
"@angular/material-examples": "ng.materialExamples",
"rxjs/BehaviorSubject": "Rx",
"rxjs/Observable": "Rx",
"rxjs/Subject": "Rx",
"rxjs/Subscription": "Rx",
"rxjs/Observer": "Rx",
"rxjs/Scheduler": "Rx",
"rxjs/observable/combineLatest": "Rx.Observable",
"rxjs/observable/forkJoin": "Rx.Observable",
"rxjs/observable/fromEvent": "Rx.Observable",
"rxjs/observable/merge": "Rx.Observable",
"rxjs/observable/of": "Rx.Observable",
"rxjs/observable/throw": "Rx.Observable",
"rxjs/operator/auditTime": "Rx.Observable.prototype",
"rxjs/operator/catch": "Rx.Observable.prototype",
"rxjs/operator/debounceTime": "Rx.Observable.prototype",
"rxjs/operator/do": "Rx.Observable.prototype",
"rxjs/operator/filter": "Rx.Observable.prototype",
"rxjs/operator/finally": "Rx.Observable.prototype",
"rxjs/operator/first": "Rx.Observable.prototype",
"rxjs/operator/let": "Rx.Observable.prototype",
"rxjs/operator/map": "Rx.Observable.prototype",
"rxjs/operator/share": "Rx.Observable.prototype",
"rxjs/operator/startWith": "Rx.Observable.prototype",
"rxjs/operator/switchMap": "Rx.Observable.prototype",
"rxjs/operator/takeUntil": "Rx.Observable.prototype",
"rxjs/operator/toPromise": "Rx.Observable.prototype",
"rxjs/add/observable/merge": "Rx.Observable",
"rxjs/add/observable/fromEvent": "Rx.Observable",
"rxjs/add/observable/of": "Rx.Observable",
"rxjs/add/observable/interval": "Rx.Observable",
"rxjs/add/operator/startWith": "Rx.Observable.prototype",
"rxjs/add/operator/map": "Rx.Observable.prototype",
"rxjs/add/operator/debounceTime": "Rx.Observable.prototype",
"rxjs/add/operator/distinctUntilChanged": "Rx.Observable.prototype",
"rxjs/add/operator/first": "Rx.Observable.prototype",
"rxjs/add/operator/catch": "Rx.Observable.prototype",
"rxjs/add/operator/switchMap": "Rx.Observable.prototype"
}
+1 -70
View File
@@ -4,76 +4,7 @@ import {rollupRemoveLicensesPlugin} from './rollup-remove-licenses';
// There are no type definitions available for these imports.
const rollup = require('rollup');
const rollupNodeResolutionPlugin = require('rollup-plugin-node-resolve');
const ROLLUP_GLOBALS = {
// Import tslib rather than having TypeScript output its helpers multiple times.
// See https://github.com/Microsoft/tslib
'tslib': 'tslib',
// Angular dependencies
'@angular/animations': 'ng.animations',
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/forms': 'ng.forms',
'@angular/http': 'ng.http',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',
'@angular/platform-browser/animations': 'ng.platformBrowser.animations',
// Local Angular packages inside of Material.
'@angular/material': 'ng.material',
// TODO(jelbourn): don't hard-code these
'@angular/cdk/a11y': 'ng.cdk.a11y',
'@angular/cdk/bidi': 'ng.cdk.bidi',
'@angular/cdk/coercion': 'ng.cdk.coercion',
'@angular/cdk/keyboard': 'ng.cdk.keyboard',
'@angular/cdk/observe-content': 'ng.cdk.observeContent',
'@angular/cdk/platform': 'ng.cdk.platform',
'@angular/cdk/portal': 'ng.cdk.portal',
'@angular/cdk/rxjs': 'ng.cdk.rxjs',
'@angular/cdk/table': 'ng.cdk.table',
'@angular/cdk': 'ng.cdk',
// RxJS dependencies
'rxjs/BehaviorSubject': 'Rx',
'rxjs/Observable': 'Rx',
'rxjs/Subject': 'Rx',
'rxjs/Subscription': 'Rx',
'rxjs/observable/combineLatest': 'Rx.Observable',
'rxjs/observable/forkJoin': 'Rx.Observable',
'rxjs/observable/fromEvent': 'Rx.Observable',
'rxjs/observable/merge': 'Rx.Observable',
'rxjs/observable/of': 'Rx.Observable',
'rxjs/observable/throw': 'Rx.Observable',
'rxjs/operator/auditTime': 'Rx.Observable.prototype',
'rxjs/operator/catch': 'Rx.Observable.prototype',
'rxjs/operator/debounceTime': 'Rx.Observable.prototype',
'rxjs/operator/do': 'Rx.Observable.prototype',
'rxjs/operator/filter': 'Rx.Observable.prototype',
'rxjs/operator/finally': 'Rx.Observable.prototype',
'rxjs/operator/first': 'Rx.Observable.prototype',
'rxjs/operator/let': 'Rx.Observable.prototype',
'rxjs/operator/map': 'Rx.Observable.prototype',
'rxjs/operator/share': 'Rx.Observable.prototype',
'rxjs/operator/startWith': 'Rx.Observable.prototype',
'rxjs/operator/switchMap': 'Rx.Observable.prototype',
'rxjs/operator/takeUntil': 'Rx.Observable.prototype',
'rxjs/operator/toPromise': 'Rx.Observable.prototype',
// RxJS imports for the examples package
'rxjs/add/observable/merge': 'Rx.Observable',
'rxjs/add/observable/fromEvent': 'Rx.Observable',
'rxjs/add/observable/of': 'Rx.Observable',
'rxjs/add/observable/interval': 'Rx.Observable',
'rxjs/add/operator/startWith': 'Rx.Observable.prototype',
'rxjs/add/operator/map': 'Rx.Observable.prototype',
'rxjs/add/operator/debounceTime': 'Rx.Observable.prototype',
'rxjs/add/operator/distinctUntilChanged': 'Rx.Observable.prototype',
'rxjs/add/operator/first': 'Rx.Observable.prototype',
'rxjs/add/operator/catch': 'Rx.Observable.prototype',
'rxjs/add/operator/switchMap': 'Rx.Observable.prototype',
};
const ROLLUP_GLOBALS = require('./rollup-globals.json');
export type BundleConfig = {
entry: string;
@@ -0,0 +1,43 @@
const path = require('path');
const Lint = require('tslint');
/**
* Rule that enforces that the specified external packages have been included in our Rollup config.
* Usage: [true, './path/to/rollup/config.json']
*/
class Rule extends Lint.Rules.AbstractRule {
apply(file) {
return this.applyWithWalker(new Walker(file, this.getOptions()));
}
}
class Walker extends Lint.RuleWalker {
constructor(file, options) {
super(...arguments);
if (!options.ruleArguments.length) {
throw Error('missing-rollup-globals: The Rollup config path has to be specified.');
}
const [configPath, ...whitelist] = options.ruleArguments;
this._configPath = path.resolve(process.cwd(), configPath);
this._config = require(this._configPath);
this._enabled = !whitelist.length || whitelist.some(p => new RegExp(p).test(file.fileName));
}
visitImportDeclaration(node) {
// Parse out the module name. The first and last characters are the quote marks.
const module = node.moduleSpecifier.getText().slice(1, -1);
const isExternal = !module.startsWith('.') && !module.startsWith('/');
// Check whether the module is external and whether it's in our config.
if (this._enabled && isExternal && !this._config[module]) {
this.addFailureAtNode(node, `Module "${module}" is missing from file ${this._configPath}.`);
}
super.visitImportDeclaration(node);
}
}
exports.Rule = Rule;
+5
View File
@@ -35,6 +35,11 @@
"src/lib",
"src/cdk"
],
"missing-rollup-globals": [
true,
"./tools/package-tools/rollup-globals.json",
"^((?!tools).)*$"
],
"one-line": [
true,
"check-catch",