44 * It will search for blocked statements, which have been added in the commits and fail if present.
55 */
66
7- var child_process = require ( 'child_process' ) ;
8- var blocked_statements = [
9- 'ddescribe' ,
10- 'fdescribe' ,
11- 'iit' ,
12- 'fit' ,
13- 'xdescribe' ,
14- 'xit' ,
15- 'debugger;'
7+ const child_process = require ( 'child_process' ) ;
8+ const fs = require ( 'fs' ) ;
9+
10+ const exec = function ( cmd ) {
11+ return new Promise ( function ( resolve , reject ) {
12+ child_process . exec ( cmd , function ( err , stdout /*, stderr */ ) {
13+ if ( err ) {
14+ reject ( err ) ;
15+ } else {
16+ resolve ( stdout ) ;
17+ }
18+ } ) ;
19+ } ) ;
20+ } ;
21+
22+
23+ const blocked_statements = [
24+ '\\bddescribe\\(' ,
25+ '\\bfdescribe\\(' ,
26+ '\\biit\\(' ,
27+ '\\bfit\\(' ,
28+ '\\bxdescribe\\(' ,
29+ '\\bxit\\(' ,
30+ '\\bdebugger;'
1631] ;
1732
18- var blockedRegex = new RegExp ( '\\+.*(' + blocked_statements . join ( '|' ) + ').*$' , 'mg' ) ;
19- var commit_range = process . env . TRAVIS_COMMIT_RANGE || 'HEAD~1' ;
33+ const blockedRegex = new RegExp ( blocked_statements . join ( '|' ) , 'g' ) ;
34+
35+ /**
36+ * Find the fork point between HEAD of the current branch, and master.
37+ * @return {Promise<string> } A promise which resolves with the fork SHA (or reject).
38+ */
39+ function findForkPoint ( ) {
40+ return exec ( 'git merge-base --fork-point HEAD master' )
41+ . then ( function ( stdout ) {
42+ return stdout . split ( '\n' ) [ 0 ] ;
43+ } ) ;
44+ }
45+
46+ /**
47+ * Get the commit range to evaluate when this script is run.
48+ * @return {Promise<string> } A commit range of the form ref1...ref2.
49+ */
50+ function getCommitRange ( ) {
51+ if ( process . env [ 'TRAVIS_COMMIT_RANGE' ] ) {
52+ return Promise . resolve ( process . env [ 'TRAVIS_COMMIT_RANGE' ] ) ;
53+ } else {
54+ return findForkPoint ( ) . then ( ( forkPointSha ) => `${ forkPointSha } ...HEAD` ) ;
55+ }
56+ }
57+
58+ /**
59+ * List all the files that have been changed or added in the last commit range.
60+ * @returns {Promise<Array<string>> } Resolves with a list of files that are
61+ * added or changed.
62+ */
63+ function findChangedFiles ( ) {
64+ return getCommitRange ( )
65+ . then ( function ( range ) {
66+ return exec ( `git diff --name-status ${ range } ./src ./e2e` ) ;
67+ } )
68+ . then ( function ( rawDiff ) {
69+ // Ignore deleted files.
70+ return rawDiff . split ( '\n' )
71+ . filter ( function ( line ) {
72+ // Status: C## => Copied (##% confident)
73+ // R## => Renamed (##% confident)
74+ // D => Deleted
75+ // M => Modified
76+ // A => Added
77+ return line . match ( / ( [ C R ] [ 0 - 9 ] * | [ A M ] ) \s + / ) ;
78+ } )
79+ . map ( function ( line ) {
80+ return line . split ( / \s + / , 2 ) [ 1 ] ;
81+ } ) ;
82+ } ) ;
83+ }
2084
21- var diff = child_process . execSync ( `git diff --unified=0 ${ commit_range } ./src ./e2e` ) . toString ( ) ;
2285
23- if ( blockedRegex . test ( diff ) ) {
86+ // Find all files, check for errors, and output every errors found.
87+ findChangedFiles ( )
88+ . then ( function ( fileList ) {
89+ // Only match .js or .ts, and remove .d.ts files.
90+ return fileList . filter ( function ( name ) {
91+ return name . match ( / \. [ j t ] s $ / ) && ! name . match ( / \. d \. t s $ / ) ;
92+ } ) ;
93+ } )
94+ . then ( function ( fileList ) {
95+ // Read every file and return a Promise that will contain an array of
96+ // Object of the form { fileName, content }.
97+ return Promise . all ( fileList . map ( function ( fileName ) {
98+ return {
99+ fileName : fileName ,
100+ content : fs . readFileSync ( fileName , { encoding : 'utf-8' } )
101+ } ;
102+ } ) ) ;
103+ } )
104+ . then ( function ( diffList ) {
105+ // Reduce the diffList to an array of errors. The array will be empty if no errors
106+ // were found.
107+ return diffList . reduce ( function ( errors , diffEntry ) {
108+ let fileName = diffEntry . fileName ;
109+ let content = diffEntry . content . split ( '\n' ) ;
110+ let ln = 0 ;
24111
25- console . warn ( 'Warning: You are using a statement in your commit, which is not allowed.\n' +
26- 'Blocked Statements are: ' + blocked_statements . join ( ', ' ) + '\n' +
27- 'Please remove them, and the CI will continue.' ) ;
112+ // Get all the lines that start with `+`.
113+ content . forEach ( function ( line ) {
114+ ln ++ ;
28115
29- process . exit ( 1 ) ;
116+ let m = line . match ( blockedRegex ) ;
117+ if ( m ) {
118+ // Accumulate all errors at once.
119+ errors . push ( {
120+ fileName : fileName ,
121+ lineNumber : ln ,
122+ statement : m [ 0 ]
123+ } ) ;
124+ }
125+ } ) ;
126+ return errors ;
127+ } , [ ] ) ;
128+ } )
129+ . then ( function ( errors ) {
130+ if ( errors . length > 0 ) {
131+ console . error ( 'Error: You are using a statement in your commit, which is not allowed.' ) ;
132+ errors . forEach ( function ( entry ) {
133+ console . error ( ` ${ entry . fileName } @${ entry . lineNumber } , Statement: ${ entry . statement } .\n` ) ;
134+ } ) ;
30135
31- } else {
32- console . log ( 'Info: The commits have been analyzed and are valid!' ) ;
33- }
136+ process . exit ( 1 ) ;
137+ }
138+ } )
139+ . catch ( function ( err ) {
140+ // An error occured in this script. Output the error and the stack.
141+ console . error ( 'An error occured during execution:' ) ;
142+ console . error ( err ) ;
143+ console . error ( err . stack ) ;
144+ process . exit ( 2 ) ;
145+ } ) ;
0 commit comments