underpost 2.81.1 → 2.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.production CHANGED
@@ -10,6 +10,7 @@ GITHUB_TOKEN=changethis
10
10
  GITHUB_USERNAME=changethis
11
11
  GITHUB_BACKUP_REPO=changethis
12
12
  GITHUB_DNS_REPO=changethis
13
+ GITHUB_EMAIL=admin@default.net
13
14
  DEFAULT_DEPLOY_ID=dd-default
14
15
  DEFAULT_DEPLOY_HOST=default.net
15
16
  DEFAULT_DEPLOY_PATH=/
@@ -10,7 +10,9 @@ permissions:
10
10
  id-token: write
11
11
  jobs:
12
12
  pwa-microservices-template:
13
- if: github.repository == 'underpostnet/engine' && startsWith(github.event.head_commit.message, 'ci(package-pwa-microservices-template)')
13
+ if: |
14
+ github.repository == 'underpostnet/engine'
15
+ && startsWith(github.event.head_commit.message, 'ci(package-pwa-microservices-template')
14
16
  name: Update npm repo package Jobs
15
17
  runs-on: ubuntu-latest
16
18
  container:
@@ -56,17 +58,3 @@ jobs:
56
58
  git config user.email 'fcoverdugoa@underpost.net'
57
59
  underpost cmt . ci package-pwa-microservices-template-ghpkg 'Update npm repo package'
58
60
  underpost push . underpostnet/pwa-microservices-template
59
- # cd ../engine
60
- # git commit --allow-empty -m "ci(engine-core-repo-build): ⚙️ Update engine core repository"
61
- # git commit --allow-empty -m "ci(engine-cyberia-repo-build): ⚙️ Update engine cyberia repository"
62
- # git commit --allow-empty -m "ci(engine-lampp-repo-build): ⚙️ Update engine lampp repository"
63
- # git push https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/engine.git
64
-
65
- # git clone --bare https://github.com/underpostnet/engine.git
66
- # mkdir engine
67
- # mv ./engine.git ./engine/.git
68
- # cd engine
69
- # git init
70
-
71
- # git push -u origin https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/underpostnet/pwa-microservices-template-ghpkg.git
72
- # git push -u origin master
@@ -33,5 +33,13 @@ jobs:
33
33
  underpost run secret
34
34
  underpost run pull
35
35
  underpost run secret
36
- underpost cmt . --empty ci docker-image-engine
37
- underpost run ssh-deploy sync-engine-test
36
+ node bin run git-conf
37
+ node bin run template-deploy-image
38
+ underpost config set GITHUB_USERNAME underpostnet
39
+ mkdir -p /home/dd
40
+ sudo rm -rf /home/dd/engine
41
+ cd /home/dd
42
+ underpost clone underpostnet/engine
43
+ cd engine
44
+ npm install
45
+ node bin run ssh-deploy sync-engine-test
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  <!-- badges -->
20
20
 
