rollbridge 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/release-group.js +7 -3
- package/test/rollbridge.test.js +12 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rollbridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Zero-downtime process supervisor and local traffic switcher for deploy-managed apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deploy",
|
|
@@ -27,10 +27,11 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"all-checks": "npm run typecheck && npm run lint && npm test",
|
|
30
|
-
"lint": "eslint",
|
|
30
|
+
"lint": "npm run eslint && npm run typecheck",
|
|
31
31
|
"release:patch": "release-patch",
|
|
32
32
|
"test": "node --test test/*.test.js",
|
|
33
|
-
"typecheck": "tsc --noEmit"
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"eslint": "eslint"
|
|
34
35
|
},
|
|
35
36
|
"engines": {
|
|
36
37
|
"node": ">=20"
|
package/src/release-group.js
CHANGED
|
@@ -91,8 +91,9 @@ export default class ReleaseGroup extends EventEmitter {
|
|
|
91
91
|
}
|
|
92
92
|
} catch (error) {
|
|
93
93
|
this.state = "failed"
|
|
94
|
-
this.logStartupFailure(error instanceof Error ? error : String(error))
|
|
94
|
+
this.logStartupFailure(error instanceof Error ? error : String(error), {phase: "before cleanup"})
|
|
95
95
|
await this.stop()
|
|
96
|
+
this.logStartupFailure(error instanceof Error ? error : String(error), {phase: "after cleanup"})
|
|
96
97
|
throw error
|
|
97
98
|
}
|
|
98
99
|
}
|
|
@@ -125,13 +126,15 @@ export default class ReleaseGroup extends EventEmitter {
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
/**
|
|
128
|
-
* Logs process diagnostics
|
|
129
|
+
* Logs process diagnostics around failed startup cleanup.
|
|
129
130
|
* @param {Error | string} error - Startup failure.
|
|
131
|
+
* @param {{phase: string}} options - Diagnostic phase.
|
|
130
132
|
* @returns {void}
|
|
131
133
|
*/
|
|
132
|
-
logStartupFailure(error) {
|
|
134
|
+
logStartupFailure(error, {phase}) {
|
|
133
135
|
this.logger("release startup failed", {
|
|
134
136
|
error: error instanceof Error ? error.message : error,
|
|
137
|
+
phase,
|
|
135
138
|
releaseId: this.releaseId
|
|
136
139
|
})
|
|
137
140
|
|
|
@@ -143,6 +146,7 @@ export default class ReleaseGroup extends EventEmitter {
|
|
|
143
146
|
exitCode: status.exitCode ?? null,
|
|
144
147
|
exitSignal: status.exitSignal ?? null,
|
|
145
148
|
logs: status.logs,
|
|
149
|
+
phase,
|
|
146
150
|
pid: status.pid ?? null,
|
|
147
151
|
processId: status.id,
|
|
148
152
|
releaseId: this.releaseId,
|
package/test/rollbridge.test.js
CHANGED
|
@@ -123,8 +123,8 @@ test("wildcard proxy bind host targets release processes through loopback", asyn
|
|
|
123
123
|
}
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
test("failed release startup logs process output
|
|
127
|
-
const fixture = await createFixture({webCommand: `${JSON.stringify(process.execPath)} -e "console.log('startup stdout'); console.error('startup stderr'); const http = require('node:http'); http.createServer((_request, response) => { response.writeHead(500); response.end('bad') }).listen(Number(process.env.ROLLBRIDGE_PORT), '127.0.0.1')"`, webHealthTimeoutMs: 500})
|
|
126
|
+
test("failed release startup logs process output and cleanup status", async () => {
|
|
127
|
+
const fixture = await createFixture({handoffService: true, webCommand: `${JSON.stringify(process.execPath)} -e "console.log('startup stdout'); console.error('startup stderr'); const http = require('node:http'); http.createServer((_request, response) => { response.writeHead(500); response.end('bad') }).listen(Number(process.env.ROLLBRIDGE_PORT), '127.0.0.1')"`, webHealthTimeoutMs: 500})
|
|
128
128
|
/** @type {Array<{data?: Record<string, import("../src/json.js").JsonValue>, message: string}>} */
|
|
129
129
|
const logs = []
|
|
130
130
|
const daemon = new RollbridgeDaemon({
|
|
@@ -140,13 +140,22 @@ test("failed release startup logs process output before cleanup", async () => {
|
|
|
140
140
|
/Health check failed/
|
|
141
141
|
)
|
|
142
142
|
|
|
143
|
-
const processStatusLog = logs.find((entry) => entry.message === "release startup process status" && entry.data?.processId === "web")
|
|
143
|
+
const processStatusLog = logs.find((entry) => entry.message === "release startup process status" && entry.data?.phase === "before cleanup" && entry.data?.processId === "web")
|
|
144
|
+
const cleanupProcessStatusLog = logs.find((entry) => entry.message === "release startup process status" && entry.data?.phase === "after cleanup" && entry.data?.processId === "web")
|
|
145
|
+
const handoffServiceStatusLog = logs.find((entry) => entry.message === "release startup process status" && entry.data?.phase === "after cleanup" && entry.data?.processId === "beacon")
|
|
144
146
|
|
|
145
147
|
assert.ok(processStatusLog, "expected failed web process diagnostics to be logged")
|
|
146
148
|
assert.ok(processStatusLog.data, "expected diagnostic data")
|
|
147
149
|
assert.ok(Array.isArray(processStatusLog.data.logs), "expected retained process output in diagnostics")
|
|
148
150
|
assert.ok(processStatusLog.data.logs.some((entry) => typeof entry === "object" && entry && "line" in entry && entry.line === "startup stdout"))
|
|
149
151
|
assert.ok(processStatusLog.data.logs.some((entry) => typeof entry === "object" && entry && "line" in entry && entry.line === "startup stderr"))
|
|
152
|
+
assert.equal(processStatusLog.data.state, "running")
|
|
153
|
+
assert.ok(cleanupProcessStatusLog, "expected failed web cleanup diagnostics to be logged")
|
|
154
|
+
assert.equal(cleanupProcessStatusLog.data?.state, "stopped")
|
|
155
|
+
assert.equal(cleanupProcessStatusLog.data?.exitSignal, "SIGTERM")
|
|
156
|
+
assert.ok(handoffServiceStatusLog, "expected handoff service cleanup diagnostics to be logged")
|
|
157
|
+
assert.equal(handoffServiceStatusLog.data?.state, "stopped")
|
|
158
|
+
assert.equal(handoffServiceStatusLog.data?.exitSignal, "SIGTERM")
|
|
150
159
|
} finally {
|
|
151
160
|
await daemon.shutdown()
|
|
152
161
|
await fs.rm(fixture.root, {force: true, recursive: true})
|