1
1
import { task } from 'gulp' ;
2
- import { readdirSync , statSync , existsSync , mkdirSync } from 'fs' ;
3
- import { openScreenshotsCloudStorage , openFirebaseScreenshotsDatabase } from '../task_helpers' ;
2
+ import { readdirSync , statSync , existsSync , mkdirp } from 'fs-extra' ;
4
3
import * as path from 'path' ;
5
4
import * as admin from 'firebase-admin' ;
5
+ import { openScreenshotsBucket , openFirebaseScreenshotsDatabase } from '../task_helpers' ;
6
+ import { updateGithubStatus } from '../util-functions' ;
7
+
6
8
const request = require ( 'request' ) ;
7
9
const imageDiff = require ( 'image-diff' ) ;
8
10
9
11
const SCREENSHOT_DIR = './screenshots' ;
10
- const FIREBASE_FILELIST = 'screenshot/filenames' ;
11
12
const FIREBASE_REPORT = 'screenshot/reports' ;
12
13
13
14
/** Task which upload screenshots generated from e2e test. */
14
15
task ( 'screenshots' , ( ) => {
15
16
let prNumber = process . env [ 'TRAVIS_PULL_REQUEST' ] ;
16
17
if ( prNumber ) {
17
18
let database = openFirebaseScreenshotsDatabase ( ) ;
18
- return getScreenFilenames ( database )
19
- . then ( ( filenames : string [ ] ) => downloadAllGolds ( filenames , database , prNumber ) )
19
+ return getScreenshotFiles ( database )
20
+ . then ( ( files : any [ ] ) => downloadAllGoldsAndCompare ( files , database , prNumber ) )
20
21
. then ( ( results : boolean ) => updateResult ( database , prNumber , results ) )
21
22
. then ( ( result : boolean ) => updateGithubStatus ( result , prNumber ) )
22
- . then ( ( ) => setScreenFilenames ( database , prNumber ) )
23
23
. then ( ( ) => uploadScreenshots ( prNumber , 'diff' ) )
24
24
. then ( ( ) => uploadScreenshots ( prNumber , 'test' ) )
25
25
. then ( ( ) => updateTravis ( database , prNumber ) )
@@ -29,108 +29,92 @@ task('screenshots', () => {
29
29
30
30
function updateFileResult ( database : admin . database . Database , prNumber : string ,
31
31
filenameKey : string , result : boolean ) : admin . Promise < void > {
32
- return database . ref ( FIREBASE_REPORT ) . child ( ` ${ prNumber } / results/ ${ filenameKey } ` ) . set ( result ) ;
32
+ return database . ref ( FIREBASE_REPORT ) . child ( prNumber ) . child ( ' results' ) . child ( filenameKey ) . set ( result ) ;
33
33
}
34
34
35
35
function updateResult ( database : admin . database . Database , prNumber : string ,
36
- result : boolean ) : admin . Promise < void > {
37
- return database . ref ( FIREBASE_REPORT ) . child ( ` ${ prNumber } / result` ) . set ( result ) . then ( ( ) => result ) ;
36
+ result : boolean ) {
37
+ return database . ref ( FIREBASE_REPORT ) . child ( prNumber ) . child ( ' result' ) . set ( result ) . then ( ( ) => result ) ;
38
38
}
39
39
40
40
function updateTravis ( database : admin . database . Database ,
41
41
prNumber : string ) : admin . Promise < void > {
42
42
return database . ref ( FIREBASE_REPORT ) . child ( prNumber ) . update ( {
43
- ' commit' : process . env [ 'TRAVIS_COMMIT' ] ,
44
- ' sha' : process . env [ 'TRAVIS_PULL_REQUEST_SHA' ] ,
45
- ' travis' : process . env [ 'TRAVIS_JOB_ID' ] ,
43
+ commit : process . env [ 'TRAVIS_COMMIT' ] ,
44
+ sha : process . env [ 'TRAVIS_PULL_REQUEST_SHA' ] ,
45
+ travis : process . env [ 'TRAVIS_JOB_ID' ] ,
46
46
} ) ;
47
47
}
48
48
49
49
/** Get a list of filenames from firebase database. */
50
- function getScreenFilenames ( database : admin . database . Database ) : admin . Promise < string [ ] > {
51
- return database . ref ( FIREBASE_FILELIST ) . once ( 'value' )
52
- . then ( ( snapshots : admin . database . DataSnapshot ) => {
53
- return snapshots . val ( ) ;
50
+ function getScreenshotFiles ( database : admin . database . Database ) : admin . Promise < any [ ] > {
51
+ let bucket = openScreenshotsBucket ( ) ;
52
+ return bucket . getFiles ( { prefix : 'golds/' } ) . then ( function ( data : any ) {
53
+ return data [ 0 ] . filter ( ( file : any ) => file . name . endsWith ( '.screenshot.png' ) ) ;
54
54
} ) ;
55
55
}
56
56
57
- /** Upload a list of filenames to firebase database as gold. */
58
- function setScreenFilenames ( database : admin . database . Database ,
59
- reportKey ?: string ) : admin . Promise < void > {
60
- let filenames : string [ ] = [ ] ;
61
- readdirSync ( SCREENSHOT_DIR ) . map ( ( file : string ) => {
62
- let fullName = path . join ( SCREENSHOT_DIR , file ) ;
63
- let key = file . replace ( '.screenshot.png' , '' ) ;
64
- if ( ! statSync ( fullName ) . isDirectory ( ) && key ) {
65
- filenames . push ( file ) ;
66
- }
67
- } ) ;
68
- let filelistDatabase = reportKey ?
69
- database . ref ( FIREBASE_REPORT ) . child ( reportKey ) . child ( 'filenames' ) :
70
- database . ref ( FIREBASE_FILELIST ) ;
71
- return filelistDatabase . set ( filenames ) ;
57
+ function extractScreenshotName ( fileName : string ) {
58
+ return path . basename ( fileName , '.screenshot.png' ) ;
59
+ }
60
+
61
+ function getLocalScreenshotFiles ( dir : string ) : string [ ] {
62
+ return readdirSync ( dir )
63
+ . filter ( ( fileName : string ) => ! statSync ( path . join ( SCREENSHOT_DIR , fileName ) ) . isDirectory ( ) )
64
+ . filter ( ( fileName : string ) => fileName . endsWith ( '.screenshot.png' ) ) ;
72
65
}
73
66
74
67
/**
75
68
* Upload screenshots to google cloud storage.
76
- * @param { string } reportKey - The key used in firebase. Here it is the PR number.
77
- * If there's no reportKey , we will upload images to 'golds/' folder
78
- * @param { string } mode - Can be 'test' or 'diff' or null.
69
+ * @param prNumber - The key used in firebase. Here it is the PR number.
70
+ * If there's no prNumber , we will upload images to 'golds/' folder
71
+ * @param mode - Can be 'test' or 'diff' or null.
79
72
* If the images are the test results, mode should be 'test'.
80
73
* If the images are the diff images generated, mode should be 'diff'.
81
74
* For golds mode should be null.
82
75
*/
83
- function uploadScreenshots ( reportKey ?: string , mode ?: 'test' | 'diff' ) {
84
- let bucket = openScreenshotsCloudStorage ( ) ;
76
+ function uploadScreenshots ( prNumber ?: string , mode ?: 'test' | 'diff' ) {
77
+ let bucket = openScreenshotsBucket ( ) ;
85
78
86
79
let promises : admin . Promise < void > [ ] = [ ] ;
87
- let localDir = mode == 'diff' ? ` ${ SCREENSHOT_DIR } / diff` : SCREENSHOT_DIR ;
88
- readdirSync ( localDir ) . map ( ( file : string ) => {
80
+ let localDir = mode == 'diff' ? path . join ( SCREENSHOT_DIR , ' diff' ) : SCREENSHOT_DIR ;
81
+ getLocalScreenshotFiles ( localDir ) . forEach ( ( file : string ) => {
89
82
let fileName = path . join ( localDir , file ) ;
90
- let key = file . replace ( '.screenshot.png' , '' ) ;
91
- let destination = ( mode == null || ! reportKey ) ?
92
- `golds/${ file } ` : `screenshots/${ reportKey } /${ mode } /${ file } ` ;
93
-
94
- if ( ! statSync ( fileName ) . isDirectory ( ) && key ) {
95
- promises . push ( bucket . upload ( fileName , { destination : destination } ) ) ;
96
- }
83
+ let destination = ( mode == null || ! prNumber ) ?
84
+ `golds/${ file } ` : `screenshots/${ prNumber } /${ mode } /${ file } ` ;
85
+ promises . push ( bucket . upload ( fileName , { destination : destination } ) ) ;
97
86
} ) ;
98
87
return admin . Promise . all ( promises ) ;
99
88
}
100
89
101
- /** Check whether the directory exists. If not then create one. */
102
- function _makeDir ( dirName : string ) {
103
- if ( ! existsSync ( dirName ) ) {
104
- mkdirSync ( dirName , '744' ) ;
105
- }
106
- }
107
-
108
90
/** Download golds screenshots. */
109
- function downloadAllGolds (
110
- filenames : string [ ] , database : admin . database . Database ,
111
- reportKey : string ) : admin . Promise < boolean > {
112
- _makeDir ( `${ SCREENSHOT_DIR } /golds` ) ;
91
+ function downloadAllGoldsAndCompare (
92
+ files : any [ ] , database : admin . database . Database ,
93
+ prNumber : string ) : admin . Promise < boolean > {
94
+
95
+ mkdirp ( path . join ( SCREENSHOT_DIR , `golds` ) ) ;
96
+ mkdirp ( path . join ( SCREENSHOT_DIR , `diff` ) ) ;
113
97
114
- return admin . Promise . all ( filenames . map ( ( filename : string ) => {
115
- return downloadGold ( filename ) . then ( ( ) => diffScreenshot ( filename , database , reportKey ) ) ;
98
+ return admin . Promise . all ( files . map ( ( file : any ) => {
99
+ return downloadGold ( file ) . then ( ( ) => diffScreenshot ( file . name , database , prNumber ) ) ;
116
100
} ) ) . then ( ( results : boolean [ ] ) => results . every ( ( value : boolean ) => value == true ) ) ;
117
101
}
118
102
119
103
/** Download one gold screenshot */
120
- function downloadGold ( filename : string ) : Promise < void > {
121
- let bucket = openScreenshotsCloudStorage ( ) ;
122
- return bucket . file ( `golds/${ filename } ` ) . download ( {
123
- destination : `${ SCREENSHOT_DIR } /golds/${ filename } `
104
+ function downloadGold ( file : any ) : Promise < void > {
105
+ return file . download ( {
106
+ destination : path . join ( SCREENSHOT_DIR , file . name )
124
107
} ) ;
125
108
}
126
109
127
110
function diffScreenshot ( filename : string , database : admin . database . Database ,
128
- reportKey : string ) : admin . Promise < boolean > {
111
+ prNumber : string ) : admin . Promise < boolean > {
129
112
// TODO(tinayuangao): Run the downloads and diffs in parallel.
130
- let goldUrl = `${ SCREENSHOT_DIR } /golds/${ filename } ` ;
131
- let pullRequestUrl = `${ SCREENSHOT_DIR } /${ filename } ` ;
132
- let diffUrl = `${ SCREENSHOT_DIR } /diff/${ filename } ` ;
133
- let filenameKey = filename . replace ( '.screenshot.png' , '' ) ;
113
+ filename = path . basename ( filename ) ;
114
+ let goldUrl = path . join ( SCREENSHOT_DIR , `golds` , filename ) ;
115
+ let pullRequestUrl = path . join ( SCREENSHOT_DIR , filename ) ;
116
+ let diffUrl = path . join ( SCREENSHOT_DIR , `diff` , filename ) ;
117
+ let filenameKey = extractScreenshotName ( filename ) ;
134
118
135
119
if ( existsSync ( goldUrl ) && existsSync ( pullRequestUrl ) ) {
136
120
return new admin . Promise ( ( resolve : any , reject : any ) => {
@@ -145,46 +129,10 @@ function diffScreenshot(filename: string, database: admin.database.Database,
145
129
reject ( err ) ;
146
130
}
147
131
resolve ( imagesAreSame ) ;
148
- return updateFileResult ( database , reportKey , filenameKey , imagesAreSame ) ;
132
+ return updateFileResult ( database , prNumber , filenameKey , imagesAreSame ) ;
149
133
} ) ;
150
134
} ) ;
151
135
} else {
152
- return updateFileResult ( database , reportKey , filenameKey , false ) . then ( ( ) => false ) ;
136
+ return updateFileResult ( database , prNumber , filenameKey , false ) . then ( ( ) => false ) ;
153
137
}
154
138
}
155
-
156
- function decode ( value : string ) : string {
157
- return value . split ( '' ) . reverse ( ) . join ( '' ) ;
158
- }
159
-
160
- function updateGithubStatus ( result : boolean , prNumber : string ) {
161
- let state = result ? 'success' : 'failure' ;
162
- let sha = process . env [ 'TRAVIS_PULL_REQUEST_SHA' ] ;
163
- let token = decode ( process . env [ 'MATERIAL2_GITHUB_STATUS_TOKEN' ] ) ;
164
-
165
- let data = JSON . stringify ( {
166
- "state" : state ,
167
- "target_url" : `http://material2-screenshots.firebaseapp.com/${ prNumber } ` ,
168
- "context" : "screenshot-diff" ,
169
- "description" : `Screenshot test ${ state } `
170
- } ) ;
171
-
172
- let headers = {
173
- 'Authorization' : `token ${ token } ` ,
174
- 'User-Agent' : 'ScreenshotDiff/1.0.0' ,
175
- 'Content-Type' : 'application/json' ,
176
- 'Content-Length' : Buffer . byteLength ( data )
177
- } ;
178
-
179
- return new admin . Promise ( ( resolve , reject ) => {
180
- request ( {
181
- url : `https://api.github.com/repos/angular/material2/statuses/${ sha } ` ,
182
- method : 'POST' ,
183
- form : data ,
184
- headers : headers
185
- } , function ( error : any , response : any , body : any ) {
186
- resolve ( response . statusCode ) ;
187
- console . log ( response . statusCode ) ;
188
- } ) ;
189
- } ) ;
190
- }
0 commit comments