Skip to content

Commit c46ba07

Browse files
authored
lint: ensure all files are owned by someone (#7937)
* lint: ensure all files are owned by someone * address comments
1 parent 64b566f commit c46ba07

File tree

4 files changed

+245
-65
lines changed

4 files changed

+245
-65
lines changed

.github/CODEOWNERS

Lines changed: 169 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,177 @@
11
# Angular Material components
2-
src/lib/list/** @jelbourn @crisbeto
3-
src/lib/tooltip/** @andrewseguin
4-
src/lib/button-toggle/** @tinayuangao
5-
src/lib/snack-bar/** @jelbourn @crisbeto @josephperrott
6-
src/lib/radio/** @tinayuangao @devversion
7-
src/lib/card/** @jelbourn
8-
src/lib/input/** @mmalerba
9-
src/lib/progress-spinner/** @jelbourn @crisbeto @josephperrott
10-
src/lib/datepicker/** @mmalerba
11-
src/lib/sort/** @andrewseguin
12-
src/lib/autocomplete/** @kara @crisbeto
13-
src/lib/chips/** @tinayuangao
14-
src/lib/icon/** @jelbourn
15-
src/lib/dialog/** @jelbourn @crisbeto
16-
src/lib/progress-bar/** @jelbourn @crisbeto @josephperrott
17-
src/lib/grid-list/** @kara @jelbourn
18-
src/lib/select/** @kara @crisbeto
19-
src/lib/expansion/** @josephperrott @jelbourn
20-
src/lib/slide-toggle/** @devversion
21-
src/lib/toolbar/** @devversion
22-
src/lib/button/** @tinayuangao
23-
src/lib/checkbox/** @tinayuangao @devversion
24-
src/lib/table/** @andrewseguin
25-
src/lib/slider/** @mmalerba
26-
src/lib/sidenav/** @mmalerba
27-
src/lib/menu/** @kara @crisbeto
28-
src/lib/paginator/** @andrewseguin
29-
src/lib/tabs/** @andrewseguin
2+
/src/lib/* @jelbourn
3+
/src/lib/autocomplete/** @kara @crisbeto
4+
/src/lib/button-toggle/** @tinayuangao
5+
/src/lib/button/** @tinayuangao
6+
/src/lib/card/** @jelbourn
7+
/src/lib/checkbox/** @tinayuangao @devversion
8+
/src/lib/chips/** @tinayuangao
9+
/src/lib/datepicker/** @mmalerba
10+
/src/lib/dialog/** @jelbourn @crisbeto
11+
/src/lib/expansion/** @josephperrott @jelbourn
12+
/src/lib/form-field/** @mmalerba
13+
/src/lib/grid-list/** @kara @jelbourn
14+
/src/lib/icon/** @jelbourn
15+
/src/lib/input/** @mmalerba
16+
/src/lib/list/** @jelbourn @crisbeto
17+
/src/lib/menu/** @kara @crisbeto
18+
/src/lib/paginator/** @andrewseguin
19+
/src/lib/progress-bar/** @jelbourn @crisbeto @josephperrott
20+
/src/lib/progress-spinner/** @jelbourn @crisbeto @josephperrott
21+
/src/lib/radio/** @tinayuangao @devversion
22+
/src/lib/select/** @kara @crisbeto
23+
/src/lib/sidenav/** @mmalerba
24+
/src/lib/slide-toggle/** @devversion
25+
/src/lib/slider/** @mmalerba
26+
/src/lib/snack-bar/** @jelbourn @crisbeto @josephperrott
27+
/src/lib/sort/** @andrewseguin
28+
/src/lib/stepper/** @mmalerba
29+
/src/lib/table/** @andrewseguin
30+
/src/lib/tabs/** @andrewseguin
31+
/src/lib/toolbar/** @devversion
32+
/src/lib/tooltip/** @andrewseguin
3033

3134
# Angular Material core
32-
src/lib/core/selection/** @tinayuangao @jelbourn
33-
src/lib/core/selection/pseudo*/** @crisbeto @jelbourn
34-
src/lib/core/theming/** @jelbourn
35-
src/lib/core/option/** @kara @crisbeto
36-
src/lib/core/rxjs/** @jelbourn
37-
src/lib/core/ripple/** @devversion
38-
src/lib/core/a11y/** @jelbourn @devversion
39-
src/lib/core/compatibility/** @jelbourn
40-
src/lib/core/overlay/** @jelbourn @crisbeto
41-
src/lib/core/overlay/scroll/** @andrewseguin @crisbeto
42-
src/lib/core/platform/** @jelbourn @devversion
43-
src/lib/core/bidi/** @jelbourn
44-
src/lib/core/placeholder/** @kara @mmalerba
45-
src/lib/core/portal/** @jelbourn
46-
src/lib/core/typography/** @crisbeto
47-
src/lib/core/datetime/** @mmalerba
35+
/src/lib/core/* @jelbourn
36+
/src/lib/core/animation/** @jelbourn
37+
/src/lib/core/common-behaviors/** @jelbourn
38+
/src/lib/core/compatibility/** @jelbourn
39+
/src/lib/core/datetime/** @mmalerba
40+
/src/lib/core/error/** @crisbeto @mmalerba
41+
/src/lib/core/gestures/** @jelbourn
42+
/src/lib/core/line/** @jelbourn
43+
/src/lib/core/option/** @kara @crisbeto
44+
/src/lib/core/placeholder/** @kara @mmalerba
45+
/src/lib/core/ripple/** @devversion
46+
/src/lib/core/selection/** @tinayuangao @jelbourn
47+
/src/lib/core/selection/pseudo*/** @crisbeto @jelbourn
48+
/src/lib/core/style/** @jelbourn
49+
/src/lib/core/testing/** @jelbourn
50+
/src/lib/core/theming/** @jelbourn
51+
/src/lib/core/typography/** @crisbeto
52+
/src/lib/core/util/** @jelbourn
4853

4954
# CDK
50-
src/cdk/coercion/** @jelbourn
51-
src/cdk/rxjs/** @jelbourn
52-
src/cdk/observers/** @jelbourn @crisbeto
53-
src/cdk/collections/** @jelbourn @crisbeto @andrewseguin
54-
src/cdk/a11y/** @jelbourn @devversion
55-
src/cdk/platform/** @jelbourn @devversion
56-
src/cdk/bidi/** @jelbourn
57-
src/cdk/table/** @andrewseguin
58-
src/cdk/portal/** @jelbourn
55+
/src/cdk/* @jelbourn
56+
/src/cdk/a11y/** @jelbourn @devversion
57+
/src/cdk/accordion/** @josephperrott
58+
/src/cdk/bidi/** @jelbourn
59+
/src/cdk/coercion/** @jelbourn
60+
/src/cdk/collections/** @jelbourn @crisbeto @andrewseguin
61+
/src/cdk/keycodes/** @jelbourn
62+
/src/cdk/layout/** @josephperrott
63+
/src/cdk/observers/** @jelbourn @crisbeto
64+
/src/cdk/overlay/** @jelbourn @crisbeto
65+
/src/cdk/platform/** @jelbourn @devversion
66+
/src/cdk/portal/** @jelbourn
67+
/src/cdk/rxjs/** @jelbourn
68+
/src/cdk/scrolling/** @andrewseguin @crisbeto
69+
/src/cdk/stepper/** @mmalerba
70+
/src/cdk/table/** @andrewseguin
71+
/src/cdk/testing/** @devversion
5972

60-
# Tooling
61-
tools/** @devversion @jelbourn
62-
test/** @devversion @jelbourn
63-
scripts/** @devversion @jelbourn
73+
# Moment adapter package
74+
/src/material-moment-adapter/** @mmalerba
6475

65-
# Docs examples
66-
src/material-examples/** @amcdnl @jelbourn
76+
# Docs examples & guides
77+
/guides/** @amcdnl @jelbourn
78+
/src/material-examples/** @amcdnl @jelbourn
6779

68-
# Moment adapter package
69-
src/material-moment-adapter/** @mmalerba
80+
# Demo app
81+
/src/demo-app/* @jelbourn
82+
/src/demo-app/a11y/** @tinayuangao
83+
/src/demo-app/autocomplete/** @kara @crisbeto
84+
/src/demo-app/baseline/** @mmalerba
85+
/src/demo-app/button-toggle/** @tinayuangao
86+
/src/demo-app/button/** @tinayuangao
87+
/src/demo-app/card/** @jelbourn
88+
/src/demo-app/checkbox/** @tinayuangao @devversion
89+
/src/demo-app/chips/** @tinayuangao
90+
/src/demo-app/dataset/** @andrewseguin
91+
/src/demo-app/datepicker/** @mmalerba
92+
/src/demo-app/demo-app/** @jelbourn
93+
/src/demo-app/dialog/** @jelbourn @crisbeto
94+
/src/demo-app/drawer/** @mmalerba
95+
/src/demo-app/expansion/** @josephperrott
96+
/src/demo-app/focus-origin/** @mmalerba
97+
/src/demo-app/gestures/** @jelbourn
98+
/src/demo-app/grid-list/** @kara @jelbourn
99+
/src/demo-app/icon/** @jelbourn
100+
/src/demo-app/input/** @mmalerba
101+
/src/demo-app/list/** @jelbourn @crisbeto
102+
/src/demo-app/live-announcer/** @jelbourn
103+
/src/demo-app/menu/** @kara @crisbeto
104+
/src/demo-app/overlay/** @jelbourn @crisbeto
105+
/src/demo-app/platform/** @jelbourn @devversion
106+
/src/demo-app/portal/** @jelbourn
107+
/src/demo-app/progress-bar/** @jelbourn @crisbeto @josephperrott
108+
/src/demo-app/progress-spinner/** @jelbourn @crisbeto @josephperrott
109+
/src/demo-app/radio/** @tinayuangao @devversion
110+
/src/demo-app/ripple/** @devversion
111+
/src/demo-app/screen-type/** @josephperrott
112+
/src/demo-app/select/** @kara @crisbeto
113+
/src/demo-app/sidenav/** @mmalerba
114+
/src/demo-app/slide-toggle/** @devversion
115+
/src/demo-app/slider/** @mmalerba
116+
/src/demo-app/snack-bar/** @jelbourn @crisbeto @josephperrott
117+
/src/demo-app/stepper/** @mmalerba
118+
/src/demo-app/table/** @andrewseguin
119+
/src/demo-app/tabs/** @andrewseguin
120+
/src/demo-app/toolbar/** @devversion
121+
/src/demo-app/tooltip/** @andrewseguin
122+
/src/demo-app/typography/** @crisbeto
123+
124+
# E2E app
125+
/e2e/* @jelbourn
126+
/e2e/components/block-scroll-strategy-e2e.spec.ts @andrewseguin @crisbeto
127+
/e2e/components/button-e2e.spec.ts @tinayuangao
128+
/e2e/components/button-toggle-e2e.spec.ts @tinayuangao
129+
/e2e/components/card-e2e.spec.ts @jelbourn
130+
/e2e/components/checkbox-e2e.spec.ts @tinayuangao @devversion
131+
/e2e/components/dialog-e2e.spec.ts @jelbourn @crisbeto
132+
/e2e/components/expansion-e2e.spec.ts @josephperrott @jelbourn
133+
/e2e/components/fullscreen-e2e.spec.ts @jelbourn
134+
/e2e/components/grid-list-e2e.spec.ts @kara @jelbourn
135+
/e2e/components/icon-e2e.spec.ts @jelbourn
136+
/e2e/components/input-e2e.spec.ts @mmalerba
137+
/e2e/components/list-e2e.spec.ts @jelbourn @crisbeto
138+
/e2e/components/menu-e2e.spec.ts @kara @crisbeto
139+
/e2e/components/progress-bar-e2e.spec.ts @jelbourn @crisbeto @josephperrott
140+
/e2e/components/progress-spinner-e2e.spec.ts @jelbourn @crisbeto @josephperrott
141+
/e2e/components/radio-e2e.spec.ts @tinayuangao @devversion
142+
/e2e/components/sidenav-e2e.spec.ts @mmalerba
143+
/e2e/components/slide-toggle-e2e.spec.ts @devversion
144+
/e2e/components/stepper-e2e.spec.ts @mmalerba
145+
/e2e/components/tabs-e2e.spec.ts @andrewseguin
146+
/e2e/components/toolbar-e2e.spec.ts @devversion
147+
/e2e/util/** @jelbourn
148+
/src/e2e-app/* @jelbourn
149+
/src/e2e-app/block-scroll-strategy/** @andrewseguin @crisbeto
150+
/src/e2e-app/button/** @tinayuangao
151+
/src/e2e-app/checkbox/** @tinayuangao @devversion
152+
/src/e2e-app/dialog/** @jelbourn @crisbeto
153+
/src/e2e-app/e2e-app/** @jelbourn
154+
/src/e2e-app/fullscreen/** @jelbourn
155+
/src/e2e-app/grid-list/** @kara @jelbourn
156+
/src/e2e-app/icon/** @jelbourn
157+
/src/e2e-app/input/** @mmalerba
158+
/src/e2e-app/menu/** @kara @crisbeto
159+
/src/e2e-app/progress-bar/** @jelbourn @crisbeto @josephperrott
160+
/src/e2e-app/progress-spinner/** @jelbourn @crisbeto @josephperrott
161+
/src/e2e-app/radio/** @tinayuangao @devversion
162+
/src/e2e-app/sidenav/** @mmalerba
163+
/src/e2e-app/slide-toggle/** @devversion
164+
/src/e2e-app/tabs/** @andrewseguin
165+
166+
# Universal app
167+
/src/universal-app/** @jelbourn
168+
169+
# Tooling
170+
/scripts/** @devversion @jelbourn
171+
/test/** @devversion @jelbourn
172+
/tools/** @devversion @jelbourn
173+
174+
# Misc
175+
/* @jelbourn
176+
/.github/** @jelbourn
177+
/src/* @jelbourn

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ node_modules
3434
npm-debug.log
3535
testem.log
3636
/.chrome
37+
/.git

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@types/fs-extra": "^3.0.1",
5151
"@types/glob": "^5.0.30",
5252
"@types/gulp": "3.8.32",
53+
"@types/gulp-util": "^3.0.31",
5354
"@types/hammerjs": "^2.0.34",
5455
"@types/jasmine": "2.5.45",
5556
"@types/merge2": "^0.3.30",

tools/gulp/tasks/lint.ts

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import {red} from 'chalk';
2+
import {readdirSync, readFileSync, statSync} from 'fs';
13
import {task} from 'gulp';
2-
import {execNodeTask} from '../util/task_helpers';
3-
import {join} from 'path';
4+
import {colors, log} from 'gulp-util';
45
import {buildConfig} from 'material2-build-tools';
5-
import {red} from 'chalk';
6+
import {IMinimatch, Minimatch} from 'minimatch';
7+
import {join} from 'path';
8+
import {execNodeTask} from '../util/task_helpers';
69

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

22-
task('lint', ['tslint', 'stylelint', 'madge']);
25+
/** Path for the Github owners file. */
26+
const ownersFilePath = '.github/CODEOWNERS';
27+
28+
/** Path for the .gitignore file. */
29+
const gitIgnorePath = '.gitignore';
30+
31+
task('lint', ['tslint', 'stylelint', 'madge', 'ownerslint']);
2332

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

58+
task('ownerslint', () => {
59+
let errors = 0;
60+
61+
let ownedPaths = readFileSync(ownersFilePath, 'utf8').split('\n')
62+
// Trim lines.
63+
.map(line => line.trim())
64+
// Remove empty lines and comments.
65+
.filter(line => line && !line.startsWith('#'))
66+
// Split off just the path glob.
67+
.map(line => line.split(/\s+/)[0])
68+
// Turn paths into Minimatch objects.
69+
.map(path => new Minimatch(path, {dot: true, matchBase: true}));
70+
71+
let ignoredPaths = readFileSync(gitIgnorePath, 'utf8').split('\n')
72+
// Trim lines.
73+
.map(line => line.trim())
74+
// Remove empty lines and comments.
75+
.filter(line => line && !line.startsWith('#'))
76+
// Turn paths into Minimatch objects.
77+
.map(path => new Minimatch(path, {dot: true, matchBase: true}));
78+
79+
for (let paths = getChildPaths('.'); paths.length;) {
80+
paths = Array.prototype.concat(...paths
81+
// Remove ignored paths
82+
.filter(path => !ignoredPaths.reduce(
83+
(isIgnored, ignoredPath) => isIgnored || ignoredPath.match('/' + path), false))
84+
// Remove paths that match an owned path.
85+
.filter(path => !ownedPaths.reduce(
86+
(isOwned, ownedPath) => isOwned || isOwnedBy(path, ownedPath), false))
87+
// Report an error for any files that didn't match any owned paths.
88+
.filter(path => {
89+
if (statSync(path).isFile()) {
90+
log(colors.red(`No code owner found for "${path}".`));
91+
errors++;
92+
return false;
93+
}
94+
return true;
95+
})
96+
// Get the next level of children for any directories.
97+
.map(path => getChildPaths(path)));
98+
}
99+
100+
if (errors) {
101+
throw Error(`Found ${errors} files with no owner.`);
102+
}
103+
});
104+
105+
/** Check if the given path is owned by the given owned path matcher. */
106+
function isOwnedBy(path: string, ownedPath: IMinimatch) {
107+
// If the owned path ends with `**` its safe to eliminate whole directories.
108+
if (ownedPath.pattern.endsWith('**') || statSync(path).isFile()) {
109+
return ownedPath.match('/' + path);
110+
}
111+
return false;
112+
}
113+
114+
/** Get the immediate child paths of the given path. */
115+
function getChildPaths(path: string) {
116+
return readdirSync(path).map(child => join(path, child));
117+
}
118+
49119
/** Returns a string that formats the graph of circular modules. */
50120
function formatMadgeCircularModules(circularModules: string[][]): string {
51121
return circularModules.map((modulePaths: string[]) => `\n - ${modulePaths.join(' > ')}`).join('');

0 commit comments

Comments
 (0)