@@ -23,6 +23,7 @@ async function packNextRuntimeImpl() {
23
23
}
24
24
25
25
let packNextRuntimePromise : ReturnType < typeof packNextRuntimeImpl > | null = null
26
+ let nextRuntimePacked = false
26
27
function packNextRuntime ( ) {
27
28
if ( ! packNextRuntimePromise ) {
28
29
packNextRuntimePromise = packNextRuntimeImpl ( )
@@ -38,13 +39,58 @@ export class NextDeployInstance extends NextInstance {
38
39
private _shouldDeleteDeploy : boolean = false
39
40
private _isCurrentlyDeploying : boolean = false
40
41
private _deployOutput : string = ''
42
+ private _setupStartTime = Date . now ( )
43
+ private _intervalsToClear : NodeJS . Timeout [ ] = [ ]
41
44
42
45
public get buildId ( ) {
43
46
// get deployment ID via fetch since we can't access
44
47
// build artifacts directly
45
48
return this . _buildId
46
49
}
47
50
51
+ private packNextRuntime ( ) {
52
+ if ( ! packNextRuntimePromise ) {
53
+ if ( ! nextRuntimePacked ) {
54
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Pack Next Runtime ...\n'
55
+ }
56
+ packNextRuntimePromise = packNextRuntimeImpl ( )
57
+ packNextRuntimePromise . then ( ( ) => {
58
+ nextRuntimePacked = true
59
+ } )
60
+ if ( ! nextRuntimePacked ) {
61
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Pack Next Runtime DONE\n'
62
+ }
63
+ }
64
+
65
+ return packNextRuntimePromise
66
+ }
67
+
68
+ private clearIntervals ( ) {
69
+ for ( const interval of this . _intervalsToClear ) {
70
+ clearInterval ( interval )
71
+ }
72
+ this . _intervalsToClear = [ ]
73
+ }
74
+
75
+ private getTimestampPrefix ( ) {
76
+ return `[${ new Date ( ) . toISOString ( ) } ] (+${ ( ( Date . now ( ) - this . _setupStartTime ) / 1000 ) . toFixed ( 3 ) } s) `
77
+ }
78
+
79
+ private ps ( pid ) {
80
+ const netlifyStatusPromise = execa ( 'ps' , [ '-p' , pid ] )
81
+
82
+ netlifyStatusPromise . stdout . on ( 'data' , this . handleOutput . bind ( this ) )
83
+ netlifyStatusPromise . stderr . on ( 'data' , this . handleOutput . bind ( this ) )
84
+ }
85
+
86
+ private handleOutput ( chunk ) {
87
+ const timestampPrefix = this . getTimestampPrefix ( )
88
+
89
+ this . _deployOutput +=
90
+ ( this . _deployOutput === '' || this . _deployOutput . endsWith ( '\n' ) ? timestampPrefix : '' ) +
91
+ chunk . toString ( ) . replace ( / \n (? = .) / gm, `\n${ timestampPrefix } ` )
92
+ }
93
+
48
94
public async setup ( parentSpan : Span ) {
49
95
if ( process . env . SITE_URL && process . env . BUILD_ID ) {
50
96
require ( 'console' ) . log ( 'Using existing deployment: ' + process . env . SITE_URL )
@@ -54,51 +100,47 @@ export class NextDeployInstance extends NextInstance {
54
100
return
55
101
}
56
102
57
- let deployStartTime = Date . now ( )
58
-
59
103
this . _isCurrentlyDeploying = true
60
104
61
- const setupStartTime = Date . now ( )
62
-
105
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Setting up test dir ...\n'
63
106
// create the test site
64
107
await super . createTestDir ( { parentSpan, skipInstall : true } )
108
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Setting up test dir DONE\n'
65
109
66
110
// If the test fixture has node modules we need to move them aside then merge them in after
67
111
68
112
const nodeModules = path . join ( this . testDir , 'node_modules' )
69
113
const nodeModulesBak = `${ nodeModules } .bak`
70
114
71
115
if ( fs . existsSync ( nodeModules ) ) {
116
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Rename node_modules ...\n'
72
117
await fs . rename ( nodeModules , nodeModulesBak )
118
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Rename node_modules DONE\n'
73
119
}
74
120
75
- const { runtimePackageName, runtimePackageTarballPath } = await packNextRuntime ( )
76
-
77
- const handleOutput = ( chunk ) => {
78
- const timestampPrefix = `[${ new Date ( ) . toISOString ( ) } ] (+${ ( ( Date . now ( ) - deployStartTime ) / 1000 ) . toFixed ( 3 ) } s) `
79
-
80
- this . _deployOutput +=
81
- ( this . _deployOutput === '' || this . _deployOutput . endsWith ( '\n' ) ? timestampPrefix : '' ) +
82
- chunk . toString ( ) . replace ( / \n (? = .) / gm, `\n${ timestampPrefix } ` )
83
- }
121
+ const { runtimePackageName, runtimePackageTarballPath } = await this . packNextRuntime ( )
84
122
85
123
// install dependencies
124
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Install dependencies ...\n'
86
125
const installResPromise = execa ( 'npm' , [ 'i' , runtimePackageTarballPath , '--legacy-peer-deps' ] , {
87
126
cwd : this . testDir ,
88
127
} )
89
128
90
- installResPromise . stdout . on ( 'data' , handleOutput )
91
- installResPromise . stderr . on ( 'data' , handleOutput )
129
+ installResPromise . stdout . on ( 'data' , this . handleOutput . bind ( this ) )
130
+ installResPromise . stderr . on ( 'data' , this . handleOutput . bind ( this ) )
92
131
93
132
await installResPromise
133
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Install dependencies DONE\n'
94
134
95
135
if ( fs . existsSync ( nodeModulesBak ) ) {
96
136
// move the contents of the fixture node_modules into the installed modules
137
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Move fixture node_modules ...\n'
97
138
for ( const file of await fs . readdir ( nodeModulesBak ) ) {
98
139
await fs . move ( path . join ( nodeModulesBak , file ) , path . join ( nodeModules , file ) , {
99
140
overwrite : true ,
100
141
} )
101
142
}
143
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Move fixture node_modules DONE\n'
102
144
}
103
145
104
146
// use next runtime package installed by the test runner
@@ -133,8 +175,8 @@ export class NextDeployInstance extends NextInstance {
133
175
try {
134
176
const netlifyStatusPromise = execa ( 'npx' , [ 'netlify' , 'status' , '--json' ] )
135
177
136
- netlifyStatusPromise . stdout . on ( 'data' , handleOutput )
137
- netlifyStatusPromise . stderr . on ( 'data' , handleOutput )
178
+ netlifyStatusPromise . stdout . on ( 'data' , this . handleOutput . bind ( this ) )
179
+ netlifyStatusPromise . stderr . on ( 'data' , this . handleOutput . bind ( this ) )
138
180
139
181
await netlifyStatusPromise
140
182
} catch ( err ) {
@@ -163,11 +205,75 @@ export class NextDeployInstance extends NextInstance {
163
205
} ,
164
206
)
165
207
166
- deployResPromise . stdout . on ( 'data' , handleOutput )
167
- deployResPromise . stderr . on ( 'data' , handleOutput )
208
+ this . _deployOutput +=
209
+ this . getTimestampPrefix ( ) + `Started deploy, PID: ${ deployResPromise . pid } \n`
210
+ require ( 'console' ) . log ( `Started deploy, PID: ${ deployResPromise . pid } ` )
211
+
212
+ deployResPromise . stdout . on ( 'data' , this . handleOutput . bind ( this ) )
213
+ deployResPromise . stderr . on ( 'data' , this . handleOutput . bind ( this ) )
214
+
215
+ deployResPromise . on ( 'error' , ( err ) => {
216
+ this . _deployOutput += this . getTimestampPrefix ( ) + `Error during deployment: ${ err . message } \n`
217
+ require ( 'console' ) . error ( `Error during deployment: ${ err . message } ` )
218
+ } )
219
+
220
+ deployResPromise . on ( 'spawn' , ( err ) => {
221
+ this . _deployOutput += this . getTimestampPrefix ( ) + `Process spawned\n`
222
+ require ( 'console' ) . error ( `Process spawned` )
223
+ } )
224
+
225
+ deployResPromise . on ( 'disconnect' , ( err ) => {
226
+ this . _deployOutput += this . getTimestampPrefix ( ) + `Process disconnected\n`
227
+ require ( 'console' ) . error ( `Process disconnected` )
228
+ } )
229
+
230
+ deployResPromise . on ( 'close' , ( code , signal ) => {
231
+ this . _deployOutput +=
232
+ this . getTimestampPrefix ( ) + `Process closed with code: ${ code } / signal: ${ signal } \n`
233
+ require ( 'console' ) . error ( `Process closed with code: ${ code } / signal: ${ signal } ` )
234
+ } )
235
+
236
+ deployResPromise . on ( 'exit' , ( code , signal ) => {
237
+ this . _deployOutput +=
238
+ this . getTimestampPrefix ( ) + `Process exited with code: ${ code } / signal: ${ signal } \n`
239
+ require ( 'console' ) . error ( `Process exited with code: ${ code } / signal: ${ signal } ` )
240
+ } )
241
+
242
+ this . _intervalsToClear . push (
243
+ setInterval ( ( ) => {
244
+ this . _deployOutput +=
245
+ this . getTimestampPrefix ( ) +
246
+ `Waiting for netlify deploy process to finish ... (killed: ${ deployResPromise . killed } , connected: ${ deployResPromise . connected } )\n`
247
+ } , 5000 ) ,
248
+ )
249
+
250
+ this . _intervalsToClear . push (
251
+ setInterval ( ( ) => {
252
+ this . ps ( deployResPromise . pid )
253
+ } , 30_000 ) ,
254
+ )
255
+
256
+ deployResPromise
257
+ . then ( ( result ) => {
258
+ require ( 'console' ) . log ( `Netlify deploy process finished.` )
259
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Netlify deploy process finished.\n'
260
+ } )
261
+ . catch ( ( err ) => {
262
+ require ( 'console' ) . log ( `Netlify deploy process failed. ` + err )
263
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Netlify deploy process failed. ' + err
264
+ } )
265
+ . finally ( ( ) => {
266
+ require ( 'console' ) . log ( `Netlify deploy process finally.` )
267
+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Netlify deploy process finally.\n'
268
+ this . clearIntervals ( )
269
+ } )
168
270
169
271
const deployRes = await deployResPromise
170
272
273
+ this . clearIntervals ( )
274
+
275
+ require ( 'console' ) . log ( `Deploy finished. Processing output...` )
276
+
171
277
if ( deployRes . exitCode !== 0 ) {
172
278
// clear deploy output to avoid printing it again in destroy()
173
279
this . _deployOutput = ''
@@ -210,12 +316,13 @@ export class NextDeployInstance extends NextInstance {
210
316
) . trim ( )
211
317
212
318
require ( 'console' ) . log ( `Got buildId: ${ this . _buildId } ` )
213
- require ( 'console' ) . log ( `Setup time: ${ ( Date . now ( ) - setupStartTime ) / 1000.0 } s` )
319
+ require ( 'console' ) . log ( `Setup time: ${ ( Date . now ( ) - this . _setupStartTime ) / 1000.0 } s` )
214
320
215
321
this . _isCurrentlyDeploying = false
216
322
}
217
323
218
324
public async destroy ( ) : Promise < void > {
325
+ this . clearIntervals ( )
219
326
if ( this . _shouldDeleteDeploy ) {
220
327
require ( 'console' ) . log ( `Deleting project with deploy_id ${ this . _deployId } ` )
221
328
0 commit comments