Skip to content

Commit f66a7f1

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

File tree

1 file changed

+127
-20
lines changed

1 file changed

+127
-20
lines changed

tests/netlify-deploy.ts

Lines changed: 127 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,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', ['aux'])
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

Comments
 (0)