21
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.81.1)](https://socket.dev/npm/package/underpost/overview/2.81.1) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
21
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.85.0)](https://socket.dev/npm/package/underpost/overview/2.85.0) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
22
22
 
23
23
  <!-- end-badges -->
24
24
 
@@ -66,7 +66,7 @@ Run dev client server
66
66
  npm run dev
67
67
  ```
68
68
  <!-- -->
69
- ## underpost ci/cd cli v2.81.1
69
+ ## underpost ci/cd cli v2.85.0
70
70
 
71
71
  ### Usage: `underpost [options] [command]`
72
72
  ```
package/bin/deploy.js CHANGED
@@ -499,7 +499,7 @@ try {
499
499
  shellExec(`node bin/deploy sync-deploy-envs`);
500
500
  shellExec(`node bin/build dd conf`);
501
501
  shellExec(`git add . && cd ./engine-private && git add .`);
502
- shellExec(`node bin cmt . ci package-pwa-microservices-template`);
502
+ shellExec(`node bin cmt . ci package-pwa-microservices-template 'New release v:${process.argv[3]}'`);
503
503
  shellExec(`node bin cmt ./engine-private ci package-pwa-microservices-template`);
504
504
  shellExec(`node bin push . ${process.env.GITHUB_USERNAME}/engine`);
505
505
  shellExec(`cd ./engine-private && node ../bin push . ${process.env.GITHUB_USERNAME}/engine-private`);
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.81.1
1
+ ## underpost ci/cd cli v2.85.0
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -123,20 +123,30 @@ Manages commits to a GitHub repository, supporting various commit types and
123
123
  options.
124
124
 
125
125
  Arguments:
126
- path The absolute or relative directory path of the repository.
127
- commit-type The type of commit to perform. Options: feat, fix, docs, style,
128
- refactor, perf, ci, cd, infra, build, test, chore, revert,
129
- backup.
130
- module-tag Optional: Sets a specific module tag for the commit.
131
- message Optional: Provides an additional custom message for the commit.
126
+ path The absolute or relative directory path of the
127
+ repository.
128
+ commit-type The type of commit to perform. Options: feat, fix,
129
+ docs, style, refactor, perf, ci, cd, infra, build,
130
+ test, chore, revert, backup.
131
+ module-tag Optional: Sets a specific module tag for the commit.
132
+ message Optional: Provides an additional custom message for
133
+ the commit.
132
134
 
133
135
  Options:
134
- --log Shows commit history from the specified number of latest n path
135
- commits.
136
- --empty Allows committing with empty files.
137
- --copy Copies the generated commit message to the clipboard.
138
- --info Displays information about available commit types.
139
- -h, --help display help for command
136
+ --log <latest-n> Shows commit history from the specified number of
137
+ latest n path commits.
138
+ --last-msg <latest-n> Displays the last n commit message.
139
+ --empty Allows committing with empty files.
140
+ --copy Copies the generated commit message to the
141
+ clipboard.
142
+ --info Displays information about available commit types.
143
+ --diff Shows the current git diff changes.
144
+ --edit Edit last commit.
145
+ --msg <msg> Sets a custom commit message.
146
+ --deploy-id <deploy-id> Sets the deployment configuration ID for the commit
147
+ context.
148
+ --cached Commit staged changes only or context.
149
+ -h, --help display help for command
140
150
 
141
151
  ```
142
152
 
@@ -613,7 +623,7 @@ Options:
613
623
  Runs a script from the specified path.
614
624
 
615
625
  Arguments:
616
- runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, underpost-config, gpu-env, tf-gpu-test, dev-cluster, ssh-cluster-info, dev-hosts-expose, dev-hosts-restore, cyberia-ide, engine-ide, cluster-build, template-deploy, clean, pull, release-deploy, ssh-deploy, ide, sync, ls-deployments, monitor, db-client, promote, metrics, cluster, deploy, sync-replica, tf-vae-test, deploy-job.
626
+ runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, underpost-config, gpu-env, tf-gpu-test, dev-cluster, ssh-cluster-info, dev-hosts-expose, dev-hosts-restore, cyberia-ide, engine-ide, cluster-build, template-deploy, template-deploy-image, clean, pull, release-deploy, ssh-deploy, ide, sync, ls-deployments, host-update, monitor, db-client, git-conf, promote, metrics, cluster, deploy, sync-replica, tf-vae-test, deploy-job.
617
627
  path The absolute or relative directory path where the script is located.
618
628
 
619
629
  Options:
@@ -631,6 +641,7 @@ Options:
631
641
  --namespace <namespace> Optional: Specifies the namespace for test execution.
632
642
  --kubeadm Flag to indicate Kubeadm cluster type context
633
643
  --k3s Flag to indicate K3s cluster type context
644
+ --force Forces operation, overriding any warnings or conflicts.
634
645
  -h, --help display help for command
635
646
 
636
647
  ```
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v2.81.1
20
+ image: localhost/rockylinux9-underpost:v2.85.0
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-default-development-green
103
- image: localhost/rockylinux9-underpost:v2.81.1
103
+ image: localhost/rockylinux9-underpost:v2.85.0
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-test-development-blue
20
- image: localhost/rockylinux9-underpost:v2.81.1
20
+ image: localhost/rockylinux9-underpost:v2.85.0
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "96294Ki"
@@ -104,7 +104,7 @@ spec:
104
104
  spec:
105
105
  containers:
106
106
  - name: dd-test-development-green
107
- image: localhost/rockylinux9-underpost:v2.81.1
107
+ image: localhost/rockylinux9-underpost:v2.85.0
108
108
  # resources:
109
109
  # requests:
110
110
  # memory: "96294Ki"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.81.1",
5
+ "version": "2.85.0",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -18,7 +18,7 @@
18
18
  "proxy": "node src/proxy proxy",
19
19
  "docs": "jsdoc -c jsdoc.json",
20
20
  "install-global": "npm install -g pm2 && npm install -g jsdoc && npm install -g prettier && npm install -g env-cmd",
21
- "install-test": "npm install -g mocha && npm install -g c8 && npm install -g nyc && npm install -g coveralls",
21
+ "install-test": "npm install -g mocha && npm install -g c8 && npm install -g coveralls",
22
22
  "install-underpost": "cp -a $(npm root -g)/underpost/node_modules ./node_modules && npm install --only=dev --ignore-scripts",
23
23
  "install": "npm run install-global && npm run install-test",
24
24
  "prettier": "prettier --write .",
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+
5
+ # Script to install a recommended base package set on Rocky Linux.
6
+ # Usage examples:
7
+ # sudo ./scripts/rocky-setup.sh # interactive (will prompt about Development Tools)
8
+ # sudo ./scripts/rocky-setup.sh --install-dev # non-interactive: install Development Tools
9
+ # INSTALL_DEV=1 sudo ./scripts/rocky-setup.sh # same as --install-dev
10
+ # sudo ./scripts/rocky-setup.sh --yes # skip prompts and assume defaults
11
+
12
+ PACKAGES=(
13
+ dnf-plugins-core
14
+ epel-release
15
+ vim
16
+ nano
17
+ bash-completion
18
+ curl
19
+ wget
20
+ unzip
21
+ zip
22
+ tar
23
+ gzip
24
+ bzip2
25
+ rsync
26
+ git
27
+ python3
28
+ python3-pip
29
+ openssh-server
30
+ openssh-clients
31
+ firewalld
32
+ chrony
33
+ NetworkManager
34
+ which
35
+ net-tools
36
+ bind-utils
37
+ )
38
+
39
+ # Defaults
40
+ INSTALL_DEV=0
41
+ ASSUME_YES=0
42
+
43
+ # Parse CLI args (simple)
44
+ while [[ $# -gt 0 ]]; do
45
+ case "$1" in
46
+ --install-dev|--yes-dev)
47
+ INSTALL_DEV=1
48
+ shift
49
+ ;;
50
+ --no-install-dev)
51
+ INSTALL_DEV=0
52
+ shift
53
+ ;;
54
+ --yes|-y|--assume-yes)
55
+ ASSUME_YES=1
56
+ shift
57
+ ;;
58
+ --help|-h)
59
+ cat <<EOF
60
+ Usage: sudo ./scripts/rocky-setup.sh [options]
61
+
62
+ Options:
63
+ --install-dev, --yes-dev Install Development Tools group (gcc, make, etc.)
64
+ --no-install-dev Explicitly skip Development Tools
65
+ --yes, -y, --assume-yes Assume defaults / non-interactive
66
+ --help, -h Show this help and exit
67
+
68
+ You can also set the environment variable INSTALL_DEV=1 to enable development tools.
69
+ EOF
70
+ exit 0
71
+ ;;
72
+ *)
73
+ echo "Unknown argument: $1" >&2
74
+ exit 1
75
+ ;;
76
+ esac
77
+ done
78
+
79
+ # Environment variable overrides (if set)
80
+ if [[ "${INSTALL_DEV:-}" =~ ^(1|y|yes|true)$ ]]; then
81
+ INSTALL_DEV=1
82
+ fi
83
+
84
+ # Helper: prompt unless ASSUME_YES
85
+ prompt_install_dev() {
86
+ if [[ $ASSUME_YES -eq 1 ]]; then
87
+ return 1 # means do NOT prompt (we treat ASSUME_YES as 'no' for optional install unless INSTALL_DEV set)
88
+ fi
89
+
90
+ read -r -p "Do you want to install the 'Development Tools' group (gcc, make, etc.)? [y/N]: " answer
91
+ if [[ "${answer,,}" == "y" || "${answer,,}" == "yes" ]]; then
92
+ return 0
93
+ fi
94
+ return 1
95
+ }
96
+
97
+ # Refresh cache and install basic packages
98
+ echo "[+] Refreshing DNF cache..."
99
+ sudo dnf makecache --refresh
100
+
101
+ echo "[+] Installing dnf-plugins-core and epel-release (if not present)..."
102
+ sudo dnf -y install dnf-plugins-core epel-release
103
+
104
+ echo "[+] Refreshing DNF cache after enabling repositories..."
105
+ sudo dnf makecache --refresh
106
+
107
+ echo "[+] Installing base packages: ${#PACKAGES[@]} packages"
108
+ sudo dnf -y install "${PACKAGES[@]}"
109
+
110
+ # Decide on Development Tools
111
+ if [[ $INSTALL_DEV -eq 1 ]]; then
112
+ echo "[+] Installing Development Tools (requested)..."
113
+ sudo dnf -y groupinstall "Development Tools"
114
+ else
115
+ if prompt_install_dev; then
116
+ echo "[+] Installing Development Tools (prompt confirmed)..."
117
+ sudo dnf -y groupinstall "Development Tools"
118
+ else
119
+ echo "[+] Skipping Development Tools. To auto-enable, run with --install-dev or set INSTALL_DEV=1"
120
+ fi
121
+ fi
122
+
123
+ echo "[+] Updating all packages to latest versions..."
124
+ sudo dnf -y update
125
+
126
+ # Cleanup
127
+ echo "[+] Cleanup: remove unnecessary packages and old metadata"
128
+ sudo dnf -y autoremove || true
129
+ sudo dnf clean all || true
130
+
131
+ cat <<EOF
132
+
133
+ Installation complete.
134
+ - To allow SSH access (if this is a VM or server), open port 22 in firewalld:
135
+ sudo firewall-cmd --add-service=ssh --permanent && sudo firewall-cmd --reload
136
+ - If you installed Development Tools, you will have gcc, make, etc.
137
+
138
+ Examples:
139
+ sudo ./scripts/rocky-setup.sh --install-dev
140
+ INSTALL_DEV=1 sudo ./scripts/rocky-setup.sh
141
+ sudo ./scripts/rocky-setup.sh --yes
142
+
143
+ Customize PACKAGES=(...) inside this script according to your needs (docker, podman, kube, mssql-tools, etc.).
144
+ EOF
@@ -735,8 +735,11 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`,
735
735
  initHost() {
736
736
  const archData = UnderpostBaremetal.API.getHostArch();
737
737
  logger.info('Installing essential host-level prerequisites for Kubernetes...', archData);
738
+
739
+ // Install base rocky setup and updates
740
+ shellExec(`node bin run host-update`);
741
+
738
742
  // Install Docker and its dependencies
739
- shellExec(`sudo dnf -y install dnf-plugins-core dbus-x11`);
740
743
  shellExec(`sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo`);
741
744
  shellExec(`sudo dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin`);
742
745
 
package/src/cli/env.js CHANGED
@@ -56,9 +56,10 @@ class UnderpostRootEnv {
56
56
  * @param {string} value - The value of the environment variable to get.
57
57
  * @param {object} options - Options for getting the environment variable.
58
58
  * @param {boolean} [options.plain=false] - If true, returns the environment variable value as a string.
59
+ * @param {boolean} [options.disableLog=false] - If true, disables logging of the environment variable value.
59
60
  * @memberof UnderpostEnv
60
61
  */
61
- get(key, value, options = { plain: false }) {
62
+ get(key, value, options = { plain: false, disableLog: false }) {
62
63
  const exeRootPath = `${getNpmRootPath()}/underpost`;
63
64
  const envPath = `${exeRootPath}/.env`;
64
65
  if (!fs.existsSync(envPath)) {
@@ -66,7 +67,8 @@ class UnderpostRootEnv {
66
67
  return undefined;
67
68
  }
68
69
  const env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
69
- options?.plain === true ? console.log(env[key]) : logger.info(`${key}(${typeof env[key]})`, env[key]);
70
+ if (!options.disableLog)
71
+ options?.plain === true ? console.log(env[key]) : logger.info(`${key}(${typeof env[key]})`, env[key]);
70
72
  return env[key];
71
73
  },
72
74
  /**
package/src/cli/index.js CHANGED
@@ -68,10 +68,16 @@ program
68
68
  .argument(`[commit-type]`, `The type of commit to perform. Options: ${Object.keys(commitData).join(', ')}.`)
69
69
  .argument(`[module-tag]`, 'Optional: Sets a specific module tag for the commit.')
70
70
  .argument(`[message]`, 'Optional: Provides an additional custom message for the commit.')
71
- .option(`--log`, 'Shows commit history from the specified number of latest n path commits.')
71
+ .option(`--log <latest-n>`, 'Shows commit history from the specified number of latest n path commits.')
72
+ .option('--last-msg <latest-n>', 'Displays the last n commit message.')
72
73
  .option('--empty', 'Allows committing with empty files.')
73
74
  .option('--copy', 'Copies the generated commit message to the clipboard.')
74
75
  .option('--info', 'Displays information about available commit types.')
76
+ .option('--diff', 'Shows the current git diff changes.')
77
+ .option('--edit', 'Edit last commit.')
78
+ .option('--msg <msg>', 'Sets a custom commit message.')
79
+ .option('--deploy-id <deploy-id>', 'Sets the deployment configuration ID for the commit context.')
80
+ .option('--cached', 'Commit staged changes only or context.')
75
81
  .description('Manages commits to a GitHub repository, supporting various commit types and options.')
76
82
  .action(Underpost.repo.commit);
77
83
 
@@ -382,6 +388,7 @@ program
382
388
  .option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
383
389
  .option('--kubeadm', 'Flag to indicate Kubeadm cluster type context')
384
390
  .option('--k3s', 'Flag to indicate K3s cluster type context')
391
+ .option('--force', 'Forces operation, overriding any warnings or conflicts.')
385
392
  .description('Runs a script from the specified path.')
386
393
  .action(UnderpostRun.API.callback);
387
394
 
@@ -17,6 +17,8 @@ dotenv.config();
17
17
 
18
18
  const logger = loggerFactory(import.meta);
19
19
 
20
+ const diffCmd = `--no-pager show -U0 -w --word-diff=color --word-diff-regex='[^[:space:]]' --color=always`;
21
+
20
22
  /**
21
23
  * @class UnderpostRepository
22
24
  * @description Manages Git operations and configurations.
@@ -80,6 +82,13 @@ class UnderpostRepository {
80
82
  * @param {boolean} [options.copy=false] - If true, copies the commit message to the clipboard.
81
83
  * @param {boolean} [options.info=false] - If true, displays information about commit types.
82
84
  * @param {boolean} [options.empty=false] - If true, allows an empty commit.
85
+ * @param {boolean} [options.diff=false] - If true, shows the diff of the last commit.
86
+ * @param {boolean} [options.edit=false] - If true, amends the last commit without changing the message.
87
+ * @param {boolean} [options.cached=false] - If true, commits only staged changes.
88
+ * @param {number} [options.log=0] - If greater than 0, shows the last N commits with diffs.
89
+ * @param {boolean} [options.lastMsg=0] - If greater than 0, copies or show the last last single n commit message to clipboard.
90
+ * @param {string} [options.msg=''] - If provided, outputs this message instead of committing.
91
+ * @param {string} [options.deployId=''] - An optional deploy ID to include in the commit message.
83
92
  * @memberof UnderpostRepository
84
93
  */
85
94
  commit(
@@ -91,14 +100,41 @@ class UnderpostRepository {
91
100
  copy: false,
92
101
  info: false,
93
102
  empty: false,
94
- log: false,
103
+ diff: false,
104
+ edit: false,
105
+ cached: false,
106
+ lastMsg: 0,
107
+ log: 0,
108
+ msg: '',
109
+ deployId: '',
95
110
  },
96
111
  ) {
112
+ if (!repoPath) repoPath = '.';
113
+ if (options.msg) {
114
+ let key = Object.keys(commitData).find((k) => k && options.msg.toLocaleLowerCase().match(k));
115
+ if (!key) key == 'chore';
116
+ shellExec(
117
+ `underpost cmt ${repoPath} ${key} ${options.deployId ? options.deployId : `''`} '${options.msg.replaceAll(`${key}(${key}`, '')}'`,
118
+ );
119
+ return;
120
+ }
121
+ if (options.lastMsg) {
122
+ if (options.copy) {
123
+ pbcopy(UnderpostRepository.API.getLastCommitMsg(options.lastMsg - 1));
124
+ } else console.log(UnderpostRepository.API.getLastCommitMsg(options.lastMsg - 1));
125
+ return;
126
+ }
127
+ if (options.diff) {
128
+ const _diffCmd = `git ${diffCmd.replace('show', `diff${options.cached ? ` --cached` : ''}`)}`;
129
+ if (options.copy) pbcopy(_diffCmd);
130
+ else console.log('Diff command:', _diffCmd);
131
+ return;
132
+ }
97
133
  if (options.log) {
98
- const history = UnderpostRepository.API.getHistory(repoPath);
134
+ const history = UnderpostRepository.API.getHistory(options.log);
99
135
  const chainCmd = history
100
136
  .reverse()
101
- .map((commitData, i) => `${i === 0 ? '' : ' && '}git --no-pager show ${commitData.hash}`)
137
+ .map((commitData, i) => `${i === 0 ? '' : ' && '}git ${diffCmd} ${commitData.hash}`)
102
138
  .join('');
103
139
  if (history[0]) {
104
140
  for (const commit of history) {
@@ -117,7 +153,7 @@ class UnderpostRepository {
117
153
  return;
118
154
  }
119
155
  if (commitType === 'reset') {
120
- if (options.copy) pbcopy(shellExec(`git --no-pager log -1 --pretty=%B`, { stdout: true }));
156
+ if (options.copy) pbcopy(UnderpostRepository.API.getLastCommitMsg());
121
157
  shellExec(`cd ${repoPath} && git reset --soft HEAD~${isNaN(parseInt(subModule)) ? 1 : parseInt(subModule)}`);
122
158
  return;
123
159
  }
@@ -126,7 +162,18 @@ class UnderpostRepository {
126
162
  commitData[commitType].emoji
127
163
  } ${message ? message : commitData[commitType].description}`;
