@rpcbase/cli 0.192.0 → 0.193.0
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 +1 -1
- package/src/cmd-deploy/index.js +41 -2
package/package.json
CHANGED
package/src/cmd-deploy/index.js
CHANGED
|
@@ -284,12 +284,50 @@ export const deploy = async (argv) => {
|
|
|
284
284
|
await ssh(`cd ~/apps/${baseDeployDir}/infrastructure && RB_DEPLOY_DIR=${shellQuote(baseDeployDir)} node ctrl.js ${action}-instance ${instance} prod`, true)
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
const printInstanceDiagnostics = async (instance) => {
|
|
288
|
+
const composePrefix = [
|
|
289
|
+
`cd ~/apps/${baseDeployDir}/infrastructure &&`,
|
|
290
|
+
`RB_DEPLOY_DIR=${shellQuote(baseDeployDir)}`,
|
|
291
|
+
"docker compose -p sample-app --env-file ../.env -f compose.yml -f compose.instances.yml",
|
|
292
|
+
`--profile instance-${instance}`,
|
|
293
|
+
].join(" ")
|
|
294
|
+
const services = `server-${instance} worker-${instance}`
|
|
295
|
+
|
|
296
|
+
console.error(`Instance ${instance} diagnostics:`)
|
|
297
|
+
for (const command of [
|
|
298
|
+
`${composePrefix} ps ${services}`,
|
|
299
|
+
`${composePrefix} logs --tail=160 ${services}`,
|
|
300
|
+
]) {
|
|
301
|
+
try {
|
|
302
|
+
await ssh(command, true)
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error(`Failed to run diagnostics command: ${error instanceof Error ? error.message : error}`)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
287
309
|
const waitForInstance = async (instance, target) => {
|
|
288
310
|
const port = Number(target?.port)
|
|
289
311
|
if (!Number.isFinite(port) || port <= 0) throw new Error(`Cannot healthcheck instance ${instance}: invalid port`)
|
|
290
312
|
|
|
291
|
-
const
|
|
292
|
-
const
|
|
313
|
+
const healthPath = typeof target?.healthPath === "string" && target.healthPath.startsWith("/") ? target.healthPath : "/_healthcheck"
|
|
314
|
+
const url = `http://127.0.0.1:${port}${healthPath}`
|
|
315
|
+
const healthcheckScript = [
|
|
316
|
+
`const url = ${JSON.stringify(url)}`,
|
|
317
|
+
"const controller = new AbortController()",
|
|
318
|
+
"const timeout = setTimeout(() => controller.abort(), 2000)",
|
|
319
|
+
"fetch(url, { signal: controller.signal }).then(async (res) => {",
|
|
320
|
+
" clearTimeout(timeout)",
|
|
321
|
+
" if (res.status < 500) process.exit(0)",
|
|
322
|
+
" const body = await res.text().catch(() => '')",
|
|
323
|
+
" console.error(`healthcheck ${url} failed with status ${res.status}: ${body.slice(0, 500)}`)",
|
|
324
|
+
" process.exit(1)",
|
|
325
|
+
"}).catch((error) => {",
|
|
326
|
+
" clearTimeout(timeout)",
|
|
327
|
+
" console.error(`healthcheck ${url} failed: ${error?.code || error?.name || 'Error'} ${error?.message || error}`)",
|
|
328
|
+
" process.exit(1)",
|
|
329
|
+
"})",
|
|
330
|
+
].join(";")
|
|
293
331
|
for (let attempt = 1; attempt <= 60; attempt += 1) {
|
|
294
332
|
try {
|
|
295
333
|
await ssh(`node -e ${shellQuote(healthcheckScript)}`)
|
|
@@ -300,6 +338,7 @@ export const deploy = async (argv) => {
|
|
|
300
338
|
}
|
|
301
339
|
}
|
|
302
340
|
|
|
341
|
+
await printInstanceDiagnostics(instance)
|
|
303
342
|
throw new Error(`Instance ${instance} did not become healthy at ${url}`)
|
|
304
343
|
}
|
|
305
344
|
|