@@ -22,7 +22,33 @@ githubClient.authenticate({
2222 token : process . env . GITHUB_TOKEN
2323} )
2424
25- function pollAndComment ( owner , repoName , prId , checkNumber ) {
25+ function pollThenComment ( owner , repoName , prId ) {
26+ const prInfo = prInfoStr ( { owner, repoName, prId } )
27+
28+ // we have to figure out what type of Travis polling we should perform,
29+ // either by PR #id (as for nodejs.org) or commit sha (for readable-stream)
30+ travisClient . repos ( owner , repoName ) . builds . get ( ( err , res ) => {
31+ if ( err ) {
32+ return console . error ( `! ${ prInfo } Error while retrieving initial builds` , err . stack )
33+ }
34+
35+ const hasAnyPrBuilds = res . builds . some ( ( build ) => build . pull_request )
36+
37+ if ( hasAnyPrBuilds ) {
38+ pollByPrThenComment ( owner , repoName , prId )
39+ } else {
40+ pollByCommitThenComment ( owner , repoName , prId )
41+ }
42+ } )
43+ }
44+
45+ /**
46+ * When Travis CI picks up our PR's, we can poll and match builds
47+ * by their related PR #id.
48+ *
49+ * That's the case for nodejs.org.
50+ */
51+ function pollByPrThenComment ( owner , repoName , prId , checkNumber ) {
2652 checkNumber = checkNumber || 1
2753
2854 const prInfo = prInfoStr ( { owner, repoName, prId } )
@@ -56,7 +82,75 @@ function pollAndComment (owner, repoName, prId, checkNumber) {
5682 console . warn ( `! ${ prInfo } Was not able to find matching build, will do check #${ checkNumber + 1 } in 30 seconds` )
5783 }
5884
59- setTimeout ( pollAndComment , 30 * 1000 , owner , repoName , prId , checkNumber + 1 )
85+ setTimeout ( pollByPrThenComment , 30 * 1000 , owner , repoName , prId , checkNumber + 1 )
86+ } )
87+ }
88+
89+ /**
90+ * When Travis CI *doesn't* pick up our PR's, we have to poll and match builds
91+ * by the last commit SHA of the related PR.
92+ *
93+ * This is the case for readable-stream.
94+ */
95+ function pollByCommitThenComment ( owner , repoName , prId ) {
96+ const prInfo = prInfoStr ( { owner, repoName, prId } )
97+
98+ githubClient . pullRequests . getCommits ( {
99+ user : owner ,
100+ repo : repoName ,
101+ number : prId
102+ } , ( err , commitMetas ) => {
103+ if ( err ) {
104+ return console . error ( `! ${ prInfo } Got error when retrieving GitHub commits for PR` , err . stack )
105+ }
106+
107+ const lastSha = commitMetas . pop ( ) . sha
108+ pollTravisBuildBySha ( { owner, repoName, prId, lastSha } )
109+ console . log ( `* ${ prInfo } Started polling Travis for build by commit ${ lastSha . substr ( 0 , 7 ) } ` )
110+ } )
111+ }
112+
113+ function pollTravisBuildBySha ( options , checkNumber ) {
114+ const createGhComment = createGhCommentFn ( options )
115+ const prInfo = prInfoStr ( options )
116+ const shaToMatch = options . lastSha
117+
118+ checkNumber = checkNumber || 1
119+
120+ if ( checkNumber > 100 ) {
121+ console . warn ( `* ${ prInfo } Was not able to find matching build for PR, stopping poll now :(` )
122+ return
123+ }
124+
125+ travisClient . repos ( options . owner , options . repoName ) . builds . get ( ( err , res ) => {
126+ if ( err ) {
127+ return console . error ( `! ${ prInfo } Got error when retrieving Travis builds` , err . stack )
128+ }
129+
130+ const matchingCommit = res . commits . find ( ( commit ) => commit . sha === shaToMatch )
131+ if ( ! matchingCommit ) {
132+ console . warn ( `! ${ prInfo } Travis hasn't picked up last commit yet, will do check #${ checkNumber + 1 } in 30 seconds` )
133+ return setTimeout ( pollTravisBuildBySha , 30 * 1000 , options , checkNumber + 1 )
134+ }
135+
136+ const lastBuildForCommit = res . builds . find ( ( build ) => build . commit_id === matchingCommit . id )
137+ if ( lastBuildForCommit ) {
138+ const lastState = lastBuildForCommit . state
139+
140+ if ( lastState === 'passed' ) {
141+ return createGhComment ( `[Travis build passed](https://travis-ci.org/${ options . owner } /${ options . repoName } /builds/${ lastBuildForCommit . id } ) :+1:` )
142+ } else if ( lastState === 'failed' ) {
143+ return createGhComment ( `[Travis build failed](https://travis-ci.org/${ options . owner } /${ options . repoName } /builds/${ lastBuildForCommit . id } ) :-1:` )
144+ } else if ( ~ [ 'created' , 'started' ] . indexOf ( lastState ) ) {
145+ console . log ( `* ${ prInfo } "${ lastState } " build found, will do check #${ checkNumber + 1 } in 30 seconds` )
146+ } else {
147+ return console . log ( `* ${ prInfo } Unknown build state: "${ lastState } ", stopping polling` )
148+ }
149+ } else {
150+ console . warn ( `! ${ prInfo } Was not able to find matching build by last commit, will do check #${ checkNumber + 1 } in 30 seconds` )
151+ }
152+
153+ setTimeout ( pollTravisBuildBySha , 30 * 1000 , options , checkNumber + 1 )
60154 } )
61155}
62156
@@ -71,7 +165,7 @@ function createGhCommentFn (options) {
71165 body : message
72166 } , ( err , res ) => {
73167 if ( err ) {
74- return console . error ( `! ${ prInfo } Error from GitHub` , err . stack )
168+ return console . error ( `! ${ prInfo } Error while creating GitHub comment ` , err . stack )
75169 }
76170 console . log ( `* ${ prInfo } Github comment created` )
77171 } )
@@ -82,4 +176,4 @@ function prInfoStr (options) {
82176 return `${ options . owner } /${ options . repoName } /#${ options . prId } `
83177}
84178
85- exports . pollAndComment = pollAndComment
179+ exports . pollThenComment = pollThenComment
0 commit comments