Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lint: ensure all files are owned by someone #7937

Merged
merged 2 commits into from
Oct 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 169 additions & 61 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,69 +1,177 @@
# Angular Material components
src/lib/list/** @jelbourn @crisbeto
src/lib/tooltip/** @andrewseguin
src/lib/button-toggle/** @tinayuangao
src/lib/snack-bar/** @jelbourn @crisbeto @josephperrott
src/lib/radio/** @tinayuangao @devversion
src/lib/card/** @jelbourn
src/lib/input/** @mmalerba
src/lib/progress-spinner/** @jelbourn @crisbeto @josephperrott
src/lib/datepicker/** @mmalerba
src/lib/sort/** @andrewseguin
src/lib/autocomplete/** @kara @crisbeto
src/lib/chips/** @tinayuangao
src/lib/icon/** @jelbourn
src/lib/dialog/** @jelbourn @crisbeto
src/lib/progress-bar/** @jelbourn @crisbeto @josephperrott
src/lib/grid-list/** @kara @jelbourn
src/lib/select/** @kara @crisbeto
src/lib/expansion/** @josephperrott @jelbourn
src/lib/slide-toggle/** @devversion
src/lib/toolbar/** @devversion
src/lib/button/** @tinayuangao
src/lib/checkbox/** @tinayuangao @devversion
src/lib/table/** @andrewseguin
src/lib/slider/** @mmalerba
src/lib/sidenav/** @mmalerba
src/lib/menu/** @kara @crisbeto
src/lib/paginator/** @andrewseguin
src/lib/tabs/** @andrewseguin
/src/lib/* @jelbourn
/src/lib/autocomplete/** @kara @crisbeto
/src/lib/button-toggle/** @tinayuangao
/src/lib/button/** @tinayuangao
/src/lib/card/** @jelbourn
/src/lib/checkbox/** @tinayuangao @devversion
/src/lib/chips/** @tinayuangao
/src/lib/datepicker/** @mmalerba
/src/lib/dialog/** @jelbourn @crisbeto
/src/lib/expansion/** @josephperrott @jelbourn
/src/lib/form-field/** @mmalerba
/src/lib/grid-list/** @kara @jelbourn
/src/lib/icon/** @jelbourn
/src/lib/input/** @mmalerba
/src/lib/list/** @jelbourn @crisbeto
/src/lib/menu/** @kara @crisbeto
/src/lib/paginator/** @andrewseguin
/src/lib/progress-bar/** @jelbourn @crisbeto @josephperrott
/src/lib/progress-spinner/** @jelbourn @crisbeto @josephperrott
/src/lib/radio/** @tinayuangao @devversion
/src/lib/select/** @kara @crisbeto
/src/lib/sidenav/** @mmalerba
/src/lib/slide-toggle/** @devversion
/src/lib/slider/** @mmalerba
/src/lib/snack-bar/** @jelbourn @crisbeto @josephperrott
/src/lib/sort/** @andrewseguin
/src/lib/stepper/** @mmalerba
/src/lib/table/** @andrewseguin
/src/lib/tabs/** @andrewseguin
/src/lib/toolbar/** @devversion
/src/lib/tooltip/** @andrewseguin

# Angular Material core
src/lib/core/selection/** @tinayuangao @jelbourn
src/lib/core/selection/pseudo*/** @crisbeto @jelbourn
src/lib/core/theming/** @jelbourn
src/lib/core/option/** @kara @crisbeto
src/lib/core/rxjs/** @jelbourn
src/lib/core/ripple/** @devversion
src/lib/core/a11y/** @jelbourn @devversion
src/lib/core/compatibility/** @jelbourn
src/lib/core/overlay/** @jelbourn @crisbeto
src/lib/core/overlay/scroll/** @andrewseguin @crisbeto
src/lib/core/platform/** @jelbourn @devversion
src/lib/core/bidi/** @jelbourn
src/lib/core/placeholder/** @kara @mmalerba
src/lib/core/portal/** @jelbourn
src/lib/core/typography/** @crisbeto
src/lib/core/datetime/** @mmalerba
/src/lib/core/* @jelbourn
/src/lib/core/animation/** @jelbourn
/src/lib/core/common-behaviors/** @jelbourn
/src/lib/core/compatibility/** @jelbourn
/src/lib/core/datetime/** @mmalerba
/src/lib/core/error/** @crisbeto @mmalerba
/src/lib/core/gestures/** @jelbourn
/src/lib/core/line/** @jelbourn
/src/lib/core/option/** @kara @crisbeto
/src/lib/core/placeholder/** @kara @mmalerba
/src/lib/core/ripple/** @devversion
/src/lib/core/selection/** @tinayuangao @jelbourn
/src/lib/core/selection/pseudo*/** @crisbeto @jelbourn
/src/lib/core/style/** @jelbourn
/src/lib/core/testing/** @jelbourn
/src/lib/core/theming/** @jelbourn
/src/lib/core/typography/** @crisbeto
/src/lib/core/util/** @jelbourn

# CDK
src/cdk/coercion/** @jelbourn
src/cdk/rxjs/** @jelbourn
src/cdk/observers/** @jelbourn @crisbeto
src/cdk/collections/** @jelbourn @crisbeto @andrewseguin
src/cdk/a11y/** @jelbourn @devversion
src/cdk/platform/** @jelbourn @devversion
src/cdk/bidi/** @jelbourn
src/cdk/table/** @andrewseguin
src/cdk/portal/** @jelbourn
/src/cdk/* @jelbourn
/src/cdk/a11y/** @jelbourn @devversion
/src/cdk/accordion/** @josephperrott
/src/cdk/bidi/** @jelbourn
/src/cdk/coercion/** @jelbourn
/src/cdk/collections/** @jelbourn @crisbeto @andrewseguin
/src/cdk/keycodes/** @jelbourn
/src/cdk/layout/** @josephperrott
/src/cdk/observers/** @jelbourn @crisbeto
/src/cdk/overlay/** @jelbourn @crisbeto
/src/cdk/platform/** @jelbourn @devversion
/src/cdk/portal/** @jelbourn
/src/cdk/rxjs/** @jelbourn
/src/cdk/scrolling/** @andrewseguin @crisbeto
/src/cdk/stepper/** @mmalerba
/src/cdk/table/** @andrewseguin
/src/cdk/testing/** @devversion

# Tooling
tools/** @devversion @jelbourn
test/** @devversion @jelbourn
scripts/** @devversion @jelbourn
# Moment adapter package
/src/material-moment-adapter/** @mmalerba

# Docs examples
src/material-examples/** @amcdnl @jelbourn
# Docs examples & guides
/guides/** @amcdnl @jelbourn
/src/material-examples/** @amcdnl @jelbourn

# Moment adapter package
src/material-moment-adapter/** @mmalerba
# Demo app
/src/demo-app/* @jelbourn
/src/demo-app/a11y/** @tinayuangao
/src/demo-app/autocomplete/** @kara @crisbeto
/src/demo-app/baseline/** @mmalerba
/src/demo-app/button-toggle/** @tinayuangao
/src/demo-app/button/** @tinayuangao
/src/demo-app/card/** @jelbourn
/src/demo-app/checkbox/** @tinayuangao @devversion
/src/demo-app/chips/** @tinayuangao
/src/demo-app/dataset/** @andrewseguin
/src/demo-app/datepicker/** @mmalerba
/src/demo-app/demo-app/** @jelbourn
/src/demo-app/dialog/** @jelbourn @crisbeto
/src/demo-app/drawer/** @mmalerba
/src/demo-app/expansion/** @josephperrott
/src/demo-app/focus-origin/** @mmalerba
/src/demo-app/gestures/** @jelbourn
/src/demo-app/grid-list/** @kara @jelbourn
/src/demo-app/icon/** @jelbourn
/src/demo-app/input/** @mmalerba
/src/demo-app/list/** @jelbourn @crisbeto
/src/demo-app/live-announcer/** @jelbourn
/src/demo-app/menu/** @kara @crisbeto
/src/demo-app/overlay/** @jelbourn @crisbeto
/src/demo-app/platform/** @jelbourn @devversion
/src/demo-app/portal/** @jelbourn
/src/demo-app/progress-bar/** @jelbourn @crisbeto @josephperrott
/src/demo-app/progress-spinner/** @jelbourn @crisbeto @josephperrott
/src/demo-app/radio/** @tinayuangao @devversion
/src/demo-app/ripple/** @devversion
/src/demo-app/screen-type/** @josephperrott
/src/demo-app/select/** @kara @crisbeto
/src/demo-app/sidenav/** @mmalerba
/src/demo-app/slide-toggle/** @devversion
/src/demo-app/slider/** @mmalerba
/src/demo-app/snack-bar/** @jelbourn @crisbeto @josephperrott
/src/demo-app/stepper/** @mmalerba
/src/demo-app/table/** @andrewseguin
/src/demo-app/tabs/** @andrewseguin
/src/demo-app/toolbar/** @devversion
/src/demo-app/tooltip/** @andrewseguin
/src/demo-app/typography/** @crisbeto

# E2E app
/e2e/* @jelbourn
/e2e/components/block-scroll-strategy-e2e.spec.ts @andrewseguin @crisbeto
/e2e/components/button-e2e.spec.ts @tinayuangao
/e2e/components/button-toggle-e2e.spec.ts @tinayuangao
/e2e/components/card-e2e.spec.ts @jelbourn
/e2e/components/checkbox-e2e.spec.ts @tinayuangao @devversion
/e2e/components/dialog-e2e.spec.ts @jelbourn @crisbeto
/e2e/components/expansion-e2e.spec.ts @josephperrott @jelbourn
/e2e/components/fullscreen-e2e.spec.ts @jelbourn
/e2e/components/grid-list-e2e.spec.ts @kara @jelbourn
/e2e/components/icon-e2e.spec.ts @jelbourn
/e2e/components/input-e2e.spec.ts @mmalerba
/e2e/components/list-e2e.spec.ts @jelbourn @crisbeto
/e2e/components/menu-e2e.spec.ts @kara @crisbeto
/e2e/components/progress-bar-e2e.spec.ts @jelbourn @crisbeto @josephperrott
/e2e/components/progress-spinner-e2e.spec.ts @jelbourn @crisbeto @josephperrott
/e2e/components/radio-e2e.spec.ts @tinayuangao @devversion
/e2e/components/sidenav-e2e.spec.ts @mmalerba
/e2e/components/slide-toggle-e2e.spec.ts @devversion
/e2e/components/stepper-e2e.spec.ts @mmalerba
/e2e/components/tabs-e2e.spec.ts @andrewseguin
/e2e/components/toolbar-e2e.spec.ts @devversion
/e2e/util/** @jelbourn
/src/e2e-app/* @jelbourn
/src/e2e-app/block-scroll-strategy/** @andrewseguin @crisbeto
/src/e2e-app/button/** @tinayuangao
/src/e2e-app/checkbox/** @tinayuangao @devversion
/src/e2e-app/dialog/** @jelbourn @crisbeto
/src/e2e-app/e2e-app/** @jelbourn
/src/e2e-app/fullscreen/** @jelbourn
/src/e2e-app/grid-list/** @kara @jelbourn
/src/e2e-app/icon/** @jelbourn
/src/e2e-app/input/** @mmalerba
/src/e2e-app/menu/** @kara @crisbeto
/src/e2e-app/progress-bar/** @jelbourn @crisbeto @josephperrott
/src/e2e-app/progress-spinner/** @jelbourn @crisbeto @josephperrott
/src/e2e-app/radio/** @tinayuangao @devversion
/src/e2e-app/sidenav/** @mmalerba
/src/e2e-app/slide-toggle/** @devversion
/src/e2e-app/tabs/** @andrewseguin

# Universal app
/src/universal-app/** @jelbourn

# Tooling
/scripts/** @devversion @jelbourn
/test/** @devversion @jelbourn
/tools/** @devversion @jelbourn

# Misc
/* @jelbourn
/.github/** @jelbourn
/src/* @jelbourn
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ node_modules
npm-debug.log
testem.log
/.chrome
/.git
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@types/fs-extra": "^3.0.1",
"@types/glob": "^5.0.30",
"@types/gulp": "3.8.32",
"@types/gulp-util": "^3.0.31",
"@types/hammerjs": "^2.0.34",
"@types/jasmine": "2.5.45",
"@types/merge2": "^0.3.30",
Expand Down
78 changes: 74 additions & 4 deletions tools/gulp/tasks/lint.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {red} from 'chalk';
import {readdirSync, readFileSync, statSync} from 'fs';
import {task} from 'gulp';
import {execNodeTask} from '../util/task_helpers';
import {join} from 'path';
import {colors, log} from 'gulp-util';
import {buildConfig} from 'material2-build-tools';
import {red} from 'chalk';
import {IMinimatch, Minimatch} from 'minimatch';
import {join} from 'path';
import {execNodeTask} from '../util/task_helpers';

// These types lack of type definitions
const madge = require('madge');
Expand All @@ -19,7 +22,13 @@ const materialOutPath = join(buildConfig.outputDir, 'packages', 'material');
/** Path to the output of the CDK package. */
const cdkOutPath = join(buildConfig.outputDir, 'packages', 'cdk');

