@@ -23,6 +23,7 @@ async function packNextRuntimeImpl() {
2323}
2424
2525let packNextRuntimePromise : ReturnType < typeof packNextRuntimeImpl > | null = null
26+ let nextRuntimePacked = false
2627function packNextRuntime ( ) {
2728 if ( ! packNextRuntimePromise ) {
2829 packNextRuntimePromise = packNextRuntimeImpl ( )
@@ -38,13 +39,58 @@ export class NextDeployInstance extends NextInstance {
3839 private _shouldDeleteDeploy : boolean = false
3940 private _isCurrentlyDeploying : boolean = false
4041 private _deployOutput : string = ''
42+ private _setupStartTime = Date . now ( )
43+ private _intervalsToClear : NodeJS . Timeout [ ] = [ ]
4144
4245 public get buildId ( ) {
4346 // get deployment ID via fetch since we can't access
4447 // build artifacts directly
4548 return this . _buildId
4649 }
4750
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 ( ) {
80+ const netlifyStatusPromise = execa ( 'ps' , [ '-fC' , 'netlify' ] )
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+
4894 public async setup ( parentSpan : Span ) {
4995 if ( process . env . SITE_URL && process . env . BUILD_ID ) {
5096 require ( 'console' ) . log ( 'Using existing deployment: ' + process . env . SITE_URL )
@@ -54,51 +100,47 @@ export class NextDeployInstance extends NextInstance {
54100 return
55101 }
56102
57- let deployStartTime = Date . now ( )
58-
59103 this . _isCurrentlyDeploying = true
60104
61- const setupStartTime = Date . now ( )
62-
105+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Setting up test dir ...\n'
63106 // create the test site
64107 await super . createTestDir ( { parentSpan, skipInstall : true } )
108+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Setting up test dir DONE\n'
65109
66110 // If the test fixture has node modules we need to move them aside then merge them in after
67111
68112 const nodeModules = path . join ( this . testDir , 'node_modules' )
69113 const nodeModulesBak = `${ nodeModules } .bak`
70114
71115 if ( fs . existsSync ( nodeModules ) ) {
116+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Rename node_modules ...\n'
72117 await fs . rename ( nodeModules , nodeModulesBak )
118+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Rename node_modules DONE\n'
73119 }
74120
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 ( )
84122
85123 // install dependencies
124+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Install dependencies ...\n'
86125 const installResPromise = execa ( 'npm' , [ 'i' , runtimePackageTarballPath , '--legacy-peer-deps' ] , {
87126 cwd : this . testDir ,
88127 } )
89128
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 ) )
92131
93132 await installResPromise
133+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Install dependencies DONE\n'
94134
95135 if ( fs . existsSync ( nodeModulesBak ) ) {
96136 // move the contents of the fixture node_modules into the installed modules
137+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Move fixture node_modules ...\n'
97138 for ( const file of await fs . readdir ( nodeModulesBak ) ) {
98139 await fs . move ( path . join ( nodeModulesBak , file ) , path . join ( nodeModules , file ) , {
99140 overwrite : true ,
100141 } )
101142 }
143+ this . _deployOutput += this . getTimestampPrefix ( ) + 'Move fixture node_modules DONE\n'
102144 }
103145
104146 // use next runtime package installed by the test runner
@@ -133,8 +175,8 @@ export class NextDeployInstance extends NextInstance {
133175 try {
134176 const netlifyStatusPromise = execa ( 'npx' , [ 'netlify' , 'status' , '--json' ] )
135177
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 ) )
138180
139181 await netlifyStatusPromise
140182 } catch ( err ) {
@@ -163,11 +205,75 @@ export class NextDeployInstance extends NextInstance {
163205 } ,
164206 )
165207
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 ( )
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+ } )
168270
169271 const deployRes = await deployResPromise
170272
273+ this . clearIntervals ( )
274+
275+ require ( 'console' ) . log ( `Deploy finished. Processing output...` )
276+
171277 if ( deployRes . exitCode !== 0 ) {
172278 // clear deploy output to avoid printing it again in destroy()
173279 this . _deployOutput = ''
@@ -210,12 +316,13 @@ export class NextDeployInstance extends NextInstance {
210316 ) . trim ( )
211317
212318 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` )
214320
215321 this . _isCurrentlyDeploying = false
216322 }
217323
218324 public async destroy ( ) : Promise < void > {
325+ this . clearIntervals ( )
219326 if ( this . _shouldDeleteDeploy ) {
220327 require ( 'console' ) . log ( `Deleting project with deploy_id ${ this . _deployId } ` )
221328
0 commit comments