1
- import { join } from 'path' ;
2
-
3
1
import * as core from '@actions/core' ;
4
2
import * as github from '@actions/github' ;
5
3
import {
6
4
addPullRequestComment ,
7
5
getDeployEnv ,
8
6
printGitHubContext
9
7
} from '@codeware/core/actions' ;
10
- import { type DeployAppOptions , Fly } from '@codeware/fly-node' ;
8
+ import { Fly } from '@codeware/fly-node' ;
11
9
import type {
12
10
PullRequestEvent ,
13
11
WebhookEventName
@@ -17,12 +15,9 @@ import { type ActionInputs } from './schemas/action-inputs.schema';
17
15
import { ActionOutputsSchema } from './schemas/action-outputs.schema' ;
18
16
import { type ActionOutputs } from './schemas/action-outputs.schema' ;
19
17
import { type BuildingContext , ContextSchema } from './schemas/context.schema' ;
20
- import { addOpinionatedEnv } from './utils/add-opinionated-env' ;
21
- import { getDeployableProjects } from './utils/get-deployable-projects' ;
22
18
import { getDeploymentConfig } from './utils/get-deployment-config' ;
23
- import { getPreviewAppName } from './utils/get-preview-app-name' ;
24
- import { getProjectConfiguration } from './utils/get-project-configuration' ;
25
- import { lookupGitHubConfigFile } from './utils/lookup-github-config-file' ;
19
+ import { runDeployApps } from './utils/run-deploy-apps' ;
20
+ import { runDestroyApps } from './utils/run-destroy-apps' ;
26
21
27
22
/**
28
23
* Run fly deployment process
@@ -72,14 +67,18 @@ export async function flyDeployment(
72
67
core . info (
73
68
`Get deployment environment for '${ eventName } ' on '${ currentBranch } '`
74
69
) ;
70
+
75
71
const deployEnv = getDeployEnv ( github . context , config . mainBranch ) ;
72
+
76
73
if ( deployEnv . environment ) {
77
74
// Add target environment to context
78
75
context . environment = deployEnv . environment ;
79
76
} else {
80
77
throw new Error ( deployEnv . reason ) ;
81
78
}
79
+
82
80
core . info ( `Using environment '${ context . environment } '` ) ;
81
+
83
82
switch ( eventName as WebhookEventName ) {
84
83
case 'pull_request' :
85
84
{
@@ -96,208 +95,63 @@ export async function flyDeployment(
96
95
}
97
96
core . endGroup ( ) ;
98
97
98
+ // Verify context data before actions
99
+ ContextSchema . parse ( context ) ;
100
+
99
101
// Initialize action results
100
102
const results : ActionOutputs = {
101
103
environment : context . environment ,
102
104
projects : [ ]
103
105
} ;
104
106
105
- // Destroy deployments based on pull request number
107
+ // Action: Destroy and exit
106
108
if ( context . action === 'destroy' ) {
107
- // Verify context data before destroying deployments
108
- ContextSchema . parse ( context ) ;
109
-
110
- core . startGroup ( 'Analyze fly apps to destroy' ) ;
111
- const apps = await fly . apps . list ( ) ;
112
- for ( const app of apps ) {
113
- if ( app . name . endsWith ( `-pr-${ context . pullRequest } ` ) ) {
114
- core . info ( `Destroy preview app '${ app . name } '` ) ;
115
-
116
- try {
117
- await fly . apps . destroy ( app . name ) ;
118
- results . projects . push ( { action : 'destroy' , app : app . name } ) ;
119
- } catch ( error ) {
120
- const msg = error instanceof Error ? error . message : String ( error ) ;
121
- core . warning ( msg ) ;
122
- results . projects . push ( {
123
- action : 'skip' ,
124
- appOrProject : app . name ,
125
- reason : 'Failed to destroy application'
126
- } ) ;
127
- }
128
- }
129
- }
109
+ core . startGroup ( 'Destroy deprecated applications' ) ;
110
+ results . projects = await runDestroyApps ( config , fly ) ;
130
111
core . endGroup ( ) ;
131
112
132
113
return ActionOutputsSchema . parse ( results ) ;
133
114
}
134
-
135
- // Create deployments based on affected projects
136
- core . startGroup ( 'Analyze affected projects to deploy' ) ;
137
- const projectNames = await getDeployableProjects ( ) ;
138
- core . info ( `Deployable projects: ${ projectNames . join ( ', ' ) } ` ) ;
139
- core . endGroup ( ) ;
140
-
141
- if ( projectNames . length === 0 ) {
142
- core . info ( 'No projects to deploy, skipping deployment' ) ;
143
- return ActionOutputsSchema . parse ( results ) ;
144
- }
145
-
146
- // Analyze each project
147
- for ( const projectName of projectNames ) {
148
- core . startGroup ( `Analyze project '${ projectName } ' before deployment` ) ;
149
-
150
- // Get project configuration
151
- core . info ( `Get project configuration for '${ projectName } '` ) ;
152
- const projectConfig = await getProjectConfiguration ( projectName ) ;
153
- if ( ! projectConfig ) {
154
- const reason = 'Project configuration not found' ;
155
- core . warning ( `${ reason } , not possible to deploy` ) ;
156
- results . projects . push ( {
157
- appOrProject : projectName ,
158
- action : 'skip' ,
159
- reason
160
- } ) ;
161
- continue ;
162
- }
163
- core . info (
164
- `Found project configuration with root '${ projectConfig . root } '`
165
- ) ;
166
-
167
- // Find github.json
168
- core . info ( `Lookup GitHub configuration file in '${ projectConfig . root } '` ) ;
169
- const gcResponse = await lookupGitHubConfigFile ( projectConfig . root ) ;
170
- if ( ! gcResponse ) {
171
- const reason = 'GitHub configuration file not found for the project' ;
172
- core . info ( `${ reason } , skipping` ) ;
173
- results . projects . push ( {
174
- appOrProject : projectName ,
175
- action : 'skip' ,
176
- reason
177
- } ) ;
178
- continue ;
179
- }
180
- const { configFile, content : githubConfig } = gcResponse ;
181
- core . info ( `Found GitHub configuration file '${ configFile } '` ) ;
182
-
183
- if ( ! githubConfig . deploy ) {
184
- const reason =
185
- 'Deployment is disabled in GitHub configuration for the project' ;
186
- core . info ( `${ reason } , skipping` ) ;
187
- results . projects . push ( {
188
- appOrProject : projectName ,
189
- action : 'skip' ,
190
- reason
191
- } ) ;
192
- continue ;
193
- }
194
-
195
- // Verify and get app name from fly.toml
196
- core . info (
197
- `Deployment is enabled, lookup Fly configuration file '${ githubConfig . flyConfig } '`
198
- ) ;
199
- const resolvedFlyConfig = join (
200
- projectConfig . root ,
201
- githubConfig . flyConfig
202
- ) ;
203
- let configAppName : string ;
204
- try {
205
- const flyConfig = await fly . config . show ( {
206
- config : resolvedFlyConfig ,
207
- local : true
208
- } ) ;
209
- configAppName = flyConfig . app ;
210
- core . info (
211
- `Resolved app name '${ configAppName } ' from Fly configuration '${ resolvedFlyConfig } '`
212
- ) ;
213
- } catch {
214
- const reason = `Fly configuration file not found '${ resolvedFlyConfig } '` ;
215
- core . warning ( `${ reason } , not possible to deploy` ) ;
216
- results . projects . push ( {
217
- appOrProject : projectName ,
218
- action : 'skip' ,
219
- reason
220
- } ) ;
221
- continue ;
222
- }
223
- core . endGroup ( ) ;
224
-
225
- // Verify context data before deploying
226
- ContextSchema . parse ( context ) ;
227
-
228
- // Requirements are met, ready to deploy
229
-
230
- core . startGroup ( `Project '${ projectName } ' ready to fly` ) ;
231
-
232
- const appName =
233
- context . environment === 'preview'
234
- ? getPreviewAppName ( configAppName , Number ( context . pullRequest ) )
235
- : configAppName ;
236
- const env = addOpinionatedEnv (
237
- { appName, prNumber : context . pullRequest } ,
238
- config . env
239
- ) ;
240
- const postgres =
241
- context . environment === 'preview'
242
- ? githubConfig . flyPostgresPreview
243
- : githubConfig . flyPostgresProduction ;
244
-
245
- const options : DeployAppOptions = {
246
- app : appName ,
247
- config : resolvedFlyConfig ,
248
- env,
115
+ // Action: Deploy
116
+ else if ( context . action === 'deploy' ) {
117
+ core . startGroup ( 'Deploy affected applications' ) ;
118
+ results . projects = await runDeployApps ( {
119
+ config,
249
120
environment : context . environment ,
250
- postgres : postgres || undefined , // rather undefined than empty string
251
- secrets : config . secrets
252
- } ;
253
-
254
- core . info ( `Deploy '${ options . app } ' to '${ options . environment } '...` ) ;
255
-
256
- try {
257
- const result = await fly . deploy ( options ) ;
258
- core . info ( `Deployed to '${ result . url } '` ) ;
259
- results . projects . push ( {
260
- action : 'deploy' ,
261
- app : result . app ,
262
- name : projectName ,
263
- url : result . url
264
- } ) ;
265
- } catch ( error ) {
266
- const msg = error instanceof Error ? error . message : String ( error ) ;
267
- core . warning ( msg ) ;
268
- results . projects . push ( {
269
- appOrProject : projectName ,
270
- action : 'skip' ,
271
- reason : 'Failed to deploy project'
272
- } ) ;
273
- }
274
-
121
+ fly,
122
+ pullRequest : context . pullRequest
123
+ } ) ;
275
124
core . endGroup ( ) ;
276
125
}
277
126
278
127
// Preview deployments should add a comment to the pull request
279
- if ( results . environment === 'preview' ) {
280
- core . startGroup ( 'Pull request preview comment' ) ;
281
- core . info ( 'Analyze deployed projects' ) ;
282
- const deployed = results . projects . filter ( ( p ) => p . action === 'deploy' ) ;
128
+ const deployed = results . projects . filter ( ( p ) => p . action === 'deploy' ) ;
129
+ if ( deployed . length && results . environment === 'preview' ) {
130
+ core . startGroup ( 'Add pull request preview comment' ) ;
131
+
132
+ // Create a table with deployed projects
283
133
const comment = [
284
134
`:sparkles: Your pull request project${
285
135
deployed . length > 1 ? 's are' : ' is'
286
136
} ready for preview`,
287
137
'| Project | App name | Preview |' ,
288
138
'| --- | --- | --- |'
289
139
] ;
140
+
290
141
for ( const project of deployed ) {
291
142
comment . push (
292
143
`| ${ project . name } | ${ project . app } | [${ project . url } ](${ project . url } ) |`
293
144
) ;
294
145
}
146
+
295
147
core . info ( `Add comment to pull request ${ context . pullRequest } ` ) ;
148
+
296
149
await addPullRequestComment (
297
150
config . token ,
298
151
Number ( context . pullRequest ) ,
299
152
comment . join ( '\n' )
300
153
) ;
154
+ core . endGroup ( ) ;
301
155
}
302
156
303
157
return ActionOutputsSchema . parse ( results ) ;
0 commit comments