@@ -4,66 +4,145 @@ const moment = require('moment');
4
4
const GithubUtils = require ( '../../libs/GithubUtils' ) ;
5
5
const GitUtils = require ( '../../libs/GitUtils' ) ;
6
6
7
- const newVersion = core . getInput ( 'NPM_VERSION' ) ;
8
-
9
-
10
- GithubUtils . getStagingDeployCash ( )
11
- . then ( ( ) => GithubUtils . updateStagingDeployCash (
12
- newVersion ,
13
- _ . filter (
14
- _ . map ( core . getInput ( 'NEW_PULL_REQUESTS' ) . split ( ',' ) , PR => PR . trim ( ) ) ,
15
- PR => ! _ . isEmpty ( PR ) ,
16
- ) ,
17
- _ . filter (
18
- _ . map ( core . getInput ( 'NEW_DEPLOY_BLOCKERS' ) . split ( ',' ) , deployBlocker => deployBlocker . trim ( ) ) ,
19
- PR => ! _ . isEmpty ( PR ) ,
20
- ) ,
21
- ) )
22
- . then ( ( { data} ) => {
23
- console . log ( 'Successfully updated StagingDeployCash! 🎉' , data . html_url ) ;
24
- process . exit ( 0 ) ;
25
- } )
26
- . catch ( ( err ) => {
27
- // Unable to find the open StagingDeployCash
28
- if ( err && err . code === 404 ) {
29
- console . log ( 'No open StagingDeployCash found, creating a new one.' ) ;
30
-
31
- // Fetch all the StagingDeployCash issues
32
- return GithubUtils . octokit . issues . listForRepo ( {
33
- log : console ,
7
+ const run = function ( ) {
8
+ const newVersion = core . getInput ( 'NPM_VERSION' ) ;
9
+
10
+ let shouldCreateNewStagingDeployCash = false ;
11
+ let currentStagingDeployCashIssueNumber = null ;
12
+
13
+ // Start by fetching the list of recent StagingDeployCash issues, along with the list of open deploy blockers
14
+ return Promise . all ( [
15
+ GithubUtils . octokit . issues . listForRepo ( {
16
+ log : console ,
17
+ owner : GithubUtils . GITHUB_OWNER ,
18
+ repo : GithubUtils . EXPENSIFY_CASH_REPO ,
19
+ labels : GithubUtils . STAGING_DEPLOY_CASH_LABEL ,
20
+ } ) ,
21
+ GithubUtils . octokit . issues . listForRepo ( {
22
+ log : console ,
23
+ owner : GithubUtils . GITHUB_OWNER ,
24
+ repo : GithubUtils . EXPENSIFY_CASH_REPO ,
25
+ labels : GithubUtils . DEPLOY_BLOCKER_CASH_LABEL ,
26
+ state : 'open' ,
27
+ } ) ,
28
+ ] )
29
+ . then ( ( results ) => {
30
+ const [ stagingDeployResponse , deployBlockerResponse ] = results ;
31
+ if ( ! stagingDeployResponse || ! stagingDeployResponse . data || _ . isEmpty ( stagingDeployResponse . data ) ) {
32
+ console . error ( 'Failed fetching StagingDeployCash issues from Github!' , stagingDeployResponse ) ;
33
+ throw new Error ( 'Failed fetching StagingDeployCash issues from Github' ) ;
34
+ }
35
+
36
+ if ( ! deployBlockerResponse || ! deployBlockerResponse . data ) {
37
+ console . log ( 'Failed fetching DeployBlockerCash issues from Github, continuing...' ) ;
38
+ }
39
+
40
+ // Look at the state of the most recent StagingDeployCash,
41
+ // if it is open then we'll update the existing one, otherwise, we'll create a new one.
42
+ shouldCreateNewStagingDeployCash = Boolean ( stagingDeployResponse . data [ 0 ] . state !== 'open' ) ;
43
+
44
+ // Parse the data from the previous StagingDeployCash
45
+ // (newest if there are none open, otherwise second-newest)
46
+ const previousStagingDeployCashData = shouldCreateNewStagingDeployCash
47
+ ? GithubUtils . getStagingDeployCashData ( stagingDeployResponse . data [ 0 ] )
48
+ : GithubUtils . getStagingDeployCashData ( stagingDeployResponse . data [ 1 ] ) ;
49
+
50
+ console . log ( 'Found tag of previous StagingDeployCash:' , previousStagingDeployCashData . tag ) ;
51
+
52
+ // Find the list of PRs merged between the last StagingDeployCash and the new version
53
+ const mergedPRs = GitUtils . getPullRequestsMergedBetween ( previousStagingDeployCashData . tag , newVersion ) ;
54
+
55
+ if ( shouldCreateNewStagingDeployCash ) {
56
+ // We're in the create flow, not update
57
+ // TODO: if there are open DeployBlockers and we are opening a new checklist,
58
+ // then we should close / remove the DeployBlockerCash label from those
59
+ return GithubUtils . generateStagingDeployCashBody ( newVersion , mergedPRs ) ;
60
+ }
61
+
62
+ // There is an open StagingDeployCash, so we'll be updating it, not creating a new one
63
+ const currentStagingDeployCashData = GithubUtils . getStagingDeployCashData ( stagingDeployResponse . data [ 0 ] ) ;
64
+ currentStagingDeployCashIssueNumber = currentStagingDeployCashData . number ;
65
+
66
+ const newDeployBlockers = _ . map ( deployBlockerResponse . data , ( { url} ) => ( {
67
+ url,
68
+ number : GithubUtils . getIssueOrPullRequestNumberFromURL ( url ) ,
69
+ isResolved : false ,
70
+ } ) ) ;
71
+
72
+ // If we aren't sent a tag, then use the existing tag
73
+ const tag = newVersion || currentStagingDeployCashData . tag ;
74
+
75
+ // Generate the PR list, preserving the previous state of `isVerified` for existing PRs
76
+ const PRList = _ . sortBy (
77
+ _ . unique (
78
+ _ . union ( currentStagingDeployCashData . PRList , _ . map ( mergedPRs , url => ( {
79
+ url,
80
+ number : GithubUtils . getPullRequestNumberFromURL ( url ) ,
81
+
82
+ // Since this is the second argument to _.union,
83
+ // it will appear later in the array than any duplicate.
84
+ // Since it is later in the array, it will be truncated by _.unique,
85
+ // and the original value of isVerified will be preserved.
86
+ isVerified : false ,
87
+ } ) ) ) ,
88
+ false ,
89
+ item => item . number ,
90
+ ) ,
91
+ 'number' ,
92
+ ) ;
93
+
94
+ // Generate the deploy blocker list, preserving the previous state of `isResolved`
95
+ const deployBlockers = _ . sortBy (
96
+ _ . unique (
97
+ _ . union ( currentStagingDeployCashData . deployBlockers , newDeployBlockers ) ,
98
+ false ,
99
+ item => item . number ,
100
+ ) ,
101
+ 'number' ,
102
+ ) ;
103
+
104
+ return GithubUtils . generateStagingDeployCashBody (
105
+ tag ,
106
+ _ . pluck ( PRList , 'url' ) ,
107
+ _ . pluck ( _ . where ( PRList , { isVerified : true } ) , 'url' ) ,
108
+ _ . pluck ( deployBlockers , 'url' ) ,
109
+ _ . pluck ( _ . where ( deployBlockers , { isResolved : true } ) , 'url' ) ,
110
+ ) ;
111
+ } )
112
+ . then ( ( body ) => {
113
+ const defaultPayload = {
34
114
owner : GithubUtils . GITHUB_OWNER ,
35
115
repo : GithubUtils . EXPENSIFY_CASH_REPO ,
36
- labels : GithubUtils . STAGING_DEPLOY_CASH_LABEL ,
37
- state : 'closed' ,
116
+ body,
117
+ } ;
118
+
119
+ if ( shouldCreateNewStagingDeployCash ) {
120
+ return GithubUtils . octokit . issues . create ( {
121
+ ...defaultPayload ,
122
+ title : `Deploy Checklist: Expensify.cash ${ moment ( ) . format ( 'YYYY-MM-DD' ) } ` ,
123
+ labels : [ GithubUtils . STAGING_DEPLOY_CASH_LABEL ] ,
124
+ assignees : [ GithubUtils . APPLAUSE_BOT ] ,
125
+ } ) ;
126
+ }
127
+
128
+ return GithubUtils . octokit . issues . update ( {
129
+ ...defaultPayload ,
130
+ issue_number : currentStagingDeployCashIssueNumber ,
38
131
} ) ;
39
- }
40
-
41
- // Unexpected error!
42
- console . error ( 'Unexpected error occurred finding the StagingDeployCash!'
43
- + ' There may have been more than one open StagingDeployCash found,'
44
- + ' or there was some other problem with the Github API request.' , err ) ;
45
- core . setFailed ( err ) ;
46
- } )
47
- . then ( ( githubResponse ) => {
48
- if ( ! githubResponse || ! githubResponse . data || _ . isEmpty ( githubResponse . data ) ) {
49
- console . error ( 'Failed fetching data from Github!' , githubResponse ) ;
50
- throw new Error ( 'Failed fetching data from Github' ) ;
51
- }
52
-
53
- // Parse the tag from the most recent StagingDeployCash
54
- const lastTag = GithubUtils . getStagingDeployCashData ( githubResponse . data [ 0 ] ) . tag ;
55
- console . log ( 'Found tag of previous StagingDeployCash:' , lastTag ) ;
56
-
57
- // Find the list of PRs merged between the last StagingDeployCash and the new version
58
- return GitUtils . getPullRequestsMergedBetween ( lastTag , newVersion ) ;
59
- } )
60
- . then ( PRNumbers => GithubUtils . createNewStagingDeployCash (
61
- `Deploy Checklist: Expensify.cash ${ moment ( ) . format ( 'YYYY-MM-DD' ) } ` ,
62
- newVersion ,
63
- _ . map ( PRNumbers , GithubUtils . getPullRequestURLFromNumber ) ,
64
- ) )
65
- . then ( ( { data} ) => console . log ( 'Successfully created new StagingDeployCash! 🎉' , data . html_url ) )
66
- . catch ( ( err ) => {
67
- console . error ( 'An error occurred!' , err ) ;
68
- core . setFailed ( err ) ;
69
- } ) ;
132
+ } )
133
+ . then ( ( { data} ) => {
134
+ // eslint-disable-next-line max-len
135
+ console . log ( `Successfully ${ shouldCreateNewStagingDeployCash ? 'created new' : 'updated' } StagingDeployCash! 🎉 ${ data . html_url } ` ) ;
136
+ return data ;
137
+ } )
138
+ . catch ( ( err ) => {
139
+ console . error ( 'An unknown error occurred!' , err ) ;
140
+ core . setFailed ( err ) ;
141
+ } ) ;
142
+ } ;
143
+
144
+ if ( require . main === module ) {
145
+ run ( ) ;
146
+ }
147
+
148
+ module . exports = run ;
0 commit comments