underpost 3.2.28 → 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,10 +52,12 @@ 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.
58
59
  * @property {string} nodeName - The name of the node to run.
60
+ * @property {string} sshKeyPath - Private key path for node SSH operations, forwarded to volume shipping over SSH.
59
61
  * @property {number} port - Custom port to use.
60
62
  * @property {string} volumeHostPath - The host path for the volume.
61
63
  * @property {string} volumeMountPath - The mount path for the volume.
@@ -127,6 +129,7 @@ const DEFAULT_OPTION = {
127
129
  dev: false,
128
130
  podName: '',
129
131
  nodeName: '',
132
+ sshKeyPath: '',
130
133
  port: 0,
131
134
  volumeHostPath: '',
132
135
  volumeMountPath: '',
@@ -213,7 +216,7 @@ class UnderpostRun {
213
216
  * @method dev-cluster
214
217
  * @description Resets and deploys a full development cluster including MongoDB, Valkey, exposes services, and updates `/etc/hosts` for local access.
215
218
  * @param {string} path - The input value, identifier, or path for the operation.
216
- * @param {Object} options - The default underpost runner options for customizing workflow
219
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
217
220
  * @memberof UnderpostRun
218
221
  */
219
222
  'dev-cluster': (path, options = DEFAULT_OPTION) => {
@@ -295,7 +298,7 @@ class UnderpostRun {
295
298
  * @method metadata
296
299
  * @description Generates metadata for the specified path after exposing the development cluster.
297
300
  * @param {string} path - The input value, identifier, or path for the operation.
298
- * @param {Object} options - The default underpost runner options for customizing workflow
301
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
299
302
  * @memberof UnderpostRun
300
303
  */
301
304
  metadata: async (path, options = DEFAULT_OPTION) => {
@@ -320,7 +323,7 @@ class UnderpostRun {
320
323
  * @method svc-ls
321
324
  * @description Lists systemd services and installed packages, optionally filtering by the provided path.
322
325
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional filter for services and packages).
323
- * @param {Object} options - The default underpost runner options for customizing workflow
326
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
324
327
  * @memberof UnderpostRun
325
328
  */
326
329
  'svc-ls': (path, options = DEFAULT_OPTION) => {
@@ -340,7 +343,7 @@ class UnderpostRun {
340
343
  * @method svc-rm
341
344
  * @description Removes a systemd service by stopping it, disabling it, uninstalling the package, and deleting related files.
342
345
  * @param {string} path - The input value, identifier, or path for the operation (used as the service name).
343
- * @param {Object} options - The default underpost runner options for customizing workflow
346
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
344
347
  * @memberof UnderpostRun
345
348
  */
346
349
  'svc-rm': (path, options = DEFAULT_OPTION) => {
@@ -355,7 +358,7 @@ class UnderpostRun {
355
358
  * @method ssh-deploy-info
356
359
  * @description Retrieves deployment status and pod information from a remote server via SSH.
357
360
  * @param {string} path - The input value, identifier, or path for the operation.
358
- * @param {Object} options - The default underpost runner options for customizing workflow
361
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
359
362
  * @memberof UnderpostRun
360
363
  */
361
364
  'ssh-deploy-info': async (path = '', options = DEFAULT_OPTION) => {
@@ -399,7 +402,7 @@ class UnderpostRun {
399
402
  * skipped (move the owning controller). StatefulSets bound to node-local PVs may stay
400
403
  * Pending after a move until their volume is available on the target node.
401
404
  * @param {string} path - Resource selector (`kind/name`, `kind`, or empty).
402
- * @param {Object} options - The default underpost runner options for customizing workflow
405
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
403
406
  * @memberof UnderpostRun
404
407
  * @returns {Array<{ref:string,kind:string,status:string,node?:string}>} Per-resource outcome.
405
408
  */
@@ -444,7 +447,15 @@ class UnderpostRun {
444
447
 
445
448
  // Kinds that own a pod template we can patch; rolloutKinds additionally
446
449
  // support `kubectl rollout restart` to reschedule existing pods now.
447
- const templated = ['deployment', 'statefulset', 'daemonset', 'replicaset', 'job', 'cronjob', 'replicationcontroller'];
450
+ const templated = [
451
+ 'deployment',
452
+ 'statefulset',
453
+ 'daemonset',
454
+ 'replicaset',
455
+ 'job',
456
+ 'cronjob',
457
+ 'replicationcontroller',
458
+ ];
448
459
  const rolloutKinds = ['deployment', 'statefulset', 'daemonset'];
449
460
  const templateSelectorPath = (kind) =>
450
461
  kind === 'cronjob'
@@ -456,7 +467,10 @@ class UnderpostRun {
456
467
  let selector = { 'kubernetes.io/hostname': node };
457
468
  if (!remove && options.labels) {
458
469
  selector = {};
459
- for (const pair of `${options.labels}`.split(',').map((s) => s.trim()).filter(Boolean)) {
470
+ for (const pair of `${options.labels}`
471
+ .split(',')
472
+ .map((s) => s.trim())
473
+ .filter(Boolean)) {
460
474
  const eq = pair.indexOf('=');
461
475
  if (eq < 0) continue;
462
476
  selector[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim();
@@ -483,8 +497,11 @@ class UnderpostRun {
483
497
 
484
498
  const kubectlNames = (kind) =>
485
499
  (
486
- shellExec(`kubectl get ${kind} -n ${ns} -o name`, { silent: true, stdout: true, silentOnError: true }).trim() ||
487
- ''
500
+ shellExec(`kubectl get ${kind} -n ${ns} -o name`, {
501
+ silent: true,
502
+ stdout: true,
503
+ silentOnError: true,
504
+ }).trim() || ''
488
505
  )
489
506
  .split('\n')
490
507
  .map((s) => s.trim())
@@ -585,7 +602,7 @@ class UnderpostRun {
585
602
  * @method dev-hosts-expose
586
603
  * @description Deploys a specified service in development mode with `/etc/hosts` modification for local access.
587
604
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
588
- * @param {Object} options - The default underpost runner options for customizing workflow
605
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
589
606
  * @memberof UnderpostRun
590
607
  */
591
608
  'dev-hosts-expose': (path, options = DEFAULT_OPTION) => {
@@ -598,7 +615,7 @@ class UnderpostRun {
598
615
  * @method dev-hosts-restore
599
616
  * @description Restores the `/etc/hosts` file to its original state after modifications made during development deployments.
600
617
  * @param {string} path - The input value, identifier, or path for the operation.
601
- * @param {Object} options - The default underpost runner options for customizing workflow
618
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
602
619
  * @memberof UnderpostRun
603
620
  */
604
621
  'dev-hosts-restore': (path, options = DEFAULT_OPTION) => {
@@ -609,11 +626,13 @@ class UnderpostRun {
609
626
  * @method cluster-build
610
627
  * @description Build configuration for cluster deployment.
611
628
  * @param {string} path - The input value, identifier, or path for the operation.
612
- * @param {Object} options - The default underpost runner options for customizing workflow
629
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
613
630
  * @memberof UnderpostRun
614
631
  */
615
632
  'cluster-build': (path, options = DEFAULT_OPTION) => {
616
- const nodeOptions = options.nodeName ? ` --node-name ${options.nodeName}` : '';
633
+ const nodeOptions =
634
+ (options.nodeName ? ` --node-name ${options.nodeName}` : '') +
635
+ (options.sshKeyPath ? ` --ssh-key-path ${options.sshKeyPath}` : '');
617
636
  shellExec(`node bin run clean`);
618
637
  shellExec(`node bin run --dev sync-replica template-deploy${nodeOptions}`);
619
638
  shellExec(`node bin run sync-replica template-deploy${nodeOptions}`);
@@ -631,7 +650,7 @@ class UnderpostRun {
631
650
  * and optionally triggers engine-<conf-id> CI with sync/init which in turn dispatches the CD workflow
632
651
  * after the build chain completes (template → ghpkg → engine-<conf-id> → CD).
633
652
  * @param {string} path - The deployment path identifier (e.g., 'sync-engine-core', 'init-engine-core', or empty for build-only).
634
- * @param {Object} options - The default underpost runner options for customizing workflow
653
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
635
654
  * @memberof UnderpostRun
636
655
  */
637
656
  'template-deploy': (path = '', options = DEFAULT_OPTION) => {
@@ -645,13 +664,10 @@ class UnderpostRun {
645
664
  shellExec(`${baseCommand} run pull`);
646
665
  shellExec(`${baseCommand} run shared-dir`);
647
666
 
648
- // Capture last N commit messages for propagation.
649
- // When --from-n-commit is not set, auto-detect unpushed commit count (same as --unpush flag).
650
- const fromN =
651
- options.fromNCommit && parseInt(options.fromNCommit) > 0
652
- ? parseInt(options.fromNCommit)
653
- : Underpost.repo.getUnpushedCount('.').count;
654
- 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`, {
655
671
  silent: true,
656
672
  stdout: true,
657
673
  }).trim();
@@ -663,8 +679,6 @@ class UnderpostRun {
663
679
  );
664
680
  shellCd('/home/dd/engine');
665
681
 
666
- const sanitizedMessage = Underpost.repo.sanitizeChangelogMessage(message);
667
-
668
682
  // Push engine repo so workflow YAML changes reach GitHub
669
683
  shellExec(`git reset`);
670
684
  shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
@@ -712,7 +726,7 @@ class UnderpostRun {
712
726
  * @method template-deploy-local
713
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.
714
728
  * @param {string} path - The deployment path identifier (e.g., 'sync-engine-core', 'init-engine-core', or empty for build-only).
715
- * @param {Object} options - The default underpost runner options for customizing workflow
729
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
716
730
  * @memberof UnderpostRun
717
731
  */
718
732
  'template-deploy-local': async (path, options = DEFAULT_OPTION) => {
@@ -726,17 +740,12 @@ class UnderpostRun {
726
740
  shellExec(`${baseCommand} run pull`);
727
741
  shellExec(`${baseCommand} run shared-dir`);
728
742
 
729
- // Capture last N commit messages from the engine repo.
730
- // When --from-n-commit is not set, auto-detect unpushed commit count (same as --unpush flag).
731
- const fromN =
732
- options.fromNCommit && parseInt(options.fromNCommit) > 0
733
- ? parseInt(options.fromNCommit)
734
- : Underpost.repo.getUnpushedCount('.').count;
735
- 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`, {
736
746
  silent: true,
737
747
  stdout: true,
738
748
  }).trim();
739
- const sanitizedMessage = Underpost.repo.sanitizeChangelogMessage(rawMessage);
740
749
 
741
750
  const { triggerCmd } = path
742
751
  ? await Underpost.release.ci(path, sanitizedMessage, options)
@@ -748,15 +757,14 @@ class UnderpostRun {
748
757
  * @description Dispatches the Docker image CI workflow (`docker-image[.<runtime>].ci.yml`) via `workflow_dispatch`.
749
758
  * Repository resolution is delegated to `Underpost.repo.resolveInstanceRepo(path)`.
750
759
  * @param {string} path - Optional runtime / workflow suffix (e.g. `cyberia-server`, `cyberia-client`).
751
- * @param {Object} options - The default underpost runner options for customizing workflow
760
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
752
761
  * @memberof UnderpostRun
753
762
  */
754
763
  'docker-image': (path, options = DEFAULT_OPTION) => {
755
- const repo = Underpost.repo.resolveInstanceRepo(path);
764
+ const repo = Underpost.repo.resolveInstanceRepo(path, options.dev);
756
765
  Underpost.repo.dispatchWorkflow({
757
766
  repo,
758
- workflowFile: `docker-image${path ? `.${path}` : ''}.ci.yml`,
759
- ref: 'master',
767
+ workflowFile: `docker-image${path ? `.${path}` : ''}${options.dev ? '.dev' : ''}.ci.yml`,
760
768
  inputs: {},
761
769
  });
762
770
  },
@@ -764,7 +772,7 @@ class UnderpostRun {
764
772
  * @method clean
765
773
  * @description Changes directory to the provided path (defaulting to `/home/dd/engine`) and runs `node bin/deploy clean-core-repo`.
766
774
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional directory path).
767
- * @param {Object} options - The default underpost runner options for customizing workflow
775
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
768
776
  * @memberof UnderpostRun
769
777
  */
770
778
  clean: (path = '', options = DEFAULT_OPTION) => {
@@ -775,7 +783,7 @@ class UnderpostRun {
775
783
  * @method pull
776
784
  * @description Clones or pulls updates for the `engine` and `engine-private` repositories into `/home/dd/engine` and `/home/dd/engine/engine-private`.
777
785
  * @param {string} path - The input value, identifier, or path for the operation.
778
- * @param {Object} options - The default underpost runner options for customizing workflow
786
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
779
787
  * @memberof UnderpostRun
780
788
  */
781
789
  pull: (path, options = DEFAULT_OPTION) => {
@@ -802,7 +810,7 @@ class UnderpostRun {
802
810
  * @method release-deploy
803
811
  * @description Executes deployment (`underpost run deploy`) for all deployment IDs listed in `./engine-private/deploy/dd.router`.
804
812
  * @param {string} path - The input value, identifier, or path for the operation.
805
- * @param {Object} options - The default underpost runner options for customizing workflow
813
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
806
814
  * @memberof UnderpostRun
807
815
  */
808
816
  'release-deploy': (path, options = DEFAULT_OPTION) => {
@@ -818,7 +826,7 @@ class UnderpostRun {
818
826
  * @method ssh-deploy
819
827
  * @description Dispatches the corresponding CD workflow for SSH-based deployment, replacing empty commits with workflow_dispatch.
820
828
  * @param {string} path - The deployment identifier (e.g., 'engine-core', 'sync-engine-core', 'init-engine-core').
821
- * @param {Object} options - The default underpost runner options for customizing workflow
829
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
822
830
  * @memberof UnderpostRun
823
831
  */
824
832
  'ssh-deploy': (path, options = DEFAULT_OPTION) => {
@@ -833,9 +841,9 @@ class UnderpostRun {
833
841
  job = 'init';
834
842
  confId = path.replace(/^init-/, '');
835
843
  }
836
-
844
+ const repo = Underpost.repo.resolveInstanceRepo(confId, options.dev);
837
845
  Underpost.repo.dispatchWorkflow({
838
- repo: `${process.env.GITHUB_USERNAME}/engine`,
846
+ repo,
839
847
  workflowFile: `${confId}.cd.yml`,
840
848
  ref: 'master',
841
849
  inputs: { job },
@@ -846,7 +854,7 @@ class UnderpostRun {
846
854
  * @description Opens a Visual Studio Code (VS Code) session for the specified path using `node ${underpostRoot}/bin/zed ${path}`,
847
855
  * or installs Zed and sublime-text IDE if `path` is 'install'.
848
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).
849
- * @param {Object} options - The default underpost runner options for customizing workflow
857
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
850
858
  * @memberof UnderpostRun
851
859
  */
852
860
  ide: (path = '', options = DEFAULT_OPTION) => {
@@ -873,7 +881,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
873
881
  * @method crypto-policy
874
882
  * @description Sets the system's crypto policies to `DEFAULT:SHA1` using `update-crypto-policies` command.
875
883
  * @param {string} path - The input value, identifier, or path for the operation.
876
- * @param {Object} options - The default underpost runner options for customizing workflow
884
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
877
885
  * @memberof UnderpostRun
878
886
  */
879
887
  'crypto-policy': (path, options = DEFAULT_OPTION) => {
@@ -888,7 +896,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
888
896
  * `deployment.yaml`. Useful when you want to force `Always` so the kubelet re-pulls a mutable tag on every rollout. Example:
889
897
  * `node bin run sync dd-core --kubeadm --image-pull-policy Always`
890
898
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string containing deploy parameters).
891
- * @param {Object} options - The default underpost runner options for customizing workflow
899
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
892
900
  * @memberof UnderpostRun
893
901
  */
894
902
  sync: async (path, options = DEFAULT_OPTION) => {
@@ -909,7 +917,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
909
917
  replicas = replicas ? replicas : defaultPath[1];
910
918
  versions = versions ? versions.replaceAll('+', ',') : defaultPath[2];
911
919
  image = image ? image : defaultPath[3];
912
- node = node ? node : defaultPath[4];
920
+ node = node ? node : options.nodeName ? options.nodeName : defaultPath[4];
913
921
  shellExec(`${baseCommand} cluster --ns-use ${options.namespace}`);
914
922
 
915
923
  if (image && !image.startsWith('localhost'))
@@ -950,13 +958,14 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
950
958
  const skipFullBuildFlag = options.skipFullBuild ? ' --skip-full-build' : '';
951
959
  const pullBundleFlag = options.pullBundle ? ' --pull-bundle' : '';
952
960
  const imagePullPolicyFlag = options.imagePullPolicy ? ` --image-pull-policy ${options.imagePullPolicy}` : '';
961
+ const sshKeyPathFlag = options.sshKeyPath ? ` --ssh-key-path ${options.sshKeyPath}` : '';
953
962
 
954
963
  shellExec(
955
964
  `${baseCommand} deploy${clusterFlag} --build-manifest --sync --info-router --replicas ${replicas} --node ${node}${
956
965
  image ? ` --image ${image}` : ''
957
966
  }${versions ? ` --versions ${versions}` : ''}${
958
967
  options.namespace ? ` --namespace ${options.namespace}` : ''
959
- }${timeoutFlags}${cmdString}${gitCleanFlag}${skipFullBuildFlag}${pullBundleFlag}${imagePullPolicyFlag} ${deployId} ${env}`,
968
+ }${timeoutFlags}${cmdString}${gitCleanFlag}${skipFullBuildFlag}${pullBundleFlag}${imagePullPolicyFlag}${sshKeyPathFlag} ${deployId} ${env}`,
960
969
  );
961
970
 
962
971
  if (isDeployRunnerContext(path, options)) {
@@ -965,9 +974,9 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
965
974
  `${baseCommand} db ${deployId} ${clusterFlag}${baseClusterCommand} --repo-backup --primary-pod --git --force-clone --preserveUUID ${options.namespace ? ` --ns ${options.namespace}` : ''}`,
966
975
  );
967
976
  shellExec(
968
- `${baseCommand} deploy${clusterFlag}${cmdString} --replicas ${replicas} --disable-update-proxy ${deployId} ${env} --versions ${versions}${
977
+ `${baseCommand} deploy${clusterFlag}${cmdString} --replicas ${replicas} --node ${node} --disable-update-proxy ${deployId} ${env} --versions ${versions}${
969
978
  options.namespace ? ` --namespace ${options.namespace}` : ''
970
- }${timeoutFlags}${gitCleanFlag}${imagePullPolicyFlag}`,
979
+ }${timeoutFlags}${gitCleanFlag}${imagePullPolicyFlag}${sshKeyPathFlag}`,
971
980
  );
972
981
  if (!targetTraffic)
973
982
  targetTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace });
@@ -981,7 +990,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
981
990
  * @method stop
982
991
  * @description Stops a deployment by deleting the corresponding Kubernetes deployment and service resources.
983
992
  * @param {string} path - The input value, identifier, or path for the operation (used to determine which traffic to stop).
984
- * @param {Object} options - The default underpost runner options for customizing workflow
993
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
985
994
  * @memberof UnderpostRun
986
995
  */
987
996
  stop: async (path = '', options = DEFAULT_OPTION) => {
@@ -1005,7 +1014,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1005
1014
  * @method ssh-deploy-stop
1006
1015
  * @description Stops a remote deployment via SSH by executing the appropriate Underpost command on the remote server.
1007
1016
  * @param {string} path - The input value, identifier, or path for the operation (used to determine which traffic to stop).
1008
- * @param {Object} options - The default underpost runner options for customizing workflow
1017
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1009
1018
  * @memberof UnderpostRun
1010
1019
  */
1011
1020
  'ssh-deploy-stop': async (path, options = DEFAULT_OPTION) => {
@@ -1032,7 +1041,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1032
1041
  * @method ssh-deploy-db-rollback
1033
1042
  * @description Performs a database rollback on remote deployment via SSH.
1034
1043
  * @param {string} path - Comma-separated deployId and optional number of commits to reset (format: "deployId,nCommits")
1035
- * @param {Object} options - The default underpost runner options for customizing workflow
1044
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1036
1045
  * @param {string} options.deployId - The deployment identifier
1037
1046
  * @param {string} options.user - The SSH user for credential lookup
1038
1047
  * @param {boolean} options.dev - Development mode flag
@@ -1059,7 +1068,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1059
1068
  * @method ssh-deploy-db
1060
1069
  * @description Imports/restores a database on remote deployment via SSH.
1061
1070
  * @param {string} path - The deployment ID for database import
1062
- * @param {Object} options - The default underpost runner options for customizing workflow
1071
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1063
1072
  * @param {string} options.deployId - The deployment identifier
1064
1073
  * @param {string} options.user - The SSH user for credential lookup
1065
1074
  * @param {boolean} options.dev - Development mode flag
@@ -1084,7 +1093,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1084
1093
  * @method ssh-deploy-db-status
1085
1094
  * @description Retrieves database status/stats for a deployment (or all deployments from dd.router) via SSH.
1086
1095
  * @param {string} path - Comma-separated deployId(s) or 'dd' to use the dd.router list.
1087
- * @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).
1088
1097
  * @param {string} options.deployId - Deployment identifier used for SSH config lookup.
1089
1098
  * @param {string} options.user - SSH user for credential lookup.
1090
1099
  * @param {boolean} options.dev - Development mode flag.
@@ -1130,7 +1139,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1130
1139
  * @method tz
1131
1140
  * @description Sets the system timezone using `timedatectl set-timezone` command.
1132
1141
  * @param {string} path - The input value, identifier, or path for the operation (used as the timezone string).
1133
- * @param {Object} options - The default underpost runner options for customizing workflow
1142
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1134
1143
  * @memberof UnderpostRun
1135
1144
  */
1136
1145
  tz: (path, options = DEFAULT_OPTION) => {
@@ -1151,7 +1160,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
1151
1160
  * @method get-proxy
1152
1161
  * @description Retrieves and logs the HTTPProxy resources in the specified namespace using `kubectl get HTTPProxy`.
1153
1162
  * @param {string} path - The input value, identifier, or path for the operation (used as an optional filter for the HTTPProxy resources).
1154
- * @param {Object} options - The default underpost runner options for customizing workflow
1163
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1155
1164
  * @memberof UnderpostRun
1156
1165
  */
1157
1166
  'get-proxy': async (path = '', options = DEFAULT_OPTION) => {
@@ -1258,7 +1267,7 @@ EOF
1258
1267
  /**
1259
1268
  * @method instance
1260
1269
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string containing workflow parameters).
1261
- * @param {Object} options - The default underpost runner options for customizing workflow
1270
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1262
1271
  * @memberof UnderpostRun
1263
1272
  */
1264
1273
  instance: async (path = '', options = DEFAULT_OPTION) => {
@@ -1327,9 +1336,16 @@ EOF
1327
1336
  deployId: _deployId,
1328
1337
  env,
1329
1338
  version: targetTraffic,
1330
- nodeName: options.nodeName,
1339
+ nodeName: Underpost.deploy.resolveDeployNode({
1340
+ node: options.nodeName,
1341
+ kind: options.kind,
1342
+ kubeadm: options.kubeadm,
1343
+ k3s: options.k3s,
1344
+ env,
1345
+ }),
1331
1346
  clusterContext: options.k3s ? 'k3s' : options.kubeadm ? 'kubeadm' : 'kind',
1332
1347
  gitClean: options.gitClean || false,
1348
+ sshKeyPath: options.sshKeyPath || '',
1333
1349
  });
1334
1350
  // Regenerate the parent deploy's gRPC ClusterIP service pointing to the
1335
1351
  // parent's current traffic colour and apply it before the instance pod starts so
@@ -1423,12 +1439,39 @@ EOF
1423
1439
  }
1424
1440
  },
1425
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
+
1426
1468
  /**
1427
1469
  * @method instance-build-manifest
1428
1470
  * @description Builds a Kubernetes Deployment + Service manifest for a specific instance entry
1429
- * from `conf.instances.json` and writes it to a file.
1430
- * Traffic colour is automatically chosen as the opposite of the current live colour (blue/green),
1431
- * 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`).
1432
1475
  *
1433
1476
  * If `--build` is supplied the image is built from the project Dockerfile and loaded into the
1434
1477
  * cluster before the manifest is written (kind by default; `--kubeadm` / `--k3s` override).
@@ -1439,7 +1482,7 @@ EOF
1439
1482
  * `<projectPath>/manifests/<env>/deployment.yaml`.
1440
1483
  * In production, files are also copied to `<projectPath>/Dockerfile` and
1441
1484
  * `<projectPath>/deployment.yaml`.
1442
- * @param {Object} options - The default underpost runner options for customizing workflow
1485
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1443
1486
  * @memberof UnderpostRun
1444
1487
  */
1445
1488
  'instance-build-manifest': (path, options = DEFAULT_OPTION) => {
@@ -1518,7 +1561,7 @@ EOF
1518
1561
  path: projectPath,
1519
1562
  imageName: _image,
1520
1563
  podmanSave: true,
1521
- imagePath: projectPath,
1564
+ imageOutPath: projectPath,
1522
1565
  kind: isKind,
1523
1566
  kubeadm: !!options.kubeadm,
1524
1567
  k3s: !!options.k3s,
@@ -1531,15 +1574,8 @@ EOF
1531
1574
  });
1532
1575
  }
1533
1576
 
1534
- // Determine target traffic: opposite of current, or 'blue' if nothing is running yet.
1535
- const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
1536
- hostTest: _host,
1537
- namespace: options.namespace,
1538
- });
1539
- const targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'blue';
1540
-
1541
- // Resolve {{grpc-service-dns}} using the parent deploy's current (or default) traffic.
1542
- const parentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace }) || 'blue';
1577
+ const targetTraffic = options.traffic || 'blue';
1578
+ const parentTraffic = targetTraffic;
1543
1579
  const resolvedCmd = _cmd[env].map((c) =>
1544
1580
  c.replaceAll(
1545
1581
  '{{grpc-service-dns}}',
@@ -1587,11 +1623,86 @@ EOF
1587
1623
  image: _image,
1588
1624
  });
1589
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
+
1590
1696
  if (env === 'production') {
1591
1697
  if (fs.existsSync(dockerfileManifestPath)) {
1592
1698
  fs.copyFileSync(dockerfileManifestPath, `${rootPath}/Dockerfile`);
1593
1699
  }
1594
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
+ }
1595
1706
  logger.info('[instance-build-manifest] Production artifacts copied to project root', {
1596
1707
  rootPath,
1597
1708
  dockerfile: `${rootPath}/Dockerfile`,
@@ -1603,6 +1714,25 @@ EOF
1603
1714
  fs.copyFileSync(ciSrc, `${rootPath}/.github/workflows/docker-image.${_runtime}.ci.yml`);
1604
1715
  logger.info(`[instance-build-manifest] CI workflow copied`, { src: ciSrc });
1605
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
+ }
1606
1736
  }
1607
1737
  },
1608
1738
 
@@ -1610,7 +1740,7 @@ EOF
1610
1740
  * @method ls-deployments
1611
1741
  * @description Retrieves and logs a table of Kubernetes deployments using `Underpost.deploy.get`.
1612
1742
  * @param {string} path - The input value, identifier, or path for the operation (used as an optional deployment name filter).
1613
- * @param {Object} options - The default underpost runner options for customizing workflow
1743
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1614
1744
  * @memberof UnderpostRun
1615
1745
  */
1616
1746
  'ls-deployments': async (path, options = DEFAULT_OPTION) => {
@@ -1621,7 +1751,7 @@ EOF
1621
1751
  * @method host-update
1622
1752
  * @description Executes the `rocky-setup.sh` script to update the host system configuration.
1623
1753
  * @param {string} path - The input value, identifier, or path for the operation.
1624
- * @param {Object} options - The default underpost runner options for customizing workflow
1754
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1625
1755
  * @memberof UnderpostRun
1626
1756
  */
1627
1757
  'host-update': async (path, options = DEFAULT_OPTION) => {
@@ -1637,7 +1767,7 @@ EOF
1637
1767
  * the systemd cgroup driver, enables the `crio` service, and writes `/etc/crictl.yaml`
1638
1768
  * so that `crictl` targets the CRI-O socket by default.
1639
1769
  * @param {string} path - Unused.
1640
- * @param {Object} options - The default underpost runner options for customizing workflow.
1770
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
1641
1771
  * @memberof UnderpostRun
1642
1772
  */
1643
1773
  'install-crio': (path, options = DEFAULT_OPTION) => {
@@ -1688,7 +1818,7 @@ EOF`);
1688
1818
  * @method dd-container
1689
1819
  * @description Deploys a development or debug container tasks jobs, setting up necessary volumes and images, and running specified commands within the container.
1690
1820
  * @param {string} path - The input value, identifier, or path for the operation (used as the command to run inside the container).
1691
- * @param {Object} options - The default underpost runner options for customizing workflow
1821
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1692
1822
  * @memberof UnderpostRun
1693
1823
  */
1694
1824
  'dd-container': async (path = '', options = DEFAULT_OPTION) => {
@@ -1715,7 +1845,11 @@ EOF`);
1715
1845
  }
1716
1846
 
1717
1847
  if (!currentImage)
1718
- 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
+ );
1719
1853
  // shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
1720
1854
 
1721
1855
  const payload = {
@@ -1743,7 +1877,7 @@ EOF`);
1743
1877
  * @method ip-info
1744
1878
  * @description Executes the `ip-info.sh` script to display IP-related information for the specified path.
1745
1879
  * @param {string} path - The input value, identifier, or path for the operation (used as an argument to the script).
1746
- * @param {Object} options - The default underpost runner options for customizing workflow
1880
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1747
1881
  * @memberof UnderpostRun
1748
1882
  */
1749
1883
  'ip-info': (path, options = DEFAULT_OPTION) => {
@@ -1756,7 +1890,7 @@ EOF`);
1756
1890
  * @method db-client
1757
1891
  * @description Deploys and exposes the Adminer database client application (using `adminer:4.7.6-standalone` image) on the cluster.
1758
1892
  * @param {string} path - The input value, identifier, or path for the operation.
1759
- * @param {Object} options - The default underpost runner options for customizing workflow
1893
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1760
1894
  * @memberof UnderpostRun
1761
1895
  */
1762
1896
  'db-client': async (path, options = DEFAULT_OPTION) => {
@@ -1783,7 +1917,7 @@ EOF`);
1783
1917
  * @method git-conf
1784
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.
1785
1919
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `username,email`).
1786
- * @param {Object} options - The default underpost runner options for customizing workflow
1920
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1787
1921
  * @memberof UnderpostRun
1788
1922
  */
1789
1923
  'git-conf': (path = '', options = DEFAULT_OPTION) => {
@@ -1831,7 +1965,7 @@ EOF`);
1831
1965
  * TLS config, deletes stale Certificate resources, then reapplies the proxy and secret.yaml
1832
1966
  * (cert-manager Certificate resources) for each affected deployment.
1833
1967
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `deployId,env,replicas`).
1834
- * @param {Object} options - The default underpost runner options for customizing workflow
1968
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1835
1969
  * @memberof UnderpostRun
1836
1970
  */
1837
1971
  promote: async (path, options = DEFAULT_OPTION) => {
@@ -1885,10 +2019,31 @@ EOF`);
1885
2019
  * @method metrics
1886
2020
  * @description Deploys Prometheus and Grafana for metrics monitoring, targeting the hosts defined in the deployment configuration files.
1887
2021
  * @param {string} path - The input value, identifier, or path for the operation.
1888
- * @param {Object} options - The default underpost runner options for customizing workflow
2022
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1889
2023
  * @memberof UnderpostRun
1890
2024
  */
1891
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
+ }
1892
2047
  const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
1893
2048
  let hosts = [];
1894
2049
  for (const deployId of deployList) {
@@ -1902,7 +2057,7 @@ EOF`);
1902
2057
  * @method cluster
1903
2058
  * @description Deploys a full production/development ready Kubernetes cluster environment including MongoDB, MariaDB, Valkey, Contour (Ingress), and Cert-Manager, and deploys all services.
1904
2059
  * @param {string} path - The input value, identifier, or path for the operation.
1905
- * @param {Object} options - The default underpost runner options for customizing workflow
2060
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1906
2061
  * @memberof UnderpostRun
1907
2062
  */
1908
2063
  cluster: async (path = '', options = DEFAULT_OPTION) => {
@@ -1964,7 +2119,7 @@ EOF`);
1964
2119
  * @method deploy
1965
2120
  * @description Deploys a specified service (identified by `path`) using blue/green strategy, monitors its status, and switches traffic upon readiness.
1966
2121
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
1967
- * @param {Object} options - The default underpost runner options for customizing workflow
2122
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1968
2123
  * @memberof UnderpostRun
1969
2124
  */
1970
2125
  deploy: async (path, options = DEFAULT_OPTION) => {
@@ -1989,7 +2144,7 @@ EOF`);
1989
2144
  * @method disk-clean
1990
2145
  * @description Executes the `disk-clean-sh` script to perform disk cleanup operations.
1991
2146
  * @param {string} path - The input value, identifier, or path for the operation.
1992
- * @param {Object} options - The default underpost runner options for customizing workflow
2147
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
1993
2148
  * @memberof UnderpostRun
1994
2149
  */
1995
2150
  'disk-clean': async (path, options = DEFAULT_OPTION) => {
@@ -2002,7 +2157,7 @@ EOF`);
2002
2157
  * @method disk-devices
2003
2158
  * @description Executes the `disk-devices.sh` script to display information about disk devices.
2004
2159
  * @param {string} path - The input value, identifier, or path for the operation.
2005
- * @param {Object} options - The default underpost runner options for customizing workflow
2160
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2006
2161
  * @memberof UnderpostRun
2007
2162
  */
2008
2163
  'disk-devices': async (path = '/', options = DEFAULT_OPTION) => {
@@ -2015,7 +2170,7 @@ EOF`);
2015
2170
  * @method disk-usage
2016
2171
  * @description Displays disk usage statistics using the `du` command, sorted by size.
2017
2172
  * @param {string} path - The input value, identifier, or path for the operation.
2018
- * @param {Object} options - The default underpost runner options for customizing workflow
2173
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2019
2174
  * @memberof UnderpostRun
2020
2175
  */
2021
2176
  'disk-usage': async (path = '/', options = DEFAULT_OPTION) => {
@@ -2030,7 +2185,7 @@ EOF`);
2030
2185
  * @method dev
2031
2186
  * @description Starts development servers for client, API, and proxy based on provided parameters (deployId, host, path, clientHostPort).
2032
2187
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,subConf,host,path,clientHostPort`).
2033
- * @param {Object} options - The default underpost runner options for customizing workflow
2188
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2034
2189
  * @memberof UnderpostRun
2035
2190
  */
2036
2191
  dev: async (path = '', options = DEFAULT_OPTION) => {
@@ -2090,7 +2245,7 @@ EOF`);
2090
2245
  * @method service
2091
2246
  * @description Deploys and exposes specific services (like `mongo-express-service`) on the cluster, updating deployment configurations and monitoring status.
2092
2247
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,serviceId,host,path,replicas,image,node`).
2093
- * @param {Object} options - The default underpost runner options for customizing workflow
2248
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2094
2249
  * @memberof UnderpostRun
2095
2250
  */
2096
2251
  service: async (path = '', options = DEFAULT_OPTION) => {
@@ -2186,7 +2341,7 @@ EOF`);
2186
2341
  * @method etc-hosts
2187
2342
  * @description Generates and logs the contents for the `/etc/hosts` file based on provided hosts or deployment configurations.
2188
2343
  * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated list of hosts).
2189
- * @param {Object} options - The default underpost runner options for customizing workflow
2344
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2190
2345
  * @memberof UnderpostRun
2191
2346
  */
2192
2347
  'etc-hosts': async (path = '', options = DEFAULT_OPTION) => {
@@ -2203,7 +2358,7 @@ EOF`);
2203
2358
  * @method sh
2204
2359
  * @description Enables remote control for the Kitty terminal emulator.
2205
2360
  * @param {string} path - The input value, identifier, or path for the operation.
2206
- * @param {Object} options - The default underpost runner options for customizing workflow
2361
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2207
2362
  * @memberof UnderpostRun
2208
2363
  */
2209
2364
  sh: async (path = '', options = DEFAULT_OPTION) => {
@@ -2223,7 +2378,7 @@ EOF`);
2223
2378
  * @method log
2224
2379
  * @description Searches and highlights keywords in a specified log file, optionally showing surrounding lines.
2225
2380
  * @param {string} path - The input value, identifier, or path for the operation (formatted as `filePath,keywords,lines`).
2226
- * @param {Object} options - The default underpost runner options for customizing workflow
2381
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2227
2382
  * @memberof UnderpostRun
2228
2383
  */
2229
2384
  log: async (path, options = DEFAULT_OPTION) => {
@@ -2240,7 +2395,7 @@ EOF`);
2240
2395
  * @method ps
2241
2396
  * @description Displays running processes that match a specified path or keyword.
2242
2397
  * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter processes).
2243
- * @param {Object} options - The default underpost runner options for customizing workflow
2398
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2244
2399
  * @memberof UnderpostRun
2245
2400
  */
2246
2401
  ps: async (path = '', options = DEFAULT_OPTION) => {
@@ -2265,7 +2420,7 @@ EOF`);
2265
2420
  * @method pid-info
2266
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.
2267
2422
  * @param {string} path - The PID of the process to inspect.
2268
- * @param {Object} options - The default underpost runner options for customizing workflow
2423
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2269
2424
  * @memberof UnderpostRun
2270
2425
  */
2271
2426
  'pid-info': (path, options = DEFAULT_OPTION) => {
@@ -2305,7 +2460,7 @@ EOF`);
2305
2460
  * @method background
2306
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`.
2307
2462
  * @param {string} path - The command to run in the background (e.g. 'npm run prod:container dd-cyberia-r3').
2308
- * @param {Object} options - The default underpost runner options for customizing workflow
2463
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2309
2464
  * @memberof UnderpostRun
2310
2465
  */
2311
2466
  background: (path, options = DEFAULT_OPTION) => {
@@ -2325,7 +2480,7 @@ EOF`);
2325
2480
  * @method ports
2326
2481
  * @description Set on ~/.bashrc alias: ports <port> Command to list listening ports that match the given keyword.
2327
2482
  * @param {string} path - The input value, identifier, or path for the operation (used as a keyword to filter listening ports).
2328
- * @param {Object} options - The default underpost runner options for customizing workflow
2483
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2329
2484
  * @memberof UnderpostRun
2330
2485
  */
2331
2486
  ports: async (path = '', options = DEFAULT_OPTION) => {
@@ -2337,7 +2492,7 @@ EOF`);
2337
2492
  * @method deploy-test
2338
2493
  * @description Deploys a test deployment (`dd-test`) in either development or production mode, setting up necessary secrets and starting the deployment.
2339
2494
  * @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID).
2340
- * @param {Object} options - The default underpost runner options for customizing workflow
2495
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2341
2496
  * @memberof UnderpostRun
2342
2497
  */
2343
2498
  'deploy-test': async (path, options = DEFAULT_OPTION) => {
@@ -2362,7 +2517,7 @@ EOF`);
2362
2517
  * @method tf-vae-test
2363
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.
2364
2519
  * @param {string} path - The input value, identifier, or path for the operation.
2365
- * @param {Object} options - The default underpost runner options for customizing workflow
2520
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2366
2521
  * @memberof UnderpostRun
2367
2522
  */
2368
2523
  'tf-vae-test': async (path, options = DEFAULT_OPTION) => {
@@ -2462,7 +2617,7 @@ EOF`);
2462
2617
  * @method spark-template
2463
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`.
2464
2619
  * @param {string} path - The input value, identifier, or path for the operation.
2465
- * @param {Object} options - The default underpost runner options for customizing workflow
2620
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2466
2621
  * @memberof UnderpostRun
2467
2622
  */
2468
2623
  'spark-template': (path, options = DEFAULT_OPTION) => {
@@ -2490,7 +2645,7 @@ EOF`);
2490
2645
  * @method pull-rocky-image
2491
2646
  * @description Pulls the base `rockylinux:9` image from Docker Hub via Podman.
2492
2647
  * @param {string} path - The input value, identifier, or path for the operation.
2493
- * @param {Object} options - The default underpost runner options for customizing workflow
2648
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2494
2649
  * @memberof UnderpostRun
2495
2650
  */
2496
2651
  'pull-rocky-image': (path, options = DEFAULT_OPTION) => {
@@ -2500,7 +2655,7 @@ EOF`);
2500
2655
  * @method rmi
2501
2656
  * @description Forces the removal of all local Podman images (`podman rmi $(podman images -qa) --force`).
2502
2657
  * @param {string} path - The input value, identifier, or path for the operation.
2503
- * @param {Object} options - The default underpost runner options for customizing workflow
2658
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2504
2659
  * @memberof UnderpostRun
2505
2660
  */
2506
2661
  rmi: (path, options = DEFAULT_OPTION) => {
@@ -2510,7 +2665,7 @@ EOF`);
2510
2665
  * @method kill
2511
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.
2512
2667
  * @param {string} path - The input value, identifier, or path for the operation (used as the port number).
2513
- * @param {Object} options - The default underpost runner options for customizing workflow
2668
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2514
2669
  * @memberof UnderpostRun
2515
2670
  */
2516
2671
  kill: (path = '', options = DEFAULT_OPTION) => {
@@ -2542,7 +2697,7 @@ EOF`);
2542
2697
  * constraints (lowercase, uppercase, digit, special char, min 8 chars). Logs the plain password
2543
2698
  * to the console or, when `--copy` is set, copies it to the clipboard via pbcopy.
2544
2699
  * @param {string} path - Optional password length (default: 16).
2545
- * @param {Object} options - The default underpost runner options for customizing workflow.
2700
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2546
2701
  * @param {boolean} options.copy - When true, copies to clipboard instead of logging.
2547
2702
  * @memberof UnderpostRun
2548
2703
  */
@@ -2576,7 +2731,7 @@ EOF`);
2576
2731
  * @method secret
2577
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.
2578
2733
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional path to the secret file).
2579
- * @param {Object} options - The default underpost runner options for customizing workflow
2734
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2580
2735
  * @memberof UnderpostRun
2581
2736
  */
2582
2737
  secret: (path, options = DEFAULT_OPTION) => {
@@ -2589,7 +2744,7 @@ EOF`);
2589
2744
  * @method underpost-config
2590
2745
  * @description Calls `Underpost.deploy.configMap` to create a Kubernetes ConfigMap, defaulting to the 'production' environment.
2591
2746
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional configuration name/environment).
2592
- * @param {Object} options - The default underpost runner options for customizing workflow
2747
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2593
2748
  * @memberof UnderpostRun
2594
2749
  */
2595
2750
  'underpost-config': (path = '', options = DEFAULT_OPTION) => {
@@ -2599,7 +2754,7 @@ EOF`);
2599
2754
  * @method gpu-env
2600
2755
  * @description Sets up a dedicated GPU development environment cluster, resetting and then setting up the cluster with `--dedicated-gpu` and monitoring the pods.
2601
2756
  * @param {string} path - The input value, identifier, or path for the operation.
2602
- * @param {Object} options - The default underpost runner options for customizing workflow
2757
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2603
2758
  * @memberof UnderpostRun
2604
2759
  */
2605
2760
  'gpu-env': (path, options = DEFAULT_OPTION) => {
@@ -2612,7 +2767,7 @@ EOF`);
2612
2767
  * @method tf-gpu-test
2613
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`.
2614
2769
  * @param {string} path - The input value, identifier, or path for the operation.
2615
- * @param {Object} options - The default underpost runner options for customizing workflow
2770
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2616
2771
  * @memberof UnderpostRun
2617
2772
  */
2618
2773
  'tf-gpu-test': (path, options = DEFAULT_OPTION) => {
@@ -2626,7 +2781,7 @@ EOF`);
2626
2781
  * @method deploy-job
2627
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).
2628
2783
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional script path or job argument).
2629
- * @param {Object} options - The default underpost runner options for customizing workflow
2784
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
2630
2785
  * @memberof UnderpostRun
2631
2786
  */
2632
2787
  'deploy-job': async (path, options = DEFAULT_OPTION) => {
@@ -2761,7 +2916,7 @@ EOF`;
2761
2916
  * Only files matching `<host>-<route>.zip.part*` or `<host>-<route>.zip` for each non-skipped route are uploaded.
2762
2917
  * @param {string} path - Optional `fsPath.splitOption` string.
2763
2918
  * Examples: `build` (default split 8), `build.16` (split 16 MB), `build.none-split` (no split flag).
2764
- * @param {Object} options - The default underpost runner options for customizing workflow.
2919
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2765
2920
  * @param {string} [options.deployId] - Override deploy ID.
2766
2921
  * @param {boolean} [options.dev] - Use development environment; defaults to production.
2767
2922
  * @memberof UnderpostRun
@@ -2849,7 +3004,7 @@ EOF`;
2849
3004
  * so that multi-path deployments are handled correctly.
2850
3005
  * @param {string} path - Optional comma-separated host name(s) to restrict processing (e.g. 'underpost.net' or 'a.com,b.com').
2851
3006
  * If omitted, all hosts from `engine-private/conf/<deployId>/conf.server.json` are used.
2852
- * @param {Object} options - The default underpost runner options for customizing workflow.
3007
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2853
3008
  * @param {string} [options.deployId] - Deploy ID for storage lookup (defaults to 'dd-default').
2854
3009
  * @param {boolean} [options.dev] - Use development environment; defaults to production.
2855
3010
  * @memberof UnderpostRun
@@ -2941,7 +3096,7 @@ EOF`;
2941
3096
  * @method build-cluster-deployment-manifests
2942
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.
2943
3098
  * @param {string} path - Unused.
2944
- * @param {Object} options - The default underpost runner options for customizing workflow.
3099
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2945
3100
  * @memberof UnderpostRun
2946
3101
  */
2947
3102
  'build-cluster-deployment-manifests': (path = '', options = DEFAULT_OPTION) => {
@@ -2954,7 +3109,7 @@ EOF`;
2954
3109
  * @description Installs and enables the Cockpit KVM Dashboard (cockpit, cockpit-machines, libvirt)
2955
3110
  * and opens the cockpit firewall service. With `--remove`, closes the firewall service instead.
2956
3111
  * @param {string} path - Unused.
2957
- * @param {Object} options - The default underpost runner options for customizing workflow.
3112
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2958
3113
  * `options.remove` — when true, removes the cockpit firewall rule instead of adding it.
2959
3114
  * @memberof UnderpostRun
2960
3115
  */
@@ -2978,7 +3133,7 @@ EOF`;
2978
3133
  * Use `reload-shared-dir` for subsequent permission repairs without recreating the group.
2979
3134
  * @param {string} path - Target directory to set up (defaults to `/home/dd/engine`).
2980
3135
  * Customise via the `path` argument or leave empty to use the default.
2981
- * @param {Object} options - The default underpost runner options for customizing workflow.
3136
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow.
2982
3137
  * Key fields: `options.user` (default `'admin'`), `options.group` (default `'engine-dev'`).
2983
3138
  * @memberof UnderpostRun
2984
3139
  */
@@ -3006,7 +3161,7 @@ EOF`;
3006
3161
  * write throughout the shared workspace while preserving existing ownership.
3007
3162
  *
3008
3163
  * @param {string} path - Shared directory (defaults to `/home/dd/engine`).
3009
- * @param {Object} options - Underpost runner options.
3164
+ * @param {UnderpostRunDefaultOptions} options - Underpost runner options.
3010
3165
  * Key fields:
3011
3166
  * - options.user (default: 'admin')
3012
3167
  * - options.group (default: 'engine-dev')
@@ -3054,7 +3209,7 @@ EOF`;
3054
3209
  * @description Executes a specified runner function from the UnderpostRun class with the provided path and options.
3055
3210
  * @param {string} runner - The name of the runner to execute.
3056
3211
  * @param {string} path - The input value, identifier, or path for the operation.
3057
- * @param {Object} options - The default underpost runner options for customizing workflow
3212
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
3058
3213
  * @memberof UnderpostRun
3059
3214
  * @returns {Promise<any>} The result of the runner execution.
3060
3215
  */
@@ -3067,7 +3222,7 @@ EOF`;
3067
3222
  * @description Initiates the execution of a specified CLI command (runner) with the given input value (`path`) and processed options.
3068
3223
  * @param {string} runner - The name of the runner to execute.
3069
3224
  * @param {string} path - The input value, identifier, or path for the operation.
3070
- * @param {Object} options - The default underpost runner options for customizing workflow
3225
+ * @param {UnderpostRunDefaultOptions} options - The default underpost runner options for customizing workflow
3071
3226
  * @memberof UnderpostRun
3072
3227
  * @returns {Promise<any>} The result of the callback execution.
3073
3228
  */