task('lint', ['tslint', 'stylelint', 'madge']);
/** Path for the Github owners file. */
const ownersFilePath = '.github/CODEOWNERS';

/** Path for the .gitignore file. */
const gitIgnorePath = '.gitignore';

task('lint', ['tslint', 'stylelint', 'madge', 'ownerslint']);

/** Task to lint Angular Material's scss stylesheets. */
task('stylelint', execNodeTask(
Expand All @@ -46,6 +55,67 @@ task('madge', ['material:clean-build'], () => {
});
});

task('ownerslint', () => {
let errors = 0;

let ownedPaths = readFileSync(ownersFilePath, 'utf8').split('\n')
// Trim lines.
.map(line => line.trim())
// Remove empty lines and comments.
.filter(line => line && !line.startsWith('#'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't handle cases like /some/path owner1 owner2 #owner3.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will? it splits on white space and just cares about the first piece

// Split off just the path glob.
.map(line => line.split(/\s+/)[0])
// Turn paths into Minimatch objects.
.map(path => new Minimatch(path, {dot: true, matchBase: true}));

let ignoredPaths = readFileSync(gitIgnorePath, 'utf8').split('\n')
// Trim lines.
.map(line => line.trim())
// Remove empty lines and comments.
.filter(line => line && !line.startsWith('#'))
// Turn paths into Minimatch objects.
.map(path => new Minimatch(path, {dot: true, matchBase: true}));

for (let paths = getChildPaths('.'); paths.length;) {
paths = Array.prototype.concat(...paths
// Remove ignored paths
.filter(path => !ignoredPaths.reduce(
(isIgnored, ignoredPath) => isIgnored || ignoredPath.match('/' + path), false))
// Remove paths that match an owned path.
.filter(path => !ownedPaths.reduce(
(isOwned, ownedPath) => isOwned || isOwnedBy(path, ownedPath), false))
// Report an error for any files that didn't match any owned paths.
.filter(path => {
if (statSync(path).isFile()) {
log(colors.red(`No code owner found for "${path}".`));
errors++;
return false;
}
return true;
})
// Get the next level of children for any directories.
.map(path => getChildPaths(path)));
}

if (errors) {
throw Error(`Found ${errors} files with no owner.`);
}
});

/** Check if the given path is owned by the given owned path matcher. */
function isOwnedBy(path: string, ownedPath: IMinimatch) {
// If the owned path ends with `**` its safe to eliminate whole directories.
if (ownedPath.pattern.endsWith('**') || statSync(path).isFile()) {
return ownedPath.match('/' + path);
}
return false;
}

/** Get the immediate child paths of the given path. */
function getChildPaths(path: string) {
return readdirSync(path).map(child => join(path, child));
}

/** Returns a string that formats the graph of circular modules. */
function formatMadgeCircularModules(circularModules: string[][]): string {
return circularModules.map((modulePaths: string[]) => `\n - ${modulePaths.join(' > ')}`).join('');
Expand Down