underpost 3.2.30 → 3.2.70

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/src/cli/run.js CHANGED
@@ -22,7 +22,7 @@ import { actionInitLog, loggerFactory } from '../server/logger.js';
22
22
 
23
23
  import fs from 'fs-extra';
24
24
  import net from 'net';
25
- import { range, setPad, timer } from '../client/components/core/CommonJs.js';
25
+ import { range, s4, setPad, timer } from '../client/components/core/CommonJs.js';
26
26
 
27
27
  import os from 'os';
28
28
  import Underpost from '../index.js';
@@ -52,6 +52,7 @@ const logger = loggerFactory(import.meta);
52
52
  /**
53
53
  * @constant DEFAULT_OPTION
54
54
  * @description Default options for the UnderpostRun class.
55
+ * @typedef {Object} UnderpostRunDefaultOptions
55
56
  * @type {Object}
56
57
  * @property {boolean} dev - Whether to run in development mode.
57
58
  * @property {string} podName - The name of the pod to run.
@@ -215,7 +216,7 @@ class UnderpostRun {
215
216
  * @method dev-cluster
216
217
  * @description Resets and deploys a full development cluster including MongoDB, Valkey, exposes services, and updates `/etc/hosts` for local access.
217
218
  * @param {string} path - The input value, identifier, or path for the operation.
218
- * @param {Object} options - The default underpost runner options for customizing workflow
219
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
219
220
  * @memberof UnderpostRun
220
221
  */
