@nmakarov/cli-toolkit 0.51.0 → 0.55.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/dist/cli-runner.cjs +23 -12
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +23 -12
- package/dist/cli-runner.js.map +1 -1
- package/dist/deploy.cjs +234 -16
- package/dist/deploy.cjs.map +1 -1
- package/dist/deploy.js +221 -10
- package/dist/deploy.js.map +1 -1
- package/dist/index.cjs +246 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +231 -18
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +14 -5
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +14 -5
- package/dist/init.js.map +1 -1
- package/dist/tasks.cjs +10 -8
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +10 -8
- package/dist/tasks.js.map +1 -1
- package/package.json +1 -1
- package/scripts/deploy/cli.js +5 -1
package/dist/deploy.cjs
CHANGED
|
@@ -34,9 +34,12 @@ __export(deploy_exports, {
|
|
|
34
34
|
ensureEnvOnRemote: () => ensureEnvOnRemote,
|
|
35
35
|
ensureRemoteRepo: () => ensureRemoteRepo,
|
|
36
36
|
ensureRepoDependencies: () => ensureRepoDependencies,
|
|
37
|
+
getPm2Process: () => getPm2Process,
|
|
37
38
|
initServiceStructure: () => initServiceStructure,
|
|
38
39
|
installDeps: () => installDeps,
|
|
39
40
|
installOperatorShell: () => installOperatorShell,
|
|
41
|
+
isFreshOnline: () => isFreshOnline,
|
|
42
|
+
isPidAlive: () => isPidAlive,
|
|
40
43
|
listReleases: () => listReleases,
|
|
41
44
|
loadServices: () => loadServices,
|
|
42
45
|
npmEnv: () => npmEnv,
|
|
@@ -55,6 +58,7 @@ __export(deploy_exports, {
|
|
|
55
58
|
resolveServiceFrom: () => resolveServiceFrom,
|
|
56
59
|
rollbackService: () => rollbackService,
|
|
57
60
|
run: () => run,
|
|
61
|
+
runCapture: () => runCapture,
|
|
58
62
|
runReleaseTests: () => runReleaseTests,
|
|
59
63
|
runRemoteCli: () => runRemoteCli,
|
|
60
64
|
runRemoteStatus: () => runRemoteStatus,
|
|
@@ -63,7 +67,10 @@ __export(deploy_exports, {
|
|
|
63
67
|
servicePaths: () => servicePaths,
|
|
64
68
|
shellQuote: () => shellQuote,
|
|
65
69
|
sshRun: () => sshRun,
|
|
70
|
+
startPm2: () => startPm2,
|
|
71
|
+
stopPm2: () => stopPm2,
|
|
66
72
|
syncEnv: () => syncEnv,
|
|
73
|
+
waitPm2: () => waitPm2,
|
|
67
74
|
writeReleaseBuildInfo: () => writeReleaseBuildInfo
|
|
68
75
|
});
|
|
69
76
|
module.exports = __toCommonJS(deploy_exports);
|
|
@@ -81,8 +88,13 @@ function defineService(service) {
|
|
|
81
88
|
const pm2 = {
|
|
82
89
|
appName: service.name,
|
|
83
90
|
args: "",
|
|
91
|
+
stopAllowance: 60,
|
|
84
92
|
...service.pm2
|
|
85
93
|
};
|
|
94
|
+
if (pm2.killTimeout == null) {
|
|
95
|
+
const stopSec = Number(pm2.stopAllowance);
|
|
96
|
+
pm2.killTimeout = Number.isFinite(stopSec) && stopSec > 0 ? Math.floor(stopSec * 1e3) + 5e3 : 65e3;
|
|
97
|
+
}
|
|
86
98
|
const nginx = service.nginx ? { siteName: service.name, ...service.nginx } : null;
|
|
87
99
|
return {
|
|
88
100
|
repoDirName: deriveRepoDirName(service.repoUrl),
|
|
@@ -163,6 +175,30 @@ function run(cmd, args, options = {}) {
|
|
|
163
175
|
function runShell(command, options = {}) {
|
|
164
176
|
return run("bash", ["-lc", command], options);
|
|
165
177
|
}
|
|
178
|
+
function runCapture(cmd, args, options = {}) {
|
|
179
|
+
const { cwd, env, logger, allowFail = false } = options;
|
|
180
|
+
return new Promise((resolve2, reject) => {
|
|
181
|
+
logger?.info?.(`$ ${cmd} ${args.join(" ")}${cwd ? ` (cwd=${cwd})` : ""}`);
|
|
182
|
+
const child = (0, import_node_child_process.spawn)(cmd, args, {
|
|
183
|
+
cwd,
|
|
184
|
+
env: env ?? process.env,
|
|
185
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
186
|
+
});
|
|
187
|
+
let stdout = "";
|
|
188
|
+
let stderr = "";
|
|
189
|
+
child.stdout?.on("data", (chunk) => {
|
|
190
|
+
stdout += chunk.toString();
|
|
191
|
+
});
|
|
192
|
+
child.stderr?.on("data", (chunk) => {
|
|
193
|
+
stderr += chunk.toString();
|
|
194
|
+
});
|
|
195
|
+
child.on("error", reject);
|
|
196
|
+
child.on("close", (code) => {
|
|
197
|
+
if (code === 0 || allowFail) resolve2({ stdout, stderr, code });
|
|
198
|
+
else reject(new Error(`${cmd} exited with code ${code}${stderr ? `: ${stderr.trim()}` : ""}`));
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
166
202
|
|
|
167
203
|
// src/deploy/log.js
|
|
168
204
|
var import_promises = require("fs/promises");
|
|
@@ -380,7 +416,7 @@ async function runReleaseTests(service, releasePath, paths, options = {}) {
|
|
|
380
416
|
// src/deploy/prune.js
|
|
381
417
|
var import_promises7 = require("fs/promises");
|
|
382
418
|
async function pruneReleases(service, paths, options = {}) {
|
|
383
|
-
const { dryRun = false, logger = console } = options;
|
|
419
|
+
const { dryRun = false, logger = console, protect = [] } = options;
|
|
384
420
|
const keep = service.keepReleases ?? 3;
|
|
385
421
|
const releases = await listReleases(paths);
|
|
386
422
|
let activeName = null;
|
|
@@ -394,6 +430,9 @@ async function pruneReleases(service, paths, options = {}) {
|
|
|
394
430
|
if (keepSet.size < keep) keepSet.add(rel.name);
|
|
395
431
|
}
|
|
396
432
|
if (activeName) keepSet.add(activeName);
|
|
433
|
+
for (const name of protect) {
|
|
434
|
+
if (name) keepSet.add(name);
|
|
435
|
+
}
|
|
397
436
|
const toRemove = releases.filter((rel) => !keepSet.has(rel.name));
|
|
398
437
|
for (const rel of toRemove) {
|
|
399
438
|
if (dryRun) {
|
|
@@ -407,14 +446,139 @@ async function pruneReleases(service, paths, options = {}) {
|
|
|
407
446
|
}
|
|
408
447
|
|
|
409
448
|
// src/deploy/pm2.js
|
|
449
|
+
function sleep(ms) {
|
|
450
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
451
|
+
}
|
|
452
|
+
function isPidAlive(pid) {
|
|
453
|
+
const n = Number(pid);
|
|
454
|
+
if (!Number.isFinite(n) || n <= 0) return false;
|
|
455
|
+
try {
|
|
456
|
+
process.kill(n, 0);
|
|
457
|
+
return true;
|
|
458
|
+
} catch {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function getPm2Process(appName, options = {}) {
|
|
463
|
+
const { logger } = options;
|
|
464
|
+
const { stdout } = await runCapture("bash", ["-lc", "pm2 jlist"], { logger });
|
|
465
|
+
let list;
|
|
466
|
+
try {
|
|
467
|
+
list = JSON.parse(stdout || "[]");
|
|
468
|
+
} catch (err) {
|
|
469
|
+
throw new Error(`pm2 jlist: invalid JSON (${err?.message ?? err})`);
|
|
470
|
+
}
|
|
471
|
+
if (!Array.isArray(list)) return null;
|
|
472
|
+
return list.find((p) => p?.name === appName) ?? null;
|
|
473
|
+
}
|
|
474
|
+
async function waitPm2(appName, predicate, options = {}) {
|
|
475
|
+
const {
|
|
476
|
+
timeoutMs = 65e3,
|
|
477
|
+
pollMs = 500,
|
|
478
|
+
dryRun = false,
|
|
479
|
+
logger = console,
|
|
480
|
+
label = "condition"
|
|
481
|
+
} = options;
|
|
482
|
+
if (dryRun) {
|
|
483
|
+
logger.info?.(`[dryRun] would wait pm2 ${appName} for ${label}`);
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
const deadline = Date.now() + timeoutMs;
|
|
487
|
+
let lastStatus = "(unknown)";
|
|
488
|
+
while (Date.now() < deadline) {
|
|
489
|
+
const proc = await getPm2Process(appName, { logger });
|
|
490
|
+
lastStatus = proc?.pm2_env?.status ?? "(missing)";
|
|
491
|
+
if (predicate(proc)) return proc;
|
|
492
|
+
await sleep(pollMs);
|
|
493
|
+
}
|
|
494
|
+
throw new Error(
|
|
495
|
+
`pm2 wait timed out after ${timeoutMs}ms for ${appName} (${label}); last status=${lastStatus}`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
function isFreshOnline(proc, oldPid) {
|
|
499
|
+
if (proc?.pm2_env?.status !== "online") return false;
|
|
500
|
+
const pid = Number(proc.pid);
|
|
501
|
+
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
502
|
+
if (oldPid != null) {
|
|
503
|
+
if (pid === oldPid) return false;
|
|
504
|
+
if (isPidAlive(oldPid)) return false;
|
|
505
|
+
}
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
410
508
|
async function reloadPm2(paths, options = {}) {
|
|
411
|
-
const { dryRun = false, logger = console } = options;
|
|
509
|
+
const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
|
|
412
510
|
if (dryRun) {
|
|
413
511
|
logger.info(`[dryRun] would pm2 startOrReload ${paths.ecosystem} --update-env`);
|
|
414
512
|
return;
|
|
415
513
|
}
|
|
514
|
+
let oldPid = null;
|
|
515
|
+
if (appName) {
|
|
516
|
+
const before = await getPm2Process(appName, { logger });
|
|
517
|
+
const n = Number(before?.pid);
|
|
518
|
+
if (Number.isFinite(n) && n > 0 && before?.pm2_env?.status === "online") {
|
|
519
|
+
oldPid = n;
|
|
520
|
+
logger.info(`pm2 ${appName}: reloading (old pid=${oldPid})`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
416
523
|
await runShell(`pm2 startOrReload "${paths.ecosystem}" --update-env`, { logger });
|
|
417
524
|
logger.info("pm2 reloaded");
|
|
525
|
+
if (appName) {
|
|
526
|
+
const proc = await waitPm2(
|
|
527
|
+
appName,
|
|
528
|
+
(p) => isFreshOnline(p, oldPid),
|
|
529
|
+
{
|
|
530
|
+
timeoutMs: waitTimeoutMs,
|
|
531
|
+
logger,
|
|
532
|
+
label: oldPid ? `online on new pid (old ${oldPid} gone)` : "online after reload"
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
logger.info(`pm2 ${appName} online pid=${proc?.pid ?? "?"}`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async function stopPm2(appName, options = {}) {
|
|
539
|
+
const { dryRun = false, logger = console, waitTimeoutMs = 65e3 } = options;
|
|
540
|
+
if (dryRun) {
|
|
541
|
+
logger.info(`[dryRun] would pm2 stop ${appName}`);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const before = await getPm2Process(appName, { logger });
|
|
545
|
+
if (!before) {
|
|
546
|
+
logger.info(`pm2 ${appName}: not present (already stopped)`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
if (before.pm2_env?.status === "stopped") {
|
|
550
|
+
logger.info(`pm2 ${appName}: already stopped`);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const oldPid = Number(before.pid);
|
|
554
|
+
await runShell(`pm2 stop "${appName}"`, { logger });
|
|
555
|
+
await waitPm2(
|
|
556
|
+
appName,
|
|
557
|
+
(proc) => {
|
|
558
|
+
if (proc && proc.pm2_env?.status !== "stopped") return false;
|
|
559
|
+
if (Number.isFinite(oldPid) && oldPid > 0 && isPidAlive(oldPid)) return false;
|
|
560
|
+
return true;
|
|
561
|
+
},
|
|
562
|
+
{ timeoutMs: waitTimeoutMs, logger, label: "stopped" }
|
|
563
|
+
);
|
|
564
|
+
logger.info(`pm2 ${appName} stopped`);
|
|
565
|
+
}
|
|
566
|
+
async function startPm2(paths, options = {}) {
|
|
567
|
+
const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
|
|
568
|
+
if (dryRun) {
|
|
569
|
+
logger.info(`[dryRun] would pm2 start ${paths.ecosystem} --update-env`);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
await runShell(`pm2 start "${paths.ecosystem}" --update-env`, { logger });
|
|
573
|
+
logger.info("pm2 started");
|
|
574
|
+
if (appName) {
|
|
575
|
+
const proc = await waitPm2(
|
|
576
|
+
appName,
|
|
577
|
+
(p) => isFreshOnline(p, null),
|
|
578
|
+
{ timeoutMs: waitTimeoutMs, logger, label: "online after start" }
|
|
579
|
+
);
|
|
580
|
+
logger.info(`pm2 ${appName} online pid=${proc?.pid ?? "?"}`);
|
|
581
|
+
}
|
|
418
582
|
}
|
|
419
583
|
|
|
420
584
|
// src/deploy/nginx.js
|
|
@@ -643,10 +807,26 @@ async function requireDeployRoot(parentDir, serviceRoot) {
|
|
|
643
807
|
This is meant to run on the target host (where ${parentDir} exists). For a local dry run use --appsRoot=/tmp/<service>.`
|
|
644
808
|
);
|
|
645
809
|
}
|
|
810
|
+
function resolveKillTimeoutMs(pm2) {
|
|
811
|
+
const explicit = Number(pm2?.killTimeout);
|
|
812
|
+
if (Number.isFinite(explicit) && explicit > 0) return Math.floor(explicit);
|
|
813
|
+
const stopSec = Number(pm2?.stopAllowance);
|
|
814
|
+
if (Number.isFinite(stopSec) && stopSec > 0) return Math.floor(stopSec * 1e3) + 5e3;
|
|
815
|
+
return 65e3;
|
|
816
|
+
}
|
|
817
|
+
function resolvePm2Args(pm2) {
|
|
818
|
+
const base = String(pm2?.args ?? "").trim();
|
|
819
|
+
const stopSec = Number(pm2?.stopAllowance);
|
|
820
|
+
if (!Number.isFinite(stopSec) || stopSec <= 0) return base;
|
|
821
|
+
if (/(?:^|\s)--stopAllowance=/.test(base)) return base;
|
|
822
|
+
return `${base}${base ? " " : ""}--stopAllowance=${Math.floor(stopSec)}`.trim();
|
|
823
|
+
}
|
|
646
824
|
function buildEcosystemConfig(service, paths) {
|
|
647
825
|
const { pm2 } = service;
|
|
648
826
|
const outLog = (0, import_node_path8.join)(paths.logs, `${pm2.appName}.out.log`);
|
|
649
827
|
const errLog = (0, import_node_path8.join)(paths.logs, `${pm2.appName}.err.log`);
|
|
828
|
+
const killTimeoutMs = resolveKillTimeoutMs(pm2);
|
|
829
|
+
const args = resolvePm2Args(pm2);
|
|
650
830
|
return `/**
|
|
651
831
|
* pm2 ecosystem for ${service.name} \u2014 written by cli-toolkit deploy from the
|
|
652
832
|
* service manifest (init/deploy). Do not hand-edit; change pm2.* in the
|
|
@@ -658,7 +838,7 @@ module.exports = {
|
|
|
658
838
|
name: "${pm2.appName}",
|
|
659
839
|
script: "${pm2.script}",
|
|
660
840
|
cwd: "${paths.current}",
|
|
661
|
-
args:
|
|
841
|
+
args: ${JSON.stringify(args)},
|
|
662
842
|
instances: 1,
|
|
663
843
|
exec_mode: "fork",
|
|
664
844
|
autorestart: true,
|
|
@@ -666,6 +846,8 @@ module.exports = {
|
|
|
666
846
|
max_restarts: 10,
|
|
667
847
|
restart_delay: 2000,
|
|
668
848
|
max_memory_restart: "1500M",
|
|
849
|
+
// Grace window after SIGINT/SIGTERM before SIGKILL (ms). Align with --stopAllowance.
|
|
850
|
+
kill_timeout: ${killTimeoutMs},
|
|
669
851
|
out_file: "${outLog}",
|
|
670
852
|
error_file: "${errLog}",
|
|
671
853
|
merge_logs: true,
|
|
@@ -866,15 +1048,27 @@ async function bootstrapHost(service, options = {}) {
|
|
|
866
1048
|
}
|
|
867
1049
|
|
|
868
1050
|
// src/deploy/deploy-service.js
|
|
1051
|
+
var import_promises13 = require("fs/promises");
|
|
1052
|
+
function resolveKillTimeoutMs2(service) {
|
|
1053
|
+
const explicit = Number(service.pm2?.killTimeout);
|
|
1054
|
+
if (Number.isFinite(explicit) && explicit > 0) return Math.floor(explicit);
|
|
1055
|
+
const stopSec = Number(service.pm2?.stopAllowance);
|
|
1056
|
+
if (Number.isFinite(stopSec) && stopSec > 0) return Math.floor(stopSec * 1e3) + 5e3;
|
|
1057
|
+
return 65e3;
|
|
1058
|
+
}
|
|
869
1059
|
async function deployService(service, options = {}) {
|
|
870
1060
|
const {
|
|
871
1061
|
dryRun = false,
|
|
872
1062
|
skipPull = false,
|
|
873
1063
|
skipTests = false,
|
|
874
1064
|
skipNginx = false,
|
|
1065
|
+
stopFirst = false,
|
|
875
1066
|
logger = console
|
|
876
1067
|
} = options;
|
|
877
1068
|
const paths = servicePaths(service);
|
|
1069
|
+
const appName = service.pm2.appName;
|
|
1070
|
+
const killTimeoutMs = resolveKillTimeoutMs2(service);
|
|
1071
|
+
const waitTimeoutMs = killTimeoutMs + 1e4;
|
|
878
1072
|
await initServiceStructure(service, { dryRun, logger });
|
|
879
1073
|
if (!skipPull) await pullRepo(service, { dryRun, logger });
|
|
880
1074
|
await syncEnv(service, { dryRun, logger });
|
|
@@ -882,21 +1076,38 @@ async function deployService(service, options = {}) {
|
|
|
882
1076
|
await writeReleaseBuildInfo(service, releasePath, { stamp, dryRun, logger });
|
|
883
1077
|
await installDeps(service, releasePath, paths, { dryRun, logger });
|
|
884
1078
|
if (!skipTests) await runReleaseTests(service, releasePath, paths, { dryRun, logger });
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1079
|
+
let previousReleaseName = null;
|
|
1080
|
+
try {
|
|
1081
|
+
const prev = await (0, import_promises13.readlink)(paths.current);
|
|
1082
|
+
previousReleaseName = prev.split("/").pop() || null;
|
|
1083
|
+
} catch {
|
|
1084
|
+
}
|
|
1085
|
+
if (stopFirst) {
|
|
1086
|
+
logger.info(`deploy mode=stopFirst app=${appName} killTimeoutMs=${killTimeoutMs}`);
|
|
1087
|
+
await stopPm2(appName, { dryRun, logger, waitTimeoutMs });
|
|
1088
|
+
await activateRelease(releasePath, paths, { dryRun, logger });
|
|
1089
|
+
await pruneReleases(service, paths, { dryRun, logger });
|
|
1090
|
+
await startPm2(paths, { dryRun, logger, appName, waitTimeoutMs });
|
|
1091
|
+
} else {
|
|
1092
|
+
logger.info(
|
|
1093
|
+
`deploy mode=rolling app=${appName} killTimeoutMs=${killTimeoutMs}` + (previousReleaseName ? ` previous=${previousReleaseName}` : "")
|
|
1094
|
+
);
|
|
1095
|
+
await activateRelease(releasePath, paths, { dryRun, logger });
|
|
1096
|
+
await reloadPm2(paths, { dryRun, logger, appName, waitTimeoutMs });
|
|
1097
|
+
await pruneReleases(service, paths, { dryRun, logger });
|
|
1098
|
+
}
|
|
888
1099
|
if (!skipNginx) await enableNginxUpstream(service, { dryRun, logger });
|
|
889
|
-
const summary = `deploy complete stamp=${stamp} dryRun=${dryRun}`;
|
|
1100
|
+
const summary = `deploy complete stamp=${stamp} mode=${stopFirst ? "stopFirst" : "rolling"} dryRun=${dryRun}`;
|
|
890
1101
|
logger.info(summary);
|
|
891
1102
|
if (!dryRun) await appendDeployLog(paths.deployLog, summary);
|
|
892
|
-
return { stamp, releasePath };
|
|
1103
|
+
return { stamp, releasePath, mode: stopFirst ? "stopFirst" : "rolling" };
|
|
893
1104
|
}
|
|
894
1105
|
|
|
895
1106
|
// src/deploy/provision-service.js
|
|
896
|
-
var
|
|
1107
|
+
var import_promises14 = require("fs/promises");
|
|
897
1108
|
async function pathExists6(path) {
|
|
898
1109
|
try {
|
|
899
|
-
await (0,
|
|
1110
|
+
await (0, import_promises14.access)(path);
|
|
900
1111
|
return true;
|
|
901
1112
|
} catch {
|
|
902
1113
|
return false;
|
|
@@ -930,7 +1141,7 @@ async function provisionService(service, options = {}) {
|
|
|
930
1141
|
}
|
|
931
1142
|
|
|
932
1143
|
// src/deploy/rollback-service.js
|
|
933
|
-
var
|
|
1144
|
+
var import_promises15 = require("fs/promises");
|
|
934
1145
|
async function rollbackService(service, options = {}) {
|
|
935
1146
|
const { release: targetName, dryRun = false, logger = console } = options;
|
|
936
1147
|
const paths = servicePaths(service);
|
|
@@ -938,7 +1149,7 @@ async function rollbackService(service, options = {}) {
|
|
|
938
1149
|
if (releases.length === 0) throw new Error("No releases to roll back to");
|
|
939
1150
|
let activeName = null;
|
|
940
1151
|
try {
|
|
941
|
-
const target = await (0,
|
|
1152
|
+
const target = await (0, import_promises15.readlink)(paths.current);
|
|
942
1153
|
activeName = target.split("/").pop();
|
|
943
1154
|
} catch {
|
|
944
1155
|
throw new Error("No active release (current symlink missing)");
|
|
@@ -965,14 +1176,14 @@ async function rollbackService(service, options = {}) {
|
|
|
965
1176
|
}
|
|
966
1177
|
|
|
967
1178
|
// src/deploy/ssh-remote.js
|
|
968
|
-
var
|
|
1179
|
+
var import_promises16 = require("fs/promises");
|
|
969
1180
|
var import_node_os3 = require("os");
|
|
970
1181
|
var import_node_path10 = require("path");
|
|
971
1182
|
var import_node_child_process4 = require("child_process");
|
|
972
1183
|
var REMOTE_CLI_REL = "node_modules/@nmakarov/cli-toolkit/scripts/deploy/cli.js";
|
|
973
1184
|
async function pathExists7(path) {
|
|
974
1185
|
try {
|
|
975
|
-
await (0,
|
|
1186
|
+
await (0, import_promises16.access)(path);
|
|
976
1187
|
return true;
|
|
977
1188
|
} catch {
|
|
978
1189
|
return false;
|
|
@@ -1064,9 +1275,9 @@ async function ensureEnvOnRemote(host, service, options = {}) {
|
|
|
1064
1275
|
if (!await pathExists7(localPath)) return false;
|
|
1065
1276
|
logger.info(`copying .env ${localPath} \u2192 ${host}:${paths.repoEnv}`);
|
|
1066
1277
|
await sshRun(host, `mkdir -p ${shellQuote((0, import_node_path10.dirname)(paths.repoEnv))}`, { logger });
|
|
1067
|
-
const scrubbed = scrubEnvContent(await (0,
|
|
1278
|
+
const scrubbed = scrubEnvContent(await (0, import_promises16.readFile)(localPath, "utf8"), service.envScrubPatterns ?? []);
|
|
1068
1279
|
const tmp = (0, import_node_path10.join)((0, import_node_os3.tmpdir)(), `deploy-env-${Date.now()}`);
|
|
1069
|
-
await (0,
|
|
1280
|
+
await (0, import_promises16.writeFile)(tmp, scrubbed, { mode: 384 });
|
|
1070
1281
|
await scp(tmp, `${host}:${paths.repoEnv}`, { logger });
|
|
1071
1282
|
await sshRun(host, `chmod 600 ${shellQuote(paths.repoEnv)}`, { logger });
|
|
1072
1283
|
return true;
|
|
@@ -1177,9 +1388,12 @@ function resolveServiceFrom(serviceMap, name, { appsRoot } = {}) {
|
|
|
1177
1388
|
ensureEnvOnRemote,
|
|
1178
1389
|
ensureRemoteRepo,
|
|
1179
1390
|
ensureRepoDependencies,
|
|
1391
|
+
getPm2Process,
|
|
1180
1392
|
initServiceStructure,
|
|
1181
1393
|
installDeps,
|
|
1182
1394
|
installOperatorShell,
|
|
1395
|
+
isFreshOnline,
|
|
1396
|
+
isPidAlive,
|
|
1183
1397
|
listReleases,
|
|
1184
1398
|
loadServices,
|
|
1185
1399
|
npmEnv,
|
|
@@ -1198,6 +1412,7 @@ function resolveServiceFrom(serviceMap, name, { appsRoot } = {}) {
|
|
|
1198
1412
|
resolveServiceFrom,
|
|
1199
1413
|
rollbackService,
|
|
1200
1414
|
run,
|
|
1415
|
+
runCapture,
|
|
1201
1416
|
runReleaseTests,
|
|
1202
1417
|
runRemoteCli,
|
|
1203
1418
|
runRemoteStatus,
|
|
@@ -1206,7 +1421,10 @@ function resolveServiceFrom(serviceMap, name, { appsRoot } = {}) {
|
|
|
1206
1421
|
servicePaths,
|
|
1207
1422
|
shellQuote,
|
|
1208
1423
|
sshRun,
|
|
1424
|
+
startPm2,
|
|
1425
|
+
stopPm2,
|
|
1209
1426
|
syncEnv,
|
|
1427
|
+
waitPm2,
|
|
1210
1428
|
writeReleaseBuildInfo
|
|
1211
1429
|
});
|
|
1212
1430
|
//# sourceMappingURL=deploy.cjs.map
|