128
164
  if (options.copy) return pbcopy(_message);
129
- shellExec(`cd ${repoPath} && git commit ${options?.empty ? `--allow-empty ` : ''}-m "${_message}"`);
165
+ shellExec(
166
+ `cd ${repoPath} && git commit ${options?.empty ? `--allow-empty ` : ''}${options.edit ? `--amend --no-edit ` : `-m "${_message}"`}`,
167
+ );
168
+ },
169
+
170
+ /**
171
+ * Retrieves the message of the last Git commit.
172
+ * @returns {string} The last commit message.
173
+ * @memberof UnderpostRepository
174
+ */
175
+ getLastCommitMsg(skip = 0) {
176
+ return shellExec(`git --no-pager log -1 --skip=${skip} --pretty=%B`, { stdout: true });
130
177
  },
131
178
 
132
179
  /**
@@ -291,17 +338,25 @@ Prevent build private config repo.`,
291
338
  deployVersion: packageJsonDeploy.version,
292
339
  };
293
340
  },
294
- getHistory(sinceCommit = 5) {
295
- return shellExec(`git log --oneline --graph --decorate -n ${sinceCommit}`, {
341
+
342
+ /**
343
+ * Retrieves the Git commit history.
344
+ * @param {number} [sinceCommit=1] - The number of recent commits to retrieve.
345
+ * @returns {Array<{hash: string, message: string, files: string}>} An array of commit objects with hash, message, and files.
346
+ * @memberof UnderpostRepository
347
+ */
348
+ getHistory(sinceCommit = 1) {
349
+ return shellExec(`git log -1 --pretty=format:"%h %s" -n ${sinceCommit}`, {
296
350
  stdout: true,
297
351
  silent: true,
298
352
  disableLog: true,
299
353
  })
300
354
  .split(`\n`)
301
355
  .map((line) => {
356
+ const hash = line.split(' ')[0];
302
357
  return {
303
- hash: line.slice(2, 10),
304
- message: line.slice(11),
358
+ hash,
359
+ message: line.split(`${hash} `)[1],
305
360
  };
306
361
  })
307
362
  .filter((line) => line.hash)
package/src/cli/run.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
8
- import { getNpmRootPath, isDeployRunnerContext } from '../server/conf.js';
8
+ import { getNpmRootPath, getUnderpostRootPath, isDeployRunnerContext } from '../server/conf.js';
9
9
  import { actionInitLog, loggerFactory } from '../server/logger.js';
10
10
  import UnderpostTest from './test.js';
11
11
  import fs from 'fs-extra';
@@ -14,6 +14,7 @@ import UnderpostDeploy from './deploy.js';
14
14
  import UnderpostRootEnv from './env.js';
15
15
  import UnderpostRepository from './repository.js';
16
16
  import os from 'os';
17
+ import Underpost from '../index.js';
17
18
 
18
19
  const logger = loggerFactory(import.meta);
19
20
 
@@ -42,6 +43,7 @@ class UnderpostRun {
42
43
  * @property {number} replicas - The number of replicas to run.
43
44
  * @property {boolean} k3s - Whether to run in k3s mode.
44
45
  * @property {boolean} kubeadm - Whether to run in kubeadm mode.
46
+ * @property {boolean} force - Whether to force the operation.
45
47
  * @memberof UnderpostRun
46
48
  */
47
49
  static DEFAULT_OPTION = {
@@ -56,6 +58,7 @@ class UnderpostRun {
56
58
  replicas: 1,
57
59
  k3s: false,
58
60
  kubeadm: false,
61
+ force: false,
59
62
  };
60
63
  /**
61
64
  * @static
@@ -274,11 +277,29 @@ class UnderpostRun {
274
277
  'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
275
278
  const baseCommand = options.dev ? 'node bin' : 'underpost';
276
279
  shellExec(`${baseCommand} run clean`);
277
- shellExec(`${baseCommand} push ./engine-private ${process.env.GITHUB_USERNAME}/engine-private`);
280
+ shellExec(
281
+ `${baseCommand} push ./engine-private ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine-private`,
282
+ );
278
283
  shellCd('/home/dd/engine');
279
284
  shellExec(`git reset`);
280
- shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
281
- shellExec(`${baseCommand} push . ${process.env.GITHUB_USERNAME}/engine`);
285
+ shellExec(
286
+ `${baseCommand} cmt . --empty ci package-pwa-microservices-template${path.startsWith('sync') ? `-${path}` : ''}`,
287
+ );
288
+ shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
289
+ },
290
+
291
+ /**
292
+ * @method template-deploy-image
293
+ * @description Commits and pushes a Docker image deployment for the `engine` repository.
294
+ * @param {string} path - The input value, identifier, or path for the operation.
295
+ * @param {Object} options - The default underpost runner options for customizing workflow
296
+ * @memberof UnderpostRun
297
+ */
298
+ 'template-deploy-image': (path, options = UnderpostRun.DEFAULT_OPTION) => {
299
+ // const baseCommand = options.dev ? 'node bin' : 'underpost';
300
+ shellExec(
301
+ `cd /home/dd/engine && git reset && underpost cmt . --empty ci docker-image 'underpost-engine:${Underpost.version}' && underpost push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`,
302
+ );
282
303
  },
283
304
  /**
284
305
  * @method clean
@@ -333,18 +354,25 @@ class UnderpostRun {
333
354
  shellCd('/home/dd/engine');
334
355
  shellExec(`git reset`);
335
356
  shellExec(`${baseCommand} cmt . --empty cd ssh-${path}`);
336
- shellExec(`${baseCommand} push . ${process.env.GITHUB_USERNAME}/engine`);
357
+ shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
337
358
  },
338
359
  /**
339
360
  * @method ide
340
- * @description Opens a Visual Studio Code (VS Code) session for the specified path using `node ${underpostRoot}/bin/zed ${path}`.
361
+ * @description Opens a Visual Studio Code (VS Code) session for the specified path using `node ${underpostRoot}/bin/zed ${path}`,
362
+ * or installs Zed and sublime-text IDE if `path` is 'install'.
341
363
  * @param {string} path - The input value, identifier, or path for the operation (used as the path to the directory to open in the IDE).
342
364
  * @param {Object} options - The default underpost runner options for customizing workflow
343
365
  * @memberof UnderpostRun
344
366
  */
345
367
  ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
346
368
  const { underpostRoot } = options;
347
- shellExec(`node ${underpostRoot}/bin/zed ${path}`);
369
+ if (path === 'install') {
370
+ shellExec(`sudo curl -f https://zed.dev/install.sh | sh`);
371
+ shellExec(
372
+ `sudo dnf config-manager --add-repo https://download.sublimetext.com/rpm/stable/x86_64/sublime-text.repo`,
373
+ );
374
+ shellExec(`sudo dnf install -y sublime-text`);
375
+ } else shellExec(`node ${underpostRoot}/bin/zed ${path}`);
348
376
  },
349
377
  /**
350
378
  * @method sync
@@ -405,6 +433,20 @@ class UnderpostRun {
405
433
  'ls-deployments': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
406
434
  console.table(await UnderpostDeploy.API.get(path, 'deployments'));
407
435
  },
436
+
437
+ /**
438
+ * @method host-update
439
+ * @description Executes the `rocky-setup.sh` script to update the host system configuration.
440
+ * @param {string} path - The input value, identifier, or path for the operation.
441
+ * @param {Object} options - The default underpost runner options for customizing workflow
442
+ * @memberof UnderpostRun
443
+ */
444
+ 'host-update': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
445
+ // const baseCommand = options.dev ? 'node bin' : 'underpost';
446
+ shellExec(`chmod +x ${options.underpostRoot}/scripts/rocky-setup.sh`);
447
+ shellExec(`${options.underpostRoot}/scripts/rocky-setup.sh --yes${options.dev ? ' --install-dev' : ``}`);
448
+ },
449
+
408
450
  /**
409
451
  * @method monitor
410
452
  * @description Monitors a specific pod (identified by `path`) for the existence of a file (`/await`), and performs conditional actions (like file copying and opening Firefox) when the file is removed.
@@ -513,6 +555,40 @@ class UnderpostRun {
513
555
  shellExec(`underpost deploy --expose adminer`);
514
556
  }
515
557
  },
558
+
559
+ /**
560
+ * @method git-conf
561
+ * @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.
562
+ * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `username,email`).
563
+ * @param {Object} options - The default underpost runner options for customizing workflow
564
+ * @memberof UnderpostRun
565
+ */
566
+ 'git-conf': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
567
+ const defaultUsername = UnderpostRootEnv.API.get('GITHUB_USERNAME', '', { disableLog: true });
568
+ const defaultEmail = UnderpostRootEnv.API.get('GITHUB_EMAIL', '', { disableLog: true });
569
+ const [username, email] = path && path.split(',').length > 0 ? path.split(',') : [defaultUsername, defaultEmail];
570
+
571
+ shellExec(
572
+ `git config --global credential.helper "" && ` +
573
+ `git config credential.helper "" && ` +
574
+ `git config --global user.name '${username}' && ` +
575
+ `git config --global user.email '${email}' && ` +
576
+ `git config --global credential.interactive always && ` +
577
+ `git config user.name '${username}' && ` +
578
+ `git config user.email '${email}' && ` +
579
+ `git config credential.interactive always &&` +
580
+ `git config pull.rebase false`,
581
+ );
582
+
583
+ console.log(
584
+ shellExec(`git config list`, { silent: true, stdout: true })
585
+ .replaceAll('user.email', 'user.email'.yellow)
586
+ .replaceAll(username, username.green)
587
+ .replaceAll('user.name', 'user.name'.yellow)
588
+ .replaceAll(email, email.green),
589
+ );
590
+ },
591
+
516
592
  /**
517
593
  * @method promote
518
594
  * @description Switches traffic between blue/green deployments for a specified deployment ID(s) (uses `dd.router` for 'dd', or a specific ID).
@@ -797,15 +873,22 @@ EOF`;
797
873
  * @returns {Promise<any>} The result of the callback execution.
798
874
  */