221
222
  'dev-cluster': (path, options = DEFAULT_OPTION) => {
@@ -297,7 +298,7 @@ class UnderpostRun {
297
298
  * @method metadata
298
299
  * @description Generates metadata for the specified path after exposing the development cluster.
299
300
  * @param {string} path - The input value, identifier, or path for the operation.
300
- * @param {Object} options - The default underpost runner options for customizing workflow
301
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
301
302
  * @memberof UnderpostRun
302
303
  */
303
304
  metadata: async (path, options = DEFAULT_OPTION) => {
@@ -322,7 +323,7 @@ class UnderpostRun {
322
323
  * @method svc-ls
323
324
  * @description Lists systemd services and installed packages, optionally filtering by the provided path.
324
325
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional filter for services and packages).
325
- * @param {Object} options - The default underpost runner options for customizing workflow
326
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
326
327
  * @memberof UnderpostRun
327
328
  */
328
329
  'svc-ls': (path, options = DEFAULT_OPTION) => {
@@ -342,7 +343,7 @@ class UnderpostRun {
342
343
  * @method svc-rm
343
344
  * @description Removes a systemd service by stopping it, disabling it, uninstalling the package, and deleting related files.
344
345
  * @param {string} path - The input value, identifier, or path for the operation (used as the service name).
345
- * @param {Object} options - The default underpost runner options for customizing workflow
346
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
346
347
  * @memberof UnderpostRun
347
348
  */
348
349
  'svc-rm': (path, options = DEFAULT_OPTION) => {
@@ -357,7 +358,7 @@ class UnderpostRun {
357
358
  * @method ssh-deploy-info
358
359
  * @description Retrieves deployment status and pod information from a remote server via SSH.
359
360
  * @param {string} path - The input value, identifier, or path for the operation.
360
- * @param {Object} options - The default underpost runner options for customizing workflow
361
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
361
362
  * @memberof UnderpostRun
362
363
  */
363
364
  'ssh-deploy-info': async (path = '', options = DEFAULT_OPTION) => {
@@ -401,7 +402,7 @@ class UnderpostRun {
401
402
  * skipped (move the owning controller). StatefulSets bound to node-local PVs may stay
402
403
  * Pending after a move until their volume is available on the target node.
403
404
  * @param {string} path - Resource selector (`kind/name`, `kind`, or empty).
404
- * @param {Object} options - The default underpost runner options for customizing workflow
405
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
405
406
  * @memberof UnderpostRun
406
407
  * @returns {Array<{ref:string,kind:string,status:string,node?:string}>} Per-resource outcome.
407
408
  */
@@ -601,7 +602,7 @@ class UnderpostRun {
601
602
  * @method dev-hosts-expose
602
603
  * @description Deploys a specified service in development mode with `/etc/hosts` modification for local access.
603
604
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
604
- * @param {Object} options - The default underpost runner options for customizing workflow
605
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
605
606
  * @memberof UnderpostRun
606
607
  */
607
608
  'dev-hosts-expose': (path, options = DEFAULT_OPTION) => {
@@ -614,7 +615,7 @@ class UnderpostRun {
614
615
  * @method dev-hosts-restore
615
616
  * @description Restores the `/etc/hosts` file to its original state after modifications made during development deployments.
616
617
  * @param {string} path - The input value, identifier, or path for the operation.
617
- * @param {Object} options - The default underpost runner options for customizing workflow
618
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
618
619
  * @memberof UnderpostRun
619
620
  */
620
621
  'dev-hosts-restore': (path, options = DEFAULT_OPTION) => {
@@ -625,7 +626,7 @@ class UnderpostRun {
625
626
  * @method cluster-build
626
627
  * @description Build configuration for cluster deployment.
627
628
  * @param {string} path - The input value, identifier, or path for the operation.
628
- * @param {Object} options - The default underpost runner options for customizing workflow
629
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
629
630
  * @memberof UnderpostRun
630
631
  */
631
632
  'cluster-build': (path, options = DEFAULT_OPTION) => {
@@ -649,7 +650,7 @@ class UnderpostRun {
649
650
  * and optionally triggers engine-<conf-id> CI with sync/init which in turn dispatches the CD workflow
650
651
  * after the build chain completes (template → ghpkg → engine-<conf-id> → CD).
651
652
  * @param {string} path - The deployment path identifier (e.g., 'sync-engine-core', 'init-engine-core', or empty for build-only).
652
- * @param {Object} options - The default underpost runner options for customizing workflow
653
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
653
654
  * @memberof UnderpostRun
654
655
  */
655
656
  'template-deploy': (path = '', options = DEFAULT_OPTION) => {
@@ -663,13 +664,10 @@ class UnderpostRun {
663
664
  shellExec(`${baseCommand} run pull`);
664
665
  shellExec(`${baseCommand} run shared-dir`);
665
666
 
666
- // Capture last N commit messages for propagation.
667
- // When --from-n-commit is not set, auto-detect unpushed commit count (same as --unpush flag).
668
- const fromN =
669
- options.fromNCommit && parseInt(options.fromNCommit) > 0
670
- ? parseInt(options.fromNCommit)
671
- : Underpost.repo.getUnpushedCount('.').count;
672
- const message = shellExec(`node bin cmt --changelog ${fromN} --changelog-no-hash`, {
667
+ // Capture the sanitized message from the last N commits (--from-n-commit, default 1) for
668
+ // propagation to pwa-microservices-template and every engine-* repo.
669
+ const fromN = parseInt(options.fromNCommit) > 0 ? parseInt(options.fromNCommit) : 1;
670
+ const sanitizedMessage = shellExec(`node bin cmt --changelog-msg --from-n-commit ${fromN} --changelog-no-hash`, {
673
671
  silent: true,
674
672
  stdout: true,
675
673
  }).trim();
@@ -681,8 +679,6 @@ class UnderpostRun {
681
679
  );
682
680
  shellCd('/home/dd/engine');
683
681
 
684
- const sanitizedMessage = Underpost.repo.sanitizeChangelogMessage(message);
685
-
686
682
  // Push engine repo so workflow YAML changes reach GitHub
687
683
  shellExec(`git reset`);
688
684
  shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
@@ -730,7 +726,7 @@ class UnderpostRun {
730
726
  * @method template-deploy-local
731
727
  * @description Similar to `template-deploy` but runs the workflow locally without dispatching GitHub Actions. It pulls the latest changes, pushes to GitHub, builds the template, and optionally triggers a local release with CI push.
732
728
  * @param {string} path - The deployment path identifier (e.g., 'sync-engine-core', 'init-engine-core', or empty for build-only).
733
- * @param {Object} options - The default underpost runner options for customizing workflow
729
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
734
730
  * @memberof UnderpostRun
735
731
  */
736
732
  'template-deploy-local': async (path, options = DEFAULT_OPTION) => {
@@ -744,17 +740,12 @@ class UnderpostRun {
744
740
  shellExec(`${baseCommand} run pull`);
745
741
  shellExec(`${baseCommand} run shared-dir`);
746
742
 
747
- // Capture last N commit messages from the engine repo.
748
- // When --from-n-commit is not set, auto-detect unpushed commit count (same as --unpush flag).
749
- const fromN =
750
- options.fromNCommit && parseInt(options.fromNCommit) > 0
751
- ? parseInt(options.fromNCommit)
752
- : Underpost.repo.getUnpushedCount('.').count;
753
- const rawMessage = shellExec(`node bin cmt --changelog ${fromN} --changelog-no-hash`, {
743
+ // Capture the sanitized message from the last N commits (--from-n-commit, default 1).
744
+ const fromN = parseInt(options.fromNCommit) > 0 ? parseInt(options.fromNCommit) : 1;
745
+ const sanitizedMessage = shellExec(`node bin cmt --changelog-msg --from-n-commit ${fromN} --changelog-no-hash`, {
754
746
  silent: true,
755
747
  stdout: true,
756
748
  }).trim();
757
- const sanitizedMessage = Underpost.repo.sanitizeChangelogMessage(rawMessage);
758
749
 
759
750
  const { triggerCmd } = path
760
751
  ? await Underpost.release.ci(path, sanitizedMessage, options)
@@ -766,15 +757,14 @@ class UnderpostRun {
766
757
  * @description Dispatches the Docker image CI workflow (`docker-image[.<runtime>].ci.yml`) via `workflow_dispatch`.
767
758
  * Repository resolution is delegated to `Underpost.repo.resolveInstanceRepo(path)`.
768
759
  * @param {string} path - Optional runtime / workflow suffix (e.g. `cyberia-server`, `cyberia-client`).
769
- * @param {Object} options - The default underpost runner options for customizing workflow
760
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
770
761
  * @memberof UnderpostRun
771
762
  */
772
763
  'docker-image': (path, options = DEFAULT_OPTION) => {
773
- const repo = Underpost.repo.resolveInstanceRepo(path);
764
+ const repo = Underpost.repo.resolveInstanceRepo(path, options.dev);
774
765
  Underpost.repo.dispatchWorkflow({
775
766
  repo,
776
- workflowFile: `docker-image${path ? `.${path}` : ''}.ci.yml`,
777
- ref: 'master',
767
+ workflowFile: `docker-image${path ? `.${path}` : ''}${options.dev ? '.dev' : ''}.ci.yml`,
778
768
  inputs: {},
779
769
  });
780
770
  },
@@ -782,7 +772,7 @@ class UnderpostRun {
782
772
  * @method clean
783
773
  * @description Changes directory to the provided path (defaulting to `/home/dd/engine`) and runs `node bin/deploy clean-core-repo`.
784
774
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional directory path).
785
- * @param {Object} options - The default underpost runner options for customizing workflow
775
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
786
776
  * @memberof UnderpostRun
787
777
  */
788
778
  clean: (path = '', options = DEFAULT_OPTION) => {
@@ -793,7 +783,7 @@ class UnderpostRun {
793
783
  * @method pull
794
784
  * @description Clones or pulls updates for the `engine` and `engine-private` repositories into `/home/dd/engine` and `/home/dd/engine/engine-private`.
795
785
  * @param {string} path - The input value, identifier, or path for the operation.
796
- * @param {Object} options - The default underpost runner options for customizing workflow
786
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
797
787
  * @memberof UnderpostRun
798
788
  */
799
789
  pull: (path, options = DEFAULT_OPTION) => {
@@ -820,7 +810,7 @@ class UnderpostRun {
820
810
  * @method release-deploy
821
811
  * @description Executes deployment (`underpost run deploy`) for all deployment IDs listed in `./engine-private/deploy/dd.router`.
822
812
  * @param {string} path - The input value, identifier, or path for the operation.
823
- * @param {Object} options - The default underpost runner options for customizing workflow
813
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
824
814
  * @memberof UnderpostRun
825
815
  */
826
816
  'release-deploy': (path, options = DEFAULT_OPTION) => {
@@ -836,7 +826,7 @@ class UnderpostRun {
836
826
  * @method ssh-deploy
837
827
  * @description Dispatches the corresponding CD workflow for SSH-based deployment, replacing empty commits with workflow_dispatch.
838
828
  * @param {string} path - The deployment identifier (e.g., 'engine-core', 'sync-engine-core', 'init-engine-core').
839
- * @param {Object} options - The default underpost runner options for customizing workflow
829
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
840
830
  * @memberof UnderpostRun
841
831
  */
842
832
  'ssh-deploy': (path, options = DEFAULT_OPTION) => {
@@ -851,9 +841,9 @@ class UnderpostRun {
851
841
  job = 'init';
852
842
  confId = path.replace(/^init-/, '');
853
843
  }
854
-
844
+ const repo = Underpost.repo.resolveInstanceRepo(confId, options.dev);
855
845
  Underpost.repo.dispatchWorkflow({
856
- repo: `${process.env.GITHUB_USERNAME}/engine`,
846
+ repo,
857
847
  workflowFile: `${confId}.cd.yml`,
858
848
  ref: 'master',
859
849
  inputs: { job },
@@ -864,7 +854,7 @@ class UnderpostRun {
864
854
  * @description Opens a Visual Studio Code (VS Code) session for the specified path using `node ${underpostRoot}/bin/zed ${path}`,
865
855
  * or installs Zed and sublime-text IDE if `path` is 'install'.
866
856
  * @param {string} path - The input value, identifier, or path for the operation (used as the path to the directory to open in the IDE).
867
- * @param {Object} options - The default underpost runner options for customizing workflow
857
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
868
858
  * @memberof UnderpostRun
869
859
  */
870
860
  ide: (path = '', options = DEFAULT_OPTION) => {
@@ -891,7 +881,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
891
881
  * @method crypto-policy
892
882
  * @description Sets the system's crypto policies to `DEFAULT:SHA1` using `update-crypto-policies` command.
893
883
  * @param {string} path - The input value, identifier, or path for the operation.
894
- * @param {Object} options - The default underpost runner options for customizing workflow
884
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
895
885
  * @memberof UnderpostRun
896
886
  */
897
887
  'crypto-policy': (path, options = DEFAULT_OPTION) => {
@@ -906,7 +896,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
906
896
  * `deployment.yaml`. Useful when you want to force `Always` so the kubelet re-pulls a mutable tag on every rollout. Example:
907
897
  * `node bin run sync dd-core --kubeadm --image-pull-policy Always`
908
898
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string containing deploy parameters).
909
- * @param {Object} options - The default underpost runner options for customizing workflow
899
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
910
900
  * @memberof UnderpostRun
911
901
  */
912
902
  sync: async (path, options = DEFAULT_OPTION) => {
@@ -1000,7 +990,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1000
990
  * @method stop
1001
991
  * @description Stops a deployment by deleting the corresponding Kubernetes deployment and service resources.
1002
992
  * @param {string} path - The input value, identifier, or path for the operation (used to determine which traffic to stop).
1003
- * @param {Object} options - The default underpost runner options for customizing workflow
993
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1004
994
  * @memberof UnderpostRun
1005
995
  */
1006
996
  stop: async (path = '', options = DEFAULT_OPTION) => {
@@ -1024,7 +1014,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1024
1014
  * @method ssh-deploy-stop
1025
1015
  * @description Stops a remote deployment via SSH by executing the appropriate Underpost command on the remote server.
1026
1016
  * @param {string} path - The input value, identifier, or path for the operation (used to determine which traffic to stop).
1027
- * @param {Object} options - The default underpost runner options for customizing workflow
1017
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1028
1018
  * @memberof UnderpostRun
1029
1019
  */
1030
1020
  'ssh-deploy-stop': async (path, options = DEFAULT_OPTION) => {
@@ -1051,7 +1041,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1051
1041
  * @method ssh-deploy-db-rollback
1052
1042
  * @description Performs a database rollback on remote deployment via SSH.
1053
1043
  * @param {string} path - Comma-separated deployId and optional number of commits to reset (format: "deployId,nCommits")
1054
- * @param {Object} options - The default underpost runner options for customizing workflow
1044
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1055
1045
  * @param {string} options.deployId - The deployment identifier
1056
1046
  * @param {string} options.user - The SSH user for credential lookup
1057
1047
  * @param {boolean} options.dev - Development mode flag
@@ -1078,7 +1068,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1078
1068
  * @method ssh-deploy-db
1079
1069
  * @description Imports/restores a database on remote deployment via SSH.
1080
1070
  * @param {string} path - The deployment ID for database import
1081
- * @param {Object} options - The default underpost runner options for customizing workflow
1071
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1082
1072
  * @param {string} options.deployId - The deployment identifier
1083
1073
  * @param {string} options.user - The SSH user for credential lookup
1084
1074
  * @param {boolean} options.dev - Development mode flag
@@ -1103,7 +1093,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1103
1093
  * @method ssh-deploy-db-status
1104
1094
  * @description Retrieves database status/stats for a deployment (or all deployments from dd.router) via SSH.
1105
1095
  * @param {string} path - Comma-separated deployId(s) or 'dd' to use the dd.router list.
1106
- * @param {Object} options - Runner options (uses options.deployId for SSH host lookup).
1096
+ * @param {UnderpostRunDefaultOptions} options - Runner options (uses options.deployId for SSH host lookup).
1107
1097
  * @param {string} options.deployId - Deployment identifier used for SSH config lookup.
1108
1098
  * @param {string} options.user - SSH user for credential lookup.
1109
1099
  * @param {boolean} options.dev - Development mode flag.
@@ -1149,7 +1139,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1149
1139
  * @method tz
1150
1140
  * @description Sets the system timezone using `timedatectl set-timezone` command.
1151
1141
  * @param {string} path - The input value, identifier, or path for the operation (used as the timezone string).
1152
- * @param {Object} options - The default underpost runner options for customizing workflow
1142
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1153
1143
  * @memberof UnderpostRun
1154
1144
  */
1155
1145
  tz: (path, options = DEFAULT_OPTION) => {
@@ -1170,7 +1160,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1170
1160
  * @method get-proxy
1171
1161
  * @description Retrieves and logs the HTTPProxy resources in the specified namespace using `kubectl get HTTPProxy`.
1172
1162
  * @param {string} path - The input value, identifier, or path for the operation (used as an optional filter for the HTTPProxy resources).
1173
- * @param {Object} options - The default underpost runner options for customizing workflow
1163
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1174
1164
  * @memberof UnderpostRun
1175
1165
  */
1176
1166
  'get-proxy': async (path = '', options = DEFAULT_OPTION) => {
@@ -1277,7 +1267,7 @@ EOF
1277
1267
  /**
1278
1268
  * @method instance
1279
1269
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string containing workflow parameters).
1280
- * @param {Object} options - The default underpost runner options for customizing workflow
1270
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1281
1271
  * @memberof UnderpostRun
1282
1272
  */
1283
1273
  instance: async (path = '', options = DEFAULT_OPTION) => {
@@ -1449,12 +1439,39 @@ EOF
1449
1439
  }
1450
1440
  },
1451
1441
 
1442
+ /**
1443
+ * @method deploy-key
1444
+ * @description Copies the deploy key for a specific user and deployId to a temporary location on the local machine.
1445
+ * @param {string} path - The input value, identifier, or path for the operation (not used in this method).
1446
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1447
+ * @param {string} options.user - The user for which to copy the deploy key.
1448
+ * @param {string} options.deployId - The deployment identifier associated with the deploy key.
1449
+ * @memberof UnderpostRun
1450
+ */
1451
+ 'deploy-key': (path, options = DEFAULT_OPTION) => {
1452
+ const prefix = 'dd-key';
1453
+ if (options.reset) {
1454
+ shellExec(`rm -rf /home/dd/tmp/${prefix}_*`);
1455
+ return;
1456
+ }
1457
+ if (!options.user || !options.deployId) {
1458
+ logger.error('Both --user and --deploy-id options are required to copy the deploy key.');
1459
+ return;
1460
+ }
1461
+ const targetPath = `/home/dd/tmp/${prefix}_${s4()}${s4()}`;
1462
+ fs.mkdirSync('/home/dd/tmp', { recursive: true });
1463
+ fs.copyFileSync(`./engine-private/conf/${options.deployId}/users/${options.user}/id_rsa`, targetPath);
1464
+ logger.info(`Copied deploy key to ${targetPath}`);
1465
+ if (options.copy) pbcopy(targetPath);
1466
+ },
1467
+
1452
1468
  /**
1453
1469
  * @method instance-build-manifest
1454
1470
  * @description Builds a Kubernetes Deployment + Service manifest for a specific instance entry
1455
- * from `conf.instances.json` and writes it to a file.
1456
- * Traffic colour is automatically chosen as the opposite of the current live colour (blue/green),
1457
- * defaulting to `blue` when no deployment is running yet.
1471
+ * from `conf.instances.json` and writes it to a file. This is a purely local
1472
+ * artifact generator: it never probes a live cluster. Traffic colour defaults
1473
+ * to the canonical initial `blue` and can be overridden with `--traffic`; the
1474
+ * real blue/green swap is resolved at deploy time (`deploy --sync`).
1458
1475
  *
1459
1476
  * If `--build` is supplied the image is built from the project Dockerfile and loaded into the
1460
1477
  * cluster before the manifest is written (kind by default; `--kubeadm` / `--k3s` override).
@@ -1465,7 +1482,7 @@ EOF
1465
1482
  * `<projectPath>/manifests/<env>/deployment.yaml`.
1466
1483
  * In production, files are also copied to `<projectPath>/Dockerfile` and
1467
1484
  * `<projectPath>/deployment.yaml`.
1468
- * @param {Object} options - The default underpost runner options for customizing workflow
1485
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1469
1486
  * @memberof UnderpostRun
1470
1487
  */
1471
1488
  'instance-build-manifest': (path, options = DEFAULT_OPTION) => {
@@ -1544,7 +1561,7 @@ EOF
1544
1561
  path: projectPath,
1545
1562
  imageName: _image,
1546
1563
  podmanSave: true,
1547
- imagePath: projectPath,
1564
+ imageOutPath: projectPath,
1548
1565
  kind: isKind,
1549
1566
  kubeadm: !!options.kubeadm,
1550
1567
  k3s: !!options.k3s,
@@ -1557,15 +1574,8 @@ EOF
1557
1574
  });
1558
1575
  }
1559
1576
 
1560
- // Determine target traffic: opposite of current, or 'blue' if nothing is running yet.
1561
- const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
1562
- hostTest: _host,
1563
- namespace: options.namespace,
1564
- });
1565
- const targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'blue';
1566
-
1567
- // Resolve {{grpc-service-dns}} using the parent deploy's current (or default) traffic.
1568
- const parentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace }) || 'blue';
1577
+ const targetTraffic = options.traffic || 'blue';
1578
+ const parentTraffic = targetTraffic;
1569
1579
  const resolvedCmd = _cmd[env].map((c) =>
1570
1580
  c.replaceAll(
1571
1581
  '{{grpc-service-dns}}',
@@ -1613,11 +1623,86 @@ EOF
1613
1623
  image: _image,
1614
1624
  });
1615
1625
 
1626
+ // --- Sibling manifests (pv-pvc, proxy, grpc-service) ------------------
1627
+ // Emit the same apply-able set the parent deploy writes to build/<env>,
1628
+ // scoped to this instance so the project repo and engine-private ship
1629
+ // more than just deployment.yaml. Content matches what `run instance`
1630
+ // creates dynamically at deploy time (deployVolume / instance-promote /
1631
+ // the parent gRPC ClusterIP), so a static `kubectl apply` is equivalent.
1632
+ const pvDataNode = Underpost.deploy.resolveDeployNode({
1633
+ node: options.nodeName,
1634
+ kind: options.kind,
1635
+ kubeadm: options.kubeadm,
1636
+ k3s: options.k3s,
1637
+ env,
1638
+ });
1639
+
1640
+ // pv-pvc.yaml — one PV+PVC per instance volume; names mirror deployVolume.
1641
+ let pvPvcYaml = '';
1642
+ for (const volume of _volumes || []) {
1643
+ if (!volume.claimName) continue;
1644
+ const pvcId = `${volume.claimName}-${_deployId}-${env}-${targetTraffic}`;
1645
+ const pvId = `${volume.claimName.replace('pvc-', 'pv-')}-${_deployId}-${env}-${targetTraffic}`;
1646
+ pvPvcYaml += `---\n${Underpost.deploy.persistentVolumeFactory({
1647
+ pvcId,
1648
+ namespace: options.namespace,
1649
+ hostPath: `/home/dd/engine/volume/${pvId}`,
1650
+ nodeName: pvDataNode,
1651
+ })}\n`;
1652
+ }
1653
+
1654
+ // proxy.yaml — HTTPProxy for the instance host (mirrors instance-promote).
1655
+ const proxyYaml =
1656
+ Underpost.deploy.baseProxyYamlFactory({ host: _host, env, options }) +
1657
+ Underpost.deploy.deploymentYamlServiceFactory({
1658
+ path: _path,
1659
+ port: _fromPort,
1660
+ deployId: _deployId,
1661
+ env,
1662
+ deploymentVersions: [targetTraffic],
1663
+ });
1664
+
1665
+ // grpc-service.yaml — the parent deploy's gRPC ClusterIP (shared; the
1666
+ // instance cmd resolves {{grpc-service-dns}} to it). Reuse the parent's
1667
+ // generated manifest when present rather than regenerating it here.
1668
+ const parentGrpcServicePath = `./engine-private/conf/${deployId}/build/${env}/grpc-service.yaml`;
1669
+ const grpcServiceYaml = fs.existsSync(parentGrpcServicePath)
1670
+ ? fs.readFileSync(parentGrpcServicePath, 'utf8')
1671
+ : '';
1672
+
1673
+ // Write the sibling set next to deployment.yaml (project) and into the
1674
+ // engine-private per-instance build dir (mirrors instances/<id>/ layout).
1675
+ const instanceBuildDir = `./engine-private/conf/${deployId}/instances/${_id}/build/${env}`;
1676
+ fs.mkdirpSync(instanceBuildDir);
1677
+ fs.writeFileSync(`${instanceBuildDir}/deployment.yaml`, deploymentYaml, 'utf8');
1678
+ const siblingManifests = {
1679
+ 'pv-pvc.yaml': pvPvcYaml,
1680
+ 'proxy.yaml': proxyYaml,
1681
+ 'grpc-service.yaml': grpcServiceYaml,
1682
+ };
1683
+ for (const [name, content] of Object.entries(siblingManifests)) {
1684
+ if (!content) continue;
1685
+ fs.writeFileSync(`${envManifestPath}/${name}`, content, 'utf8');
1686
+ fs.writeFileSync(`${instanceBuildDir}/${name}`, content, 'utf8');
1687
+ }
1688
+ logger.info('[instance-build-manifest] Sibling manifests written', {
1689
+ project: envManifestPath,
1690
+ enginePrivate: instanceBuildDir,
1691
+ pvPvc: !!pvPvcYaml,
1692
+ proxy: !!proxyYaml,
1693
+ grpcService: !!grpcServiceYaml,
1694
+ });
1695
+
1616
1696
  if (env === 'production') {
1617
1697
  if (fs.existsSync(dockerfileManifestPath)) {
1618
1698
  fs.copyFileSync(dockerfileManifestPath, `${rootPath}/Dockerfile`);
1619
1699
  }
1620
1700
  fs.copyFileSync(outputPath, `${rootPath}/deployment.yaml`);
1701
+ // Sibling manifests alongside deployment.yaml at the project root.
1702
+ for (const name of ['pv-pvc.yaml', 'proxy.yaml', 'grpc-service.yaml']) {
1703
+ const src = `${envManifestPath}/${name}`;
1704
+ if (fs.existsSync(src)) fs.copyFileSync(src, `${rootPath}/${name}`);
1705
+ }
1621
1706
  logger.info('[instance-build-manifest] Production artifacts copied to project root', {
1622
1707
  rootPath,
1623
1708
  dockerfile: `${rootPath}/Dockerfile`,
@@ -1629,6 +1714,25 @@ EOF
1629
1714
  fs.copyFileSync(ciSrc, `${rootPath}/.github/workflows/docker-image.${_runtime}.ci.yml`);
1630
1715
  logger.info(`[instance-build-manifest] CI workflow copied`, { src: ciSrc });
1631
1716
  }
1717
+
1718
+ // Ship the development variant alongside production so the instance repo
1719
+ // is self-contained: the dev Dockerfile (built by the -dev CI workflow
1720
+ // into underpost/<runtime>-dev, consumed by the development compose
1721
+ // stack) and its dispatchable workflow. Both are optional — synced only
1722
+ // when the source-of-truth files exist in the engine repo.
1723
+ if (_runtime) {
1724
+ const devDockerfileSrc = `src/runtime/${_runtime}/Dockerfile.dev`;
1725
+ if (fs.existsSync(devDockerfileSrc)) {
1726
+ fs.copyFileSync(devDockerfileSrc, `${rootPath}/Dockerfile.dev`);
1727
+ logger.info('[instance-build-manifest] Dev Dockerfile copied', { src: devDockerfileSrc });
1728
+ }
1729
+ const devCiSrc = `./.github/workflows/docker-image.${_runtime}.dev.ci.yml`;
1730
+ if (fs.existsSync(devCiSrc)) {
1731
+ if (!fs.existsSync(`${rootPath}/.github/workflows`)) fs.mkdirpSync(`${rootPath}/.github/workflows`);
1732
+ fs.copyFileSync(devCiSrc, `${rootPath}/.github/workflows/docker-image.${_runtime}.dev.ci.yml`);
1733
+ logger.info(`[instance-build-manifest] Dev CI workflow copied`, { src: devCiSrc });
1734
+ }
1735
+ }
1632
1736
  }
1633
1737
  },
1634
1738
 
@@ -1636,7 +1740,7 @@ EOF
1636
1740
  * @method ls-deployments
1637
1741
  * @description Retrieves and logs a table of Kubernetes deployments using `Underpost.deploy.get`.
1638
1742
  * @param {string} path - The input value, identifier, or path for the operation (used as an optional deployment name filter).
1639
- * @param {Object} options - The default underpost runner options for customizing workflow
1743
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1640
1744
  * @memberof UnderpostRun
1641
1745
  */
1642
1746
  'ls-deployments': async (path, options = DEFAULT_OPTION) => {
@@ -1647,7 +1751,7 @@ EOF
1647
1751
  * @method host-update
1648
1752
  * @description Executes the `rocky-setup.sh` script to update the host system configuration.
1649
1753
  * @param {string} path - The input value, identifier, or path for the operation.
1650
- * @param {Object} options - The default underpost runner options for customizing workflow
1754
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1651
1755
  * @memberof UnderpostRun
1652
1756
  */
1653
1757
  'host-update': async (path, options = DEFAULT_OPTION) => {
@@ -1663,7 +1767,7 @@ EOF
1663
1767
  * the systemd cgroup driver, enables the `crio` service, and writes `/etc/crictl.yaml`
1664
1768
  * so that `crictl` targets the CRI-O socket by default.
1665
1769
  * @param {string} path - Unused.
1666
- * @param {Object} options - The default underpost runner options for customizing workflow.
1770
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
1667
1771
  * @memberof UnderpostRun
1668
1772
  */
1669
1773
  'install-crio': (path, options = DEFAULT_OPTION) => {
@@ -1714,7 +1818,7 @@ EOF`);
1714
1818
  * @method dd-container
1715
1819
  * @description Deploys a development or debug container tasks jobs, setting up necessary volumes and images, and running specified commands within the container.
1716
1820
  * @param {string} path - The input value, identifier, or path for the operation (used as the command to run inside the container).
1717
- * @param {Object} options - The default underpost runner options for customizing workflow
1821
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1718
1822
  * @memberof UnderpostRun
1719
1823
  */
1720
1824
  'dd-container': async (path = '', options = DEFAULT_OPTION) => {
@@ -1741,7 +1845,11 @@ EOF`);
1741
1845
  }
1742
1846
 
1743
1847
  if (!currentImage)
1744
- shellExec(`${baseCommand} image${baseClusterCommand} --pull-base ${options.dev ? '--kind' : '--kubeadm'}`);
1848
+ shellExec(
1849
+ `${baseCommand} image${baseClusterCommand} --pull-base --build --path ${
1850
+ options.dev ? '.' : options.underpostRoot
1851
+ } ${options.dev ? '--kind' : '--kubeadm'}`,
1852
+ );
1745
1853
  // shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
1746
1854
 
1747
1855
  const payload = {
@@ -1769,7 +1877,7 @@ EOF`);
1769
1877
  * @method ip-info
1770
1878
  * @description Executes the `ip-info.sh` script to display IP-related information for the specified path.
1771
1879
  * @param {string} path - The input value, identifier, or path for the operation (used as an argument to the script).
1772
- * @param {Object} options - The default underpost runner options for customizing workflow
1880
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1773
1881
  * @memberof UnderpostRun
1774
1882
  */
1775
1883
  'ip-info': (path, options = DEFAULT_OPTION) => {
@@ -1782,7 +1890,7 @@ EOF`);
1782
1890
  * @method db-client
1783
1891
  * @description Deploys and exposes the Adminer database client application (using `adminer:4.7.6-standalone` image) on the cluster.
1784
1892
  * @param {string} path - The input value, identifier, or path for the operation.
1785
- * @param {Object} options - The default underpost runner options for customizing workflow
1893
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1786
1894
  * @memberof UnderpostRun
1787
1895
  */
1788
1896
  'db-client': async (path, options = DEFAULT_OPTION) => {
@@ -1809,7 +1917,7 @@ EOF`);
1809
1917
  * @method git-conf
1810
1918
  * @description Configures Git global and local user name and email settings based on the provided `path` (formatted as `username,email`), or defaults to environment variables.
1811
1919
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `username,email`).
1812
- * @param {Object} options - The default underpost runner options for customizing workflow
1920
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1813
1921
  * @memberof UnderpostRun
1814
1922
  */
1815
1923
  'git-conf': (path = '', options = DEFAULT_OPTION) => {
@@ -1857,7 +1965,7 @@ EOF`);
1857
1965
  * TLS config, deletes stale Certificate resources, then reapplies the proxy and secret.yaml
1858
1966
  * (cert-manager Certificate resources) for each affected deployment.
1859
1967
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `deployId,env,replicas`).
1860
- * @param {Object} options - The default underpost runner options for customizing workflow
1968
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1861
1969
  * @memberof UnderpostRun
1862
1970
  */
1863
1971
  promote: async (path, options = DEFAULT_OPTION) => {
@@ -1911,10 +2019,31 @@ EOF`);
1911
2019
  * @method metrics
1912
2020
  * @description Deploys Prometheus and Grafana for metrics monitoring, targeting the hosts defined in the deployment configuration files.
1913
2021
  * @param {string} path - The input value, identifier, or path for the operation.
1914
- * @param {Object} options - The default underpost runner options for customizing workflow
2022
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1915
2023
  * @memberof UnderpostRun
1916
2024
  */
1917
2025
  metrics: async (path, options = DEFAULT_OPTION) => {
2026
+ if (path === 'server') {
2027
+ shellExec(
2028
+ `kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml`,
2029
+ );
2030
+ await timer(2000);
2031
+
2032
+ shellExec(`kubectl patch deployment metrics-server -n kube-system \
2033
+ --type='json' \
2034
+ -p='[
2035
+ {
2036
+ "op":"add",
2037
+ "path":"/spec/template/spec/containers/0/args/-",
2038
+ "value":"--kubelet-insecure-tls"
2039
+ }
2040
+ ]'`);
2041
+ shellExec(`kubectl scale deployment metrics-server \
2042
+ -n kube-system \
2043
+ --replicas=1`);
2044
+
2045
+ return;
2046
+ }
1918
2047
  const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
1919
2048
  let hosts = [];
1920
2049
  for (const deployId of deployList) {
@@ -1928,7 +2057,7 @@ EOF`);
1928
2057
  * @method cluster
1929
2058
  * @description Deploys a full production/development ready Kubernetes cluster environment including MongoDB, MariaDB, Valkey, Contour (Ingress), and Cert-Manager, and deploys all services.
1930
2059
  * @param {string} path - The input value, identifier, or path for the operation.
1931
- * @param {Object} options - The default underpost runner options for customizing workflow
2060
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1932
2061
  * @memberof UnderpostRun
1933
2062
  */
1934
2063
  cluster: async (path = '', options = DEFAULT_OPTION) => {
@@ -1990,7 +2119,7 @@ EOF`);
1990
2119
  * @method deploy
1991
2120
  * @description Deploys a specified service (identified by `path`) using blue/green strategy, monitors its status, and switches traffic upon readiness.
1992
2121
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
1993
- * @param {Object} options - The default underpost runner options for customizing workflow
2122
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1994
2123
  * @memberof UnderpostRun
1995
2124
  */
1996
2125
  deploy: async (path, options = DEFAULT_OPTION) => {
@@ -2015,7 +2144,7 @@ EOF`);
2015
2144
  * @method disk-clean
2016
2145
  * @description Executes the `disk-clean-sh` script to perform disk cleanup operations.
2017
2146
  * @param {string} path - The input value, identifier, or path for the operation.
2018
- * @param {Object} options - The default underpost runner options for customizing workflow
2147
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2019
2148
  * @memberof UnderpostRun
2020
2149
  */
2021
2150
  'disk-clean': async (path, options = DEFAULT_OPTION) => {
@@ -2028,7 +2157,7 @@ EOF`);
2028
2157
  * @method disk-devices
2029
2158
  * @description Executes the `disk-devices.sh` script to display information about disk devices.
2030
2159
  * @param {string} path - The input value, identifier, or path for the operation.
2031
- * @param {Object} options - The default underpost runner options for customizing workflow
2160
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2032
2161
  * @memberof UnderpostRun
2033
2162
  */
2034
2163
  'disk-devices': async (path = '/', options = DEFAULT_OPTION) => {
@@ -2041,7 +2170,7 @@ EOF`);
2041
2170
  * @method disk-usage
2042
2171
  * @description Displays disk usage statistics using the `du` command, sorted by size.
2043
2172
  * @param {string} path - The input value, identifier, or path for the operation.
2044
- * @param {Object} options - The default underpost runner options for customizing workflow
2173
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2045
2174
  * @memberof UnderpostRun
2046
2175
  */
2047
2176
  'disk-usage': async (path = '/', options = DEFAULT_OPTION) => {
@@ -2056,7 +2185,7 @@ EOF`);
2056
2185
  * @method dev
2057
2186
  * @description Starts development servers for client, API, and proxy based on provided parameters (deployId, host, path, clientHostPort).
2058
2187
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,subConf,host,path,clientHostPort`).
2059
- * @param {Object} options - The default underpost runner options for customizing workflow
2188
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2060
2189
  * @memberof UnderpostRun
2061
2190
  */
2062
2191
  dev: async (path = '', options = DEFAULT_OPTION) => {
@@ -2116,7 +2245,7 @@ EOF`);
2116
2245
  * @method service
2117
2246
  * @description Deploys and exposes specific services (like `mongo-express-service`) on the cluster, updating deployment configurations and monitoring status.
2118
2247
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,serviceId,host,path,replicas,image,node`).
2119
- * @param {Object} options - The default underpost runner options for customizing workflow
2248
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2120
2249
  * @memberof UnderpostRun
2121
2250
  */
2122
2251
  service: async (path = '', options = DEFAULT_OPTION) => {
@@ -2212,7 +2341,7 @@ EOF`);
2212
2341
  * @method etc-hosts
2213
2342
  * @description Generates and logs the contents for the `/etc/hosts` file based on provided hosts or deployment configurations.
2214
2343
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated list of hosts).
2215
- * @param {Object} options - The default underpost runner options for customizing workflow
2344
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2216
2345
  * @memberof UnderpostRun
2217
2346
  */
2218
2347
  'etc-hosts': async (path = '', options = DEFAULT_OPTION) => {
@@ -2229,7 +2358,7 @@ EOF`);
2229
2358
  * @method sh
2230
2359
  * @description Enables remote control for the Kitty terminal emulator.
2231
2360
  * @param {string} path - The input value, identifier, or path for the operation.
2232
- * @param {Object} options - The default underpost runner options for customizing workflow
2361
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2233
2362
  * @memberof UnderpostRun
2234
2363
  */
2235
2364
  sh: async (path = '', options = DEFAULT_OPTION) => {
@@ -2249,7 +2378,7 @@ EOF`);
2249
2378
  * @method log
2250
2379
  * @description Searches and highlights keywords in a specified log file, optionally showing surrounding lines.
2251
2380
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `filePath,keywords,lines`).
2252
- * @param {Object} options - The default underpost runner options for customizing workflow
2381
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2253
2382
  * @memberof UnderpostRun
2254
2383
  */
2255
2384
  log: async (path, options = DEFAULT_OPTION) => {
@@ -2266,7 +2395,7 @@ EOF`);
2266
2395
  * @method ps
2267
2396
  * @description Displays running processes that match a specified path or keyword.
2268
2397
  * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter processes).
2269
- * @param {Object} options - The default underpost runner options for customizing workflow
2398
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2270
2399
  * @memberof UnderpostRun
2271
2400
  */
2272
2401
  ps: async (path = '', options = DEFAULT_OPTION) => {
@@ -2291,7 +2420,7 @@ EOF`);
2291
2420
  * @method pid-info
2292
2421
  * @description Displays detailed information about a process by PID, including service details, command line, executable path, working directory, environment variables, and parent process tree.
2293
2422
  * @param {string} path - The PID of the process to inspect.
2294
- * @param {Object} options - The default underpost runner options for customizing workflow
2423
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2295
2424
  * @memberof UnderpostRun
2296
2425
  */
2297
2426
  'pid-info': (path, options = DEFAULT_OPTION) => {
@@ -2331,7 +2460,7 @@ EOF`);
2331
2460
  * @method background
2332
2461
  * @description Runs a custom command in the background using nohup, logging output to `/var/log/<id>.log` and saving the PID to `/var/run/<id>.pid`.
2333
2462
  * @param {string} path - The command to run in the background (e.g. 'npm run prod:container dd-cyberia-r3').
2334
- * @param {Object} options - The default underpost runner options for customizing workflow
2463
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2335
2464
  * @memberof UnderpostRun
2336
2465
  */
2337
2466
  background: (path, options = DEFAULT_OPTION) => {
@@ -2351,7 +2480,7 @@ EOF`);
2351
2480
  * @method ports
2352
2481
  * @description Set on ~/.bashrc alias: ports <port> Command to list listening ports that match the given keyword.
2353
2482
  * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter listening ports).
2354
- * @param {Object} options - The default underpost runner options for customizing workflow
2483
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2355
2484
  * @memberof UnderpostRun
2356
2485
  */
2357
2486
  ports: async (path = '', options = DEFAULT_OPTION) => {
@@ -2363,7 +2492,7 @@ EOF`);
2363
2492
  * @method deploy-test
2364
2493
  * @description Deploys a test deployment (`dd-test`) in either development or production mode, setting up necessary secrets and starting the deployment.
2365
2494
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID).
2366
- * @param {Object} options - The default underpost runner options for customizing workflow
2495
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2367
2496
  * @memberof UnderpostRun
2368
2497
  */
2369
2498
  'deploy-test': async (path, options = DEFAULT_OPTION) => {
@@ -2388,7 +2517,7 @@ EOF`);
2388
2517
  * @method tf-vae-test
2389
2518
  * @description Creates and runs a job pod (`tf-vae-test`) that installs TensorFlow dependencies, clones the TensorFlow docs, and runs the CVAE tutorial script, with a terminal monitor attached.
2390
2519
  * @param {string} path - The input value, identifier, or path for the operation.
2391
- * @param {Object} options - The default underpost runner options for customizing workflow
2520
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2392
2521
  * @memberof UnderpostRun
2393
2522
  */
2394
2523
  'tf-vae-test': async (path, options = DEFAULT_OPTION) => {
@@ -2488,7 +2617,7 @@ EOF`);
2488
2617
  * @method spark-template
2489
2618
  * @description Creates a new Spark template project using `sbt new` in `/home/dd/spark-template`, initializes a Git repository, and runs `replace_params.sh` and `build.sh`.
2490
2619
  * @param {string} path - The input value, identifier, or path for the operation.
2491
- * @param {Object} options - The default underpost runner options for customizing workflow
2620
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2492
2621
  * @memberof UnderpostRun
2493
2622
  */
2494
2623
  'spark-template': (path, options = DEFAULT_OPTION) => {
@@ -2516,7 +2645,7 @@ EOF`);
2516
2645
  * @method pull-rocky-image
2517
2646
  * @description Pulls the base `rockylinux:9` image from Docker Hub via Podman.
2518
2647
  * @param {string} path - The input value, identifier, or path for the operation.
2519
- * @param {Object} options - The default underpost runner options for customizing workflow
2648
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2520
2649
  * @memberof UnderpostRun
2521
2650
  */
2522
2651
  'pull-rocky-image': (path, options = DEFAULT_OPTION) => {
@@ -2526,7 +2655,7 @@ EOF`);
2526
2655
  * @method rmi
2527
2656
  * @description Forces the removal of all local Podman images (`podman rmi $(podman images -qa) --force`).
2528
2657
  * @param {string} path - The input value, identifier, or path for the operation.
2529
- * @param {Object} options - The default underpost runner options for customizing workflow
2658
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2530
2659
  * @memberof UnderpostRun
2531
2660
  */
2532
2661
  rmi: (path, options = DEFAULT_OPTION) => {
@@ -2536,7 +2665,7 @@ EOF`);
2536
2665
  * @method kill
2537
2666
  * @description Kills processes listening on the specified port(s). If the `path` contains a `+`, it treats it as a range of ports to kill.
2538
2667
  * @param {string} path - The input value, identifier, or path for the operation (used as the port number).
2539
- * @param {Object} options - The default underpost runner options for customizing workflow
2668
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2540
2669
  * @memberof UnderpostRun
2541
2670
  */
2542
2671
  kill: (path = '', options = DEFAULT_OPTION) => {
@@ -2568,7 +2697,7 @@ EOF`);
2568
2697
  * constraints (lowercase, uppercase, digit, special char, min 8 chars). Logs the plain password
2569
2698
  * to the console or, when `--copy` is set, copies it to the clipboard via pbcopy.
2570
2699
  * @param {string} path - Optional password length (default: 16).
2571
- * @param {Object} options - The default underpost runner options for customizing workflow.
2700
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2572
2701
  * @param {boolean} options.copy - When true, copies to clipboard instead of logging.
2573
2702
  * @memberof UnderpostRun
2574
2703
  */
@@ -2602,7 +2731,7 @@ EOF`);
2602
2731
  * @method secret
2603
2732
  * @description Creates an Underpost secret named 'underpost' from a file, defaulting to `/home/dd/engine/engine-private/conf/dd-cron/.env.production` if no path is provided.
2604
2733
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional path to the secret file).
2605
- * @param {Object} options - The default underpost runner options for customizing workflow
2734
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2606
2735
  * @memberof UnderpostRun
2607
2736
  */
2608
2737
  secret: (path, options = DEFAULT_OPTION) => {
@@ -2615,7 +2744,7 @@ EOF`);
2615
2744
  * @method underpost-config
2616
2745
  * @description Calls `Underpost.deploy.configMap` to create a Kubernetes ConfigMap, defaulting to the 'production' environment.
2617
2746
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional configuration name/environment).
2618
- * @param {Object} options - The default underpost runner options for customizing workflow
2747
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2619
2748
  * @memberof UnderpostRun
2620
2749
  */
2621
2750
  'underpost-config': (path = '', options = DEFAULT_OPTION) => {
@@ -2625,7 +2754,7 @@ EOF`);
2625
2754
  * @method gpu-env
2626
2755
  * @description Sets up a dedicated GPU development environment cluster, resetting and then setting up the cluster with `--dedicated-gpu` and monitoring the pods.
2627
2756
  * @param {string} path - The input value, identifier, or path for the operation.
2628
- * @param {Object} options - The default underpost runner options for customizing workflow
2757
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2629
2758
  * @memberof UnderpostRun
2630
2759
  */
2631
2760
  'gpu-env': (path, options = DEFAULT_OPTION) => {
@@ -2638,7 +2767,7 @@ EOF`);
2638
2767
  * @method tf-gpu-test
2639
2768
  * @description Deletes existing `tf-gpu-test-script` ConfigMap and `tf-gpu-test-pod`, and applies the test manifest from `manifests/deployment/tensorflow/tf-gpu-test.yaml`.
2640
2769
  * @param {string} path - The input value, identifier, or path for the operation.
2641
- * @param {Object} options - The default underpost runner options for customizing workflow
2770
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2642
2771
  * @memberof UnderpostRun
2643
2772
  */
2644
2773
  'tf-gpu-test': (path, options = DEFAULT_OPTION) => {
@@ -2652,7 +2781,7 @@ EOF`);
2652
2781
  * @method deploy-job
2653
2782
  * @description Creates and applies a custom Kubernetes Pod manifest (Job) for running arbitrary commands inside a container image (defaulting to a TensorFlow/NVIDIA image).
2654
2783
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional script path or job argument).
2655
- * @param {Object} options - The default underpost runner options for customizing workflow
2784
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2656
2785
  * @memberof UnderpostRun
2657
2786
  */
2658
2787
  'deploy-job': async (path, options = DEFAULT_OPTION) => {
@@ -2787,7 +2916,7 @@ EOF`;
2787
2916
  * Only files matching `<host>-<route>.zip.part*` or `<host>-<route>.zip` for each non-skipped route are uploaded.
2788
2917
  * @param {string} path - Optional `fsPath.splitOption` string.
2789
2918
  * Examples: `build` (default split 8), `build.16` (split 16 MB), `build.none-split` (no split flag).
2790
- * @param {Object} options - The default underpost runner options for customizing workflow.
2919
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2791
2920
  * @param {string} [options.deployId] - Override deploy ID.
2792
2921
  * @param {boolean} [options.dev] - Use development environment; defaults to production.
2793
2922
  * @memberof UnderpostRun
@@ -2875,7 +3004,7 @@ EOF`;
2875
3004
  * so that multi-path deployments are handled correctly.
2876
3005
  * @param {string} path - Optional comma-separated host name(s) to restrict processing (e.g. 'underpost.net' or 'a.com,b.com').
2877
3006
  * If omitted, all hosts from `engine-private/conf/<deployId>/conf.server.json` are used.
2878
- * @param {Object} options - The default underpost runner options for customizing workflow.
3007
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2879
3008
  * @param {string} [options.deployId] - Deploy ID for storage lookup (defaults to 'dd-default').
2880
3009
  * @param {boolean} [options.dev] - Use development environment; defaults to production.
2881
3010
  * @memberof UnderpostRun
@@ -2967,7 +3096,7 @@ EOF`;
2967
3096
  * @method build-cluster-deployment-manifests
2968
3097
  * @description Builds deployment manifests for both production and development environments using `node bin deploy --build-manifest`, syncing them, and setting replicas to 1 for the `dd` deployment.
2969
3098
  * @param {string} path - Unused.
2970
- * @param {Object} options - The default underpost runner options for customizing workflow.
3099
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2971
3100
  * @memberof UnderpostRun
2972
3101
  */
2973
3102
  'build-cluster-deployment-manifests': (path = '', options = DEFAULT_OPTION) => {
@@ -2980,7 +3109,7 @@ EOF`;
2980
3109
  * @description Installs and enables the Cockpit KVM Dashboard (cockpit, cockpit-machines, libvirt)
2981
3110
  * and opens the cockpit firewall service. With `--remove`, closes the firewall service instead.
2982
3111
  * @param {string} path - Unused.
2983
- * @param {Object} options - The default underpost runner options for customizing workflow.
3112
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2984
3113
  * `options.remove` — when true, removes the cockpit firewall rule instead of adding it.
2985
3114
  * @memberof UnderpostRun
2986
3115
  */
@@ -3004,7 +3133,7 @@ EOF`;
3004
3133
  * Use `reload-shared-dir` for subsequent permission repairs without recreating the group.
3005
3134
  * @param {string} path - Target directory to set up (defaults to `/home/dd/engine`).
3006
3135
  * Customise via the `path` argument or leave empty to use the default.
3007
- * @param {Object} options - The default underpost runner options for customizing workflow.
3136
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
3008
3137
  * Key fields: `options.user` (default `'admin'`), `options.group` (default `'engine-dev'`).
3009
3138
  * @memberof UnderpostRun
3010
3139
  */
@@ -3032,7 +3161,7 @@ EOF`;
3032
3161
  * write throughout the shared workspace while preserving existing ownership.
3033
3162
  *
3034
3163
  * @param {string} path - Shared directory (defaults to `/home/dd/engine`).
3035
- * @param {Object} options - Underpost runner options.
3164
+ * @param {UnderpostRunDefaultOptions} options - Underpost runner options.
3036
3165
  * Key fields:
3037
3166
  * - options.user (default: 'admin')
3038
3167
  * - options.group (default: 'engine-dev')
@@ -3080,7 +3209,7 @@ EOF`;
3080
3209
  * @description Executes a specified runner function from the UnderpostRun class with the provided path and options.
3081
3210
  * @param {string} runner - The name of the runner to execute.
3082
3211
  * @param {string} path - The input value, identifier, or path for the operation.
3083
- * @param {Object} options - The default underpost runner options for customizing workflow
3212
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
3084
3213
  * @memberof UnderpostRun
3085
3214
  * @returns {Promise<any>} The result of the runner execution.
3086
3215
  */
@@ -3093,7 +3222,7 @@ EOF`;
3093
3222
  * @description Initiates the execution of a specified CLI command (runner) with the given input value (`path`) and processed options.
3094
3223
  * @param {string} runner - The name of the runner to execute.
3095
3224
  * @param {string} path - The input value, identifier, or path for the operation.
3096
- * @param {Object} options - The default underpost runner options for customizing workflow
3225
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
3097
3226
  * @memberof UnderpostRun
3098
3227
  * @returns {Promise<any>} The result of the callback execution.
3099
3228
  */