Skip to content

Commit 2acdbef

Browse files
committed
test: timestamped logs changes
1 parent de7201e commit 2acdbef

File tree

1 file changed

+129
-20
lines changed

1 file changed

+129
-20
lines changed

tests/netlify-deploy.ts

Lines changed: 129 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ async function packNextRuntimeImpl() {
2323
}
2424

2525
let packNextRuntimePromise: ReturnType<typeof packNextRuntimeImpl> | null = null
26+
let nextRuntimePacked = false
2627
function packNextRuntime() {
2728
if (!packNextRuntimePromise) {
2829
packNextRuntimePromise = packNextRuntimeImpl()
@@ -38,13 +39,60 @@ 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 async ps() {
80+
const netlifyStatusPromise = execa('ps', ['aux'])
81+
82+
netlifyStatusPromise.stdout.on('data', this.handleOutput)
83+
netlifyStatusPromise.stderr.on('data', this.handleOutput)
84+
85+
await netlifyStatusPromise
86+
}
87+
88+
private handleOutput(chunk) {
89+
const timestampPrefix = this.getTimestampPrefix()
90+
91+
this._deployOutput +=
92+
(this._deployOutput === '' || this._deployOutput.endsWith('\n') ? timestampPrefix : '') +
93+
chunk.toString().replace(/\n(?=.)/gm, `\n${timestampPrefix}`)
94+
}
95+
4896
public async setup(parentSpan: Span) {
4997
if (process.env.SITE_URL && process.env.BUILD_ID) {
5098
require('console').log('Using existing deployment: ' + process.env.SITE_URL)
@@ -54,51 +102,47 @@ export class NextDeployInstance extends NextInstance {
54102
return
55103
}
56104

57-
let deployStartTime = Date.now()
58-
59105
this._isCurrentlyDeploying = true
60106

61-
const setupStartTime = Date.now()
62-
107+
this._deployOutput += this.getTimestampPrefix() + 'Setting up test dir ...\n'
63108
// create the test site
64109
await super.createTestDir({ parentSpan, skipInstall: true })
110+
this._deployOutput += this.getTimestampPrefix() + 'Setting up test dir DONE\n'
65111

66112
// If the test fixture has node modules we need to move them aside then merge them in after
67113

68114
const nodeModules = path.join(this.testDir, 'node_modules')
69115
const nodeModulesBak = `${nodeModules}.bak`
70116

71117
if (fs.existsSync(nodeModules)) {
118+
this._deployOutput += this.getTimestampPrefix() + 'Rename node_modules ...\n'
72119
await fs.rename(nodeModules, nodeModulesBak)
120+
this._deployOutput += this.getTimestampPrefix() + 'Rename node_modules DONE\n'
73121
}
74122

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-
}
123+
const { runtimePackageName, runtimePackageTarballPath } = await this.packNextRuntime()
84124

85125
// install dependencies
126+
this._deployOutput += this.getTimestampPrefix() + 'Install dependencies ...\n'
86127
const installResPromise = execa('npm', ['i', runtimePackageTarballPath, '--legacy-peer-deps'], {
87128
cwd: this.testDir,
88129
})
89130

90-
installResPromise.stdout.on('data', handleOutput)
91-
installResPromise.stderr.on('data', handleOutput)
131+
installResPromise.stdout.on('data', this.handleOutput)
132+
installResPromise.stderr.on('data', this.handleOutput)
92133

93134
await installResPromise
135+
this._deployOutput += this.getTimestampPrefix() + 'Install dependencies DONE\n'
94136

95137
if (fs.existsSync(nodeModulesBak)) {
96138
// move the contents of the fixture node_modules into the installed modules
139+
this._deployOutput += this.getTimestampPrefix() + 'Move fixture node_modules ...\n'
97140
for (const file of await fs.readdir(nodeModulesBak)) {
98141
await fs.move(path.join(nodeModulesBak, file), path.join(nodeModules, file), {
99142
overwrite: true,
100143
})
101144
}
145+
this._deployOutput += this.getTimestampPrefix() + 'Move fixture node_modules DONE\n'
102146
}
103147

104148
// use next runtime package installed by the test runner
@@ -133,8 +177,8 @@ export class NextDeployInstance extends NextInstance {
133177
try {
134178
const netlifyStatusPromise = execa('npx', ['netlify', 'status', '--json'])
135179

136-
netlifyStatusPromise.stdout.on('data', handleOutput)
137-
netlifyStatusPromise.stderr.on('data', handleOutput)
180+
netlifyStatusPromise.stdout.on('data', this.handleOutput)
181+
netlifyStatusPromise.stderr.on('data', this.handleOutput)
138182

139183
await netlifyStatusPromise
140184
} catch (err) {
@@ -163,11 +207,75 @@ export class NextDeployInstance extends NextInstance {
163207
},
164208
)
165209

166-
deployResPromise.stdout.on('data', handleOutput)
167-
deployResPromise.stderr.on('data', handleOutput)
210+
this._deployOutput +=
211+
this.getTimestampPrefix() + `Started deploy, PID: ${deployResPromise.pid}\n`
212+
require('console').log(`Started deploy, PID: ${deployResPromise.pid}`)
213+
214+
deployResPromise.stdout.on('data', this.handleOutput)
215+
deployResPromise.stderr.on('data', this.handleOutput)
216+
217+
deployResPromise.on('error', (err) => {
218+
this._deployOutput += this.getTimestampPrefix() + `Error during deployment: ${err.message}\n`
219+
require('console').error(`Error during deployment: ${err.message}`)
220+
})
221+
222+
deployResPromise.on('spawn', (err) => {
223+
this._deployOutput += this.getTimestampPrefix() + `Process spawned\n`
224+
require('console').error(`Process spawned`)
225+
})
226+
227+
deployResPromise.on('disconnect', (err) => {
228+
this._deployOutput += this.getTimestampPrefix() + `Process disconnected\n`
229+
require('console').error(`Process disconnected`)
230+
})
231+
232+
deployResPromise.on('close', (code, signal) => {
233+
this._deployOutput +=
234+
this.getTimestampPrefix() + `Process closed with code: ${code} / signal: ${signal}\n`
235+
require('console').error(`Process closed with code: ${code} / signal: ${signal}`)
236+
})
237+
238+
deployResPromise.on('exit', (code, signal) => {
239+
this._deployOutput +=
240+
this.getTimestampPrefix() + `Process exited with code: ${code} / signal: ${signal}\n`
241+
require('console').error(`Process exited with code: ${code} / signal: ${signal}`)
242+
})
243+
244+
this._intervalsToClear.push(
245+
setInterval(() => {
246+
this._deployOutput +=
247+
this.getTimestampPrefix() +
248+
'Waiting for netlify deploy process to finish ... (killed: ${deployResPromise.killed}, connected: ${deployResPromise.connected})\n'
249+
}, 5000),
250+
)
251+
252+
this._intervalsToClear.push(
253+
setInterval(() => {
254+
this.ps()
255+
}, 30_000),
256+
)
257+
258+
deployResPromise
259+
.then((result) => {
260+
require('console').log(`Netlify deploy process finished.`)
261+
this._deployOutput += this.getTimestampPrefix() + 'Netlify deploy process finished.\n'
262+
})
263+
.catch((err) => {
264+
require('console').log(`Netlify deploy process failed. ` + err)
265+
this._deployOutput += this.getTimestampPrefix() + 'Netlify deploy process failed. ' + err
266+
})
267+
.finally(() => {
268+
require('console').log(`Netlify deploy process finally.`)
269+
this._deployOutput += this.getTimestampPrefix() + 'Netlify deploy process finally.\n'
270+
this.clearIntervals()
271+
})
168272

169273
const deployRes = await deployResPromise
170274

275+
this.clearIntervals()
276+
277+
require('console').log(`Deploy finished. Processing output...`)
278+
171279
if (deployRes.exitCode !== 0) {
172280
// clear deploy output to avoid printing it again in destroy()
173281
this._deployOutput = ''
@@ -210,12 +318,13 @@ export class NextDeployInstance extends NextInstance {
210318
).trim()
211319

212320
require('console').log(`Got buildId: ${this._buildId}`)
213-
require('console').log(`Setup time: ${(Date.now() - setupStartTime) / 1000.0}s`)
321+
require('console').log(`Setup time: ${(Date.now() - this._setupStartTime) / 1000.0}s`)
214322

215323
this._isCurrentlyDeploying = false
216324
}
217325

218326
public async destroy(): Promise<void> {
327+
this.clearIntervals()
219328
if (this._shouldDeleteDeploy) {
220329
require('console').log(`Deleting project with deploy_id ${this._deployId}`)
221330

0 commit comments

Comments
 (0)