799
875
  async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
800
- const npmRoot = getNpmRootPath();
801
- const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
802
- if (options.command) options.command = options.command.split(',');
803
- if (options.args) options.args = options.args.split(',');
804
- options.underpostRoot = underpostRoot;
805
- options.npmRoot = npmRoot;
806
- logger.info('callback', { path, options });
807
- const result = await UnderpostRun.RUNNERS[runner](path, options);
808
- return result;
876
+ try {
877
+ const npmRoot = getNpmRootPath();
878
+ const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
879
+ if (options.command) options.command = options.command.split(',');
880
+ if (options.args) options.args = options.args.split(',');
881
+ options.underpostRoot = underpostRoot;
882
+ options.npmRoot = npmRoot;
883
+ logger.info('callback', { path, options });
884
+ if (!(runner in UnderpostRun.RUNNERS)) throw new Error(`Runner not found: ${runner}`);
885
+ const result = await UnderpostRun.RUNNERS[runner](path, options);
886
+ return result;
887
+ } catch (error) {
888
+ console.log(error);
889
+ logger.error(error);
890
+ return null;
891
+ }
809
892
  },
810
893
  };
811
894
  }
@@ -118,7 +118,12 @@ const getQueryParams = () => {
118
118
  const sanitizeRoute = (route) =>
119
119
  !route || route === '/' || route === `\\`
120
120
  ? 'home'
121
- : route.toLowerCase().replaceAll('/', '').replaceAll(`\\`, '').replaceAll(' ', '-');
121
+ : route
122
+ .toLowerCase()
123
+ .replaceAll('/', '')
124
+ .replaceAll(`\\`, '')
125
+ .replaceAll(' ', '-')
126
+ .replaceAll(getProxyPath().replaceAll('/', ''), '');
122
127
 
123
128
  /**
124
129
  * Sets the document title and updates the active state of the main menu button corresponding to the route.
@@ -16,8 +16,10 @@ const getApiBasePath = (options) =>
16
16
  options?.proxyPath
17
17
  ? `/${options.proxyPath}/`
18
18
  : window.renderPayload?.apiBaseProxyPath
19
- ? window.renderPayload.apiBaseProxyPath
20
- : getProxyPath()
19
+ ? window.renderPayload.apiBaseProxyPath == '/'
20
+ ? window.renderPayload.apiBaseProxyPath
21
+ : `${window.renderPayload.apiBaseProxyPath}/`
22
+ : getProxyPath()
21
23
  }${window.renderPayload?.apiBasePath ? window.renderPayload.apiBasePath : 'api'}/`;
22
24
 
23
25
  const getApiBaseUrl = (options = { id: '', endpoint: '', proxyPath: '' }) =>
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ class Underpost {
35
35
  * @type {String}
36
36
  * @memberof Underpost
37
37
  */
38
- static version = 'v2.81.1';
38
+ static version = 'v2.85.0';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static