@nmakarov/cli-toolkit 0.59.0 → 0.61.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/deploy.cjs CHANGED
@@ -507,10 +507,47 @@ function isFreshOnline(proc, oldPid) {
507
507
  }
508
508
  return true;
509
509
  }
510
+ async function deletePm2App(appName, options = {}) {
511
+ const { dryRun = false, logger = console, waitTimeoutMs = 65e3, oldPid = null } = options;
512
+ if (dryRun) {
513
+ logger.info(`[dryRun] would pm2 delete ${appName}`);
514
+ return;
515
+ }
516
+ const before = await getPm2Process(appName, { logger });
517
+ if (!before) {
518
+ logger.info(`pm2 ${appName}: not present (skip delete)`);
519
+ return;
520
+ }
521
+ await runShell(`pm2 delete "${appName}"`, { logger });
522
+ await waitPm2(
523
+ appName,
524
+ (proc) => {
525
+ if (proc) return false;
526
+ if (oldPid != null && isPidAlive(oldPid)) return false;
527
+ return true;
528
+ },
529
+ { timeoutMs: waitTimeoutMs, logger, label: "deleted (process gone)" }
530
+ );
531
+ logger.info(`pm2 ${appName} deleted`);
532
+ }
533
+ async function startFromEcosystem(paths, options = {}) {
534
+ const { dryRun = false, logger = console } = options;
535
+ if (dryRun) {
536
+ logger.info(`[dryRun] would pm2 start ${paths.ecosystem} --update-env`);
537
+ return;
538
+ }
539
+ await runShell(
540
+ `ENV=production NODE_ENV=production pm2 start "${paths.ecosystem}" --update-env`,
541
+ { logger }
542
+ );
543
+ logger.info("pm2 started from ecosystem");
544
+ }
510
545
  async function reloadPm2(paths, options = {}) {
511
546
  const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
512
547
  if (dryRun) {
513
- logger.info(`[dryRun] would pm2 startOrReload ${paths.ecosystem} --update-env`);
548
+ logger.info(
549
+ `[dryRun] would pm2 delete${appName ? ` ${appName}` : ""} + start ${paths.ecosystem} --update-env`
550
+ );
514
551
  return;
515
552
  }
516
553
  let oldPid = null;
@@ -519,14 +556,15 @@ async function reloadPm2(paths, options = {}) {
519
556
  const n = Number(before?.pid);
520
557
  if (Number.isFinite(n) && n > 0 && before?.pm2_env?.status === "online") {
521
558
  oldPid = n;
522
- logger.info(`pm2 ${appName}: reloading (old pid=${oldPid})`);
559
+ logger.info(`pm2 ${appName}: recreate (old pid=${oldPid})`);
523
560
  }
561
+ await deletePm2App(appName, { dryRun, logger, waitTimeoutMs, oldPid });
562
+ } else {
563
+ logger.warn?.(
564
+ "reloadPm2: appName missing; starting ecosystem without delete (pass appName so script/env always recreate cleanly)"
565
+ );
524
566
  }
525
- await runShell(
526
- `ENV=production NODE_ENV=production pm2 startOrReload "${paths.ecosystem}" --update-env`,
527
- { logger }
528
- );
529
- logger.info("pm2 reloaded");
567
+ await startFromEcosystem(paths, { dryRun, logger });
530
568
  if (appName) {
531
569
  const proc = await waitPm2(
532
570
  appName,
@@ -534,7 +572,7 @@ async function reloadPm2(paths, options = {}) {
534
572
  {
535
573
  timeoutMs: waitTimeoutMs,
536
574
  logger,
537
- label: oldPid ? `online on new pid (old ${oldPid} gone)` : "online after reload"
575
+ label: oldPid ? `online on new pid (old ${oldPid} gone)` : "online after recreate"
538
576
  }
539
577
  );
540
578
  logger.info(`pm2 ${appName} online pid=${proc?.pid ?? "?"}`);
@@ -571,14 +609,15 @@ async function stopPm2(appName, options = {}) {
571
609
  async function startPm2(paths, options = {}) {
572
610
  const { dryRun = false, logger = console, appName = null, waitTimeoutMs = 65e3 } = options;
573
611
  if (dryRun) {
574
- logger.info(`[dryRun] would pm2 start ${paths.ecosystem} --update-env`);
612
+ logger.info(
613
+ `[dryRun] would pm2 delete${appName ? ` ${appName}` : ""} + start ${paths.ecosystem} --update-env`
614
+ );
575
615
  return;
576
616
  }
577
- await runShell(
578
- `ENV=production NODE_ENV=production pm2 start "${paths.ecosystem}" --update-env`,
579
- { logger }
580
- );
581
- logger.info("pm2 started");
617
+ if (appName) {
618
+ await deletePm2App(appName, { dryRun, logger, waitTimeoutMs });
619
+ }
620
+ await startFromEcosystem(paths, { dryRun, logger });
582
621
  if (appName) {
583
622
  const proc = await waitPm2(
584
623
  appName,
@@ -833,7 +872,7 @@ function buildEnsureEnvScript() {
833
872
  return `/**
834
873
  * Written by cli-toolkit deploy (init-structure). Do not hand-edit.
835
874
  * Preloaded via pm2 node_args --require. Always set (do not only fill when unset):
836
- * \`pm2 startOrReload --update-env\` can inject a non-production ENV from the
875
+ * \`pm2 start \u2026 --update-env\` can inject a non-production ENV from the
837
876
  * deploy shell / prior dump, and a conditional assign would leave it in place.
838
877
  */
839
878
  process.env.ENV = "production";
@@ -1199,7 +1238,9 @@ async function rollbackService(service, options = {}) {
1199
1238
  logger.info(`rollback target: v${buildInfo.version} release=${buildInfo.release ?? rollbackTarget.name}`);
1200
1239
  }
1201
1240
  await activateRelease(rollbackTarget.path, paths, { dryRun, logger });
1202
- await reloadPm2(paths, { dryRun, logger });
1241
+ const appName = service.pm2?.appName ?? null;
1242
+ const waitTimeoutMs = 65e3;
1243
+ await reloadPm2(paths, { dryRun, logger, appName, waitTimeoutMs });
1203
1244
  const summary = `rollback ${activeName} \u2192 ${rollbackTarget.name} dryRun=${dryRun}`;
1204
1245
  if (!dryRun) await appendDeployLog(paths.deployLog, summary);
1205
1246
  return { from: activeName, to: rollbackTarget.name, path: rollbackTarget.path };