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/image.js CHANGED
@@ -5,9 +5,12 @@
5
5
  */
6
6
 
7
7
  import fs from 'fs-extra';
8
+ import os from 'os';
9
+ import nodePath from 'path';
10
+ import crypto from 'crypto';
8
11
  import { loggerFactory } from '../server/logger.js';
9
12
  import Underpost from '../index.js';
10
- import { getNpmRootPath, getUnderpostRootPath } from '../server/conf.js';
13
+ import { getNpmRootPath } from '../server/conf.js';
11
14
  import { shellExec } from '../server/process.js';
12
15
 
13
16
  const logger = loggerFactory(import.meta);
@@ -23,59 +26,32 @@ class UnderpostImage {
23
26
  static API = {
24
27
  /**
25
28
  * @method pullBaseImages
26
- * @description Pulls base images and builds a 'rockylinux9-underpost' image,
27
- * then loads it into the specified Kubernetes cluster type (Kind, Kubeadm, or K3s).
28
- * @param {object} options - Options for pulling and loading images.
29
- * @param {boolean} [options.kind=false] - If true, load image into Kind cluster.
30
- * @param {boolean} [options.kubeadm=false] - If true, load image into Kubeadm cluster.
31
- * @param {boolean} [options.k3s=false] - If true, load image into K3s cluster.
32
- * @param {string} [options.path=''] - Path to the Dockerfile context.
33
- * @param {boolean} [options.dev=false] - If true, use development mode.
34
- * @param {string} [options.version=''] - Version tag for the image.
35
- * @param {string} [options.imageName=''] - Custom name for the image.
29
+ * @description Ensures the base image prerequisites for the runtime Dockerfiles
30
+ * are present on the host (currently `docker.io/rockylinux/rockylinux:9`). This
31
+ * only pulls it does NOT build. Builds run with `podman build --pull=never`,
32
+ * so the base must exist locally beforehand; that is the sole purpose of this
33
+ * step. Combine with `--build` in the same command to pull-then-build.
36
34
  * @memberof UnderpostImage
37
35
  */
38
- pullBaseImages(
39
- options = {
40
- kind: false,
41
- kubeadm: false,
42
- k3s: false,
43
- path: '',
44
- dev: false,
45
- version: '',
46
- imageName: '',
47
- },
48
- ) {
49
- shellExec(`sudo podman pull docker.io/library/rockylinux:9`);
50
- const baseCommand = options.dev ? 'node bin' : 'underpost';
51
- const baseCommandOption = options.dev ? ' --dev' : '';
52
- const IMAGE_NAME = options.imageName
53
- ? `options.imageName${options.version ? `:${options.version}` : ''}`
54
- : `rockylinux9-underpost:${options.version ? options.version : Underpost.version}`;
55
- let LOAD_TYPE = '';
56
- if (options.kind === true) LOAD_TYPE = `--kind`;
57
- else if (options.kubeadm === true) LOAD_TYPE = `--kubeadm`;
58
- else if (options.k3s === true) LOAD_TYPE = `--k3s`;
59
- shellExec(
60
- `${baseCommand} image${baseCommandOption} --build --podman-save --reset --image-path=. --path ${
61
- options.path ? options.path : getUnderpostRootPath()
62
- } --image-name=${IMAGE_NAME} ${LOAD_TYPE}`,
63
- );
36
+ pullBaseImages() {
37
+ shellExec(`sudo podman pull docker.io/rockylinux/rockylinux:9`);
64
38
  },
65
39
  /**
66
40
  * @method build
67
41
  * @description Builds a Docker image using Podman, optionally saves it as a tar archive,
68
- * and loads it into a specified Kubernetes cluster (Kind, Kubeadm, or K3s).
42
+ * and loads it into a specified target (Kind, Kubeadm, or K3s cluster, or the local
43
+ * Docker store for Docker Compose).
69
44
  * @param {object} options - Options for building and loading images.
70
45
  * @param {string} [options.path=''] - The path to the directory containing the Dockerfile.
71
46
  * @param {string} [options.imageName=''] - The name and tag for the image (e.g., 'my-app:latest').
72
47
  * @param {string} [options.version=''] - Version tag for the image.
73
- * @param {string} [options.imagePath=''] - Directory to save the image tar file.
48
+ * @param {string} [options.imageOutPath=''] - Directory to save the image tar file.
74
49
  * @param {string} [options.dockerfileName=''] - Name of the Dockerfile (defaults to 'Dockerfile').
75
50
  * @param {boolean} [options.podmanSave=false] - If true, save the image as a tar archive using Podman.
76
51
  * @param {boolean} [options.kind=false] - If true, load the image archive into a Kind cluster.
77
52
  * @param {boolean} [options.kubeadm=false] - If true, load the image archive into a Kubeadm cluster (uses 'ctr').
78
53
  * @param {boolean} [options.k3s=false] - If true, load the image archive into a K3s cluster (uses 'k3s ctr').
54
+ * @param {boolean} [options.dockerCompose=false] - If true, load the image archive into the local Docker store for Docker Compose.
79
55
  * @param {boolean} [options.reset=false] - If true, perform a no-cache build.
80
56
  * @param {boolean} [options.dev=false] - If true, use development mode.
81
57
  * @memberof UnderpostImage
@@ -85,42 +61,144 @@ class UnderpostImage {
85
61
  path: '',
86
62
  imageName: '',
87
63
  version: '',
88
- imagePath: '',
64
+ imageOutPath: '',
89
65
  dockerfileName: '',
90
66
  podmanSave: false,
91
67
  kind: false,
92
68
  kubeadm: false,
93
69
  k3s: false,
70
+ dockerCompose: false,
94
71
  reset: false,
95
72
  dev: false,
96
73
  },
97
74
  ) {
98
- let { path, imageName, version, imagePath, dockerfileName, podmanSave, kind, kubeadm, k3s, reset, dev } = options;
75
+ let {
76
+ path,
77
+ imageName,
78
+ version,
79
+ imageOutPath,
80
+ dockerfileName,
81
+ podmanSave,
82
+ kind,
83
+ kubeadm,
84
+ k3s,
85
+ dockerCompose,
86
+ reset,
87
+ dev,
88
+ } = options;
99
89
  if (!path) path = '.';
100
90
  if (!imageName) imageName = `rockylinux9-underpost:${Underpost.version}`;
101
- if (!imagePath) imagePath = '.';
91
+ if (!imageOutPath) imageOutPath = '.';
102
92
  if (imageName.match('/')) imageName = imageName.split('/')[1];
103
93
  if (!version) version = 'latest';
104
94
  version = imageName && imageName.match(':') ? '' : `:${version}`;
105
95
  const podManImg = `localhost/${imageName}${version}`;
106
- if (imagePath && typeof imagePath === 'string' && !fs.existsSync(imagePath))
107
- fs.mkdirSync(imagePath, { recursive: true });
108
- const tarFile = `${imagePath}/${imageName.replace(':', '_')}.tar`;
96
+ if (imageOutPath && typeof imageOutPath === 'string' && !fs.existsSync(imageOutPath))
97
+ fs.mkdirSync(imageOutPath, { recursive: true });
98
+ const tarFile = `${imageOutPath}/${imageName.replace(':', '_')}.tar`;
109
99
  let cache = '';
110
100
  if (reset === true) cache += ' --rm --no-cache';
101
+
102
+ // Forward GitHub credentials from the host environment into the build as
103
+ // podman/BuildKit secrets (`--secret id=...,src=...`), matching the
104
+ // `RUN --mount=type=secret,id=github_*` contract in the runtime
105
+ // Dockerfiles (e.g. src/runtime/engine-cyberia). Secrets are written to
106
+ // short-lived 0600 temp files and removed right after the build — they are
107
+ // never passed as build-args (which would persist in image history) nor
108
+ // baked into any layer.
109
+ const secretTmpFiles = [];
110
+ const secretFlags = [];
111
+ const addBuildSecret = (id, value) => {
112
+ if (!value) return;
113
+ const file = nodePath.join(os.tmpdir(), `underpost-secret-${id}-${crypto.randomBytes(6).toString('hex')}`);
114
+ fs.writeFileSync(file, String(value), { mode: 0o600 });
115
+ secretTmpFiles.push(file);
116
+ secretFlags.push(`--secret id=${id},src=${file}`);
117
+ };
118
+ // addBuildSecret('github_token', process.env.GITHUB_TOKEN);
119
+ addBuildSecret('github_username', process.env.GITHUB_USERNAME);
120
+ // Cloudinary creds power build-time asset pulls (`node bin fs --pull`).
121
+ // addBuildSecret('cloudinary_cloud_name', process.env.CLOUDINARY_CLOUD_NAME);
122
+ // addBuildSecret('cloudinary_api_key', process.env.CLOUDINARY_API_KEY);
123
+ // addBuildSecret('cloudinary_api_secret', process.env.CLOUDINARY_API_SECRET);
124
+ const secretArgs = secretFlags.length ? ` ${secretFlags.join(' ')}` : '';
125
+ if (secretFlags.length)
126
+ logger.info('Passing host GitHub credentials as build secrets', { ids: secretFlags.length });
127
+
111
128
  if (path)
112
- shellExec(
113
- `cd ${path} && sudo podman build -f ./${
114
- dockerfileName && typeof dockerfileName === 'string' ? dockerfileName : 'Dockerfile'
115
- } -t ${imageName} --pull=never --cap-add=CAP_AUDIT_WRITE${cache} --network host`,
116
- );
117
- if (podmanSave === true) {
129
+ try {
130
+ shellExec(
131
+ `cd ${path} && sudo podman build -f ./${
132
+ dockerfileName && typeof dockerfileName === 'string' ? dockerfileName : 'Dockerfile'
133
+ } -t ${imageName} --pull=never --cap-add=CAP_AUDIT_WRITE${cache}${secretArgs} --network host`,
134
+ );
135
+ } finally {
136
+ for (const file of secretTmpFiles) {
137
+ try {
138
+ fs.removeSync(file);
139
+ } catch {
140
+ /* best-effort cleanup */
141
+ }
142
+ }
143
+ }
144
+ // Loading into any target requires the tar archive, so imply the save when
145
+ // one is set (kind/kubeadm/k3s/docker-compose) even if --podman-save was omitted.
146
+ const loadTarget = kind === true || kubeadm === true || k3s === true || dockerCompose === true;
147
+ if (podmanSave === true || loadTarget) {
118
148
  if (fs.existsSync(tarFile)) fs.removeSync(tarFile);
119
149
  shellExec(`podman save -o ${tarFile} ${podManImg}`);
120
150
  }
121
151
  if (kind === true) shellExec(`sudo kind load image-archive ${tarFile}`);
122
152
  else if (kubeadm === true) shellExec(`sudo ctr -n k8s.io images import ${tarFile}`);
123
153
  else if (k3s === true) shellExec(`sudo k3s ctr images import ${tarFile}`);
154
+ // Independent of any cluster target: make the local image available to the
155
+ // Docker daemon so `docker compose` can resolve it (e.g. ENGINE_CYBERIA_IMAGE).
156
+ if (dockerCompose === true) shellExec(`sudo docker load -i ${tarFile}`);
157
+ },
158
+ /**
159
+ * @method importTar
160
+ * @description Loads a pre-built image tar archive into each enabled target
161
+ * without building anything. Mirrors the load step of {@link build}, but
162
+ * the archive is supplied directly via `--import-tar <tar-path>` and every
163
+ * enabled target flag is honored (the same archive is loaded into each), so
164
+ * `--kind --docker-compose` loads it into both.
165
+ * @param {object} options - CLI options.
166
+ * @param {string} options.importTar - Path to the image tar archive (e.g. `./image-v1.0.0.tar`).
167
+ * @param {boolean} [options.kind] - Load into the Kind cluster (`kind load image-archive`).
168
+ * @param {boolean} [options.kubeadm] - Import into kubeadm containerd (`ctr -n k8s.io images import`).
169
+ * @param {boolean} [options.k3s] - Import into k3s containerd (`k3s ctr images import`).
170
+ * @param {boolean} [options.dockerCompose] - Load into the local Docker daemon (`docker load`) for Docker Compose.
171
+ * @returns {void}
172
+ * @memberof UnderpostImage
173
+ */
174
+ importTar(options = { importTar: '', kind: false, kubeadm: false, k3s: false, dockerCompose: false }) {
175
+ const { importTar, kind, kubeadm, k3s, dockerCompose } = options;
176
+ if (!importTar || typeof importTar !== 'string' || !fs.existsSync(importTar)) {
177
+ logger.error('image --import-tar: archive not found', { importTar });
178
+ return;
179
+ }
180
+ const targets = [];
181
+ if (kind === true) {
182
+ shellExec(`sudo kind load image-archive ${importTar}`);
183
+ targets.push('kind');
184
+ }
185
+ if (kubeadm === true) {
186
+ shellExec(`sudo ctr -n k8s.io images import ${importTar}`);
187
+ targets.push('kubeadm');
188
+ }
189
+ if (k3s === true) {
190
+ shellExec(`sudo k3s ctr images import ${importTar}`);
191
+ targets.push('k3s');
192
+ }
193
+ if (dockerCompose === true) {
194
+ shellExec(`sudo docker load -i ${importTar}`);
195
+ targets.push('docker-compose');
196
+ }
197
+ if (targets.length === 0)
198
+ logger.warn(
199
+ 'image --import-tar: no target enabled; combine with --kind, --kubeadm, --k3s and/or --docker-compose',
200
+ );
201
+ else logger.info('image --import-tar: archive loaded', { importTar, targets });
124
202
  },
125
203
  /**
126
204
  * @method getCurrentLoaded
package/src/cli/index.js CHANGED
@@ -110,16 +110,18 @@ program
110
110
  .option('--cached', 'Commit staged changes only or context.')
111
111
  .option('--hashes <hashes>', 'Comma-separated list of specific file hashes of commits.')
112
112
  .option('--extension <extension>', 'specific file extensions of commits.')
113
- .option(
114
- '--changelog [latest-n]',
115
- 'Print plain the changelog of the specified number of latest n commits, if no number is provided it will get the changelog to latest ci integration',
116
- )
113
+ .option('--changelog', 'Print the plain changelog of the last N commits (see --from-n-commit, default 1).')
117
114
  .option('--changelog-build', 'Builds a CHANGELOG.md file based on the commit history')
118
115
  .option('--changelog-min-version <version>', 'Sets the minimum version limit for --changelog-build (default: 2.85.0)')
119
116
  .option(
120
117
  '--changelog-no-hash',
121
118
  'Excludes commit hashes from the generated changelog entries (used with --changelog-build).',
122
119
  )
120
+ .option(
121
+ '--changelog-msg',
122
+ 'Print the sanitized, commit-ready changelog message of the last N commits (see --from-n-commit, default 1). Empty when there are no tagged entries.',
123
+ )
124
+ .option('--from-n-commit <n>', 'Number of latest commits to include in --changelog/--changelog-msg (default: 1).')
123
125
  .option('--unpush', 'With --log, automatically sets range to unpushed commits ahead of remote.')
124
126
  .option('-b', 'Shows the current Git branch name.')
125
127
  .option('-p [branch]', 'Shows the reflog for the specified branch.')
@@ -132,6 +134,12 @@ program
132
134
  '--has-changes',
133
135
  'Prints "1" if there are staged or unstaged git changes in the repository, empty string otherwise.',
134
136
  )
137
+ .option('--remote-url', 'Prints the current git remote URL (origin) in plain text.')
138
+ .option(
139
+ '--switch-repo <url>',
140
+ 'Switches the git remote (origin) to <url> and force-pulls the target branch, overwriting the current working tree (discards local commits and tracked changes). Accepts a full URL or "owner/repo".',
141
+ )
142
+ .option('--target-branch <branch>', 'Target branch for --switch-repo (default: master).')
135
143
  .description('Manages commits to a GitHub repository, supporting various commit types and options.')
136
144
  .action(Underpost.repo.commit);
137
145
 
@@ -330,6 +338,10 @@ program
330
338
  'Enables TLS in the Contour HTTPProxy virtualhost without requiring a production ClusterIssuer.',
331
339
  )
332
340
  .option('--node <node>', 'Sets optional node for deployment operations.')
341
+ .option(
342
+ '--ssh-key-path <path>',
343
+ 'Private key path for node SSH operations. Currently used when shipping a hostPath volume to a remote target node over SSH. Defaults to engine-private/deploy/id_rsa.',
344
+ )
333
345
  .option(
334
346
  '--build-manifest',
335
347
  'Builds Kubernetes YAML manifests, including deployments, services, proxies, and secrets.',
@@ -424,25 +436,31 @@ program
424
436
  .option('--rm <image-id>', 'Removes specified Underpost Dockerfile images.')
425
437
  .option('--path [path]', 'The path to the Dockerfile directory.')
426
438
  .option('--image-name [image-name]', 'Sets a custom name for the Docker image.')
427
- .option('--image-path [image-path]', 'Sets the output path for the tar image archive.')
439
+ .option('--image-out-path [image-out-path]', 'Sets the output path for the tar image archive.')
428
440
  .option('--dockerfile-name [dockerfile-name]', 'Sets a custom name for the Dockerfile.')
429
441
  .option('--podman-save', 'Exports the built image as a tar file using Podman.')
430
- .option('--pull-base', 'Pulls base images and builds a "rockylinux9-underpost" image.')
442
+ .option('--pull-base', 'Pulls the base image prerequisites (rockylinux:9) on the host; combine with --build.')
431
443
  .option('--spec', 'Get current cached list of container images used by all pods')
432
444
  .option('--namespace <namespace>', 'Kubernetes namespace for image operations (defaults to "default").')
433
445
  .option('--kind', 'Set kind cluster env image context management.')
434
446
  .option('--kubeadm', 'Set kubeadm cluster env image context management.')
435
447
  .option('--k3s', 'Set k3s cluster env image context management.')
448
+ .option('--docker-compose', 'Load the built image tar into the local Docker store for Docker Compose availability.')
436
449
  .option('--node-name', 'Set node name for kubeadm or k3s cluster env image context management.')
437
450
  .option('--reset', 'Performs a build without using the cache.')
438
451
  .option('--dev', 'Use development mode.')
439
452
  .option('--pull-dockerhub <dockerhub-image>', 'Sets a custom Docker Hub image for base image pulls.')
453
+ .option(
454
+ '--import-tar <tar-path>',
455
+ 'Load a pre-built image tar archive (e.g. ./image-v1.0.0.tar) into the enabled target(s) without building. Combine with --kind, --kubeadm, --k3s and/or --docker-compose; the archive is loaded into each enabled one.',
456
+ )
440
457
  .description('Manages Docker images, including building, saving, and loading into Kubernetes clusters.')
441
458
  .action(async (options) => {
442
459
  if (options.rm) Underpost.image.rm({ ...options, imageName: options.rm });
443
460
  if (options.ls) Underpost.image.list({ ...options, log: true });
444
461
  if (options.pullBase) Underpost.image.pullBaseImages(options);
445
462
  if (options.build) Underpost.image.build(options);
463
+ if (options.importTar) Underpost.image.importTar(options);
446
464
  if (options.pullDockerhub)
447
465
  Underpost.image.pullDockerHubImage({ ...options, dockerhubImage: options.pullDockerhub });
448
466
  });
@@ -630,6 +648,10 @@ program
630
648
  .option('--replicas <replicas>', 'Sets a custom number of replicas for deployment.')
631
649
  .option('--pod-name <pod-name>', 'Optional: Specifies the pod name for execution.')
632
650
  .option('--node-name <node-name>', 'Optional: Specifies the node name for execution.')
651
+ .option(
652
+ '--ssh-key-path <path>',
653
+ 'Optional: Private key path for node SSH operations, forwarded to volume shipping over SSH. Defaults to engine-private/deploy/id_rsa.',
654
+ )
633
655
  .option('--port <port>', 'Optional: Specifies the port for execution.')
634
656
  .option('--etc-hosts', 'Enables etc-hosts context for the runner execution.')
635
657
  .option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
@@ -678,6 +700,7 @@ program
678
700
  .option('--kubeadm', 'Sets the kubeadm cluster context for the runner execution.')
679
701
  .option('--k3s', 'Sets the k3s cluster context for the runner execution.')
680
702
  .option('--kind', 'Sets the kind cluster context for the runner execution.')
703
+ .option('--traffic <traffic>', 'Blue/green traffic colour to bake into generated manifests (default: blue).')
681
704
  .option('--git-clean', 'Runs git clean on volume mount paths before copying.')
682
705
  .option('--deploy-id <deploy-id>', 'Sets deploy id context for the runner execution.')
683
706
  .option('--user <user>', 'Sets user context for the runner execution.')
@@ -751,6 +774,12 @@ program
751
774
  '--deploy-id <deploy-id>',
752
775
  "Deployment to run as the app container (default: dd-default). 'dd-default' self-bootstraps a fresh engine; any other id runs the standard 'underpost start' command (mirrors src/cli/deploy.js).",
753
776
  )
777
+ .option(
778
+ '--docker-compose-id <docker-compose-id>',
779
+ 'Selects a canonical custom-workflow stack at engine-private/conf/<deploy-id>/docker-compose/<docker-compose-id>/ ' +
780
+ '(docker-compose.yml + compose.env + nginx.conf, used as-is; nginx/env generation is skipped). ' +
781
+ 'e.g. --deploy-id dd-cyberia --docker-compose-id cyberia for the Cyberia MMO ecosystem.',
782
+ )
754
783
  .option('--env <env>', 'Deployment environment for non-default deploy ids (default: development).')
755
784
  .option('--generate', 'Render dynamic supporting files (nginx router config, env-file, app-command override).')
756
785
  .option('--up', 'Start the full stack detached (regenerates config first).')
@@ -117,9 +117,53 @@ const buildVersionBumpTargets = () => [
117
117
  /(underpost-engine:v)\d+\.\d+\.\d+/g,
118
118
  /(type=raw,value=v)\d+\.\d+\.\d+/g,
119
119
  /(UNDERPOST_VERSION=)\d+\.\d+\.\d+/g,
120
+ /(UNDERPOST_VERSION:\s*['"]?)\d+\.\d+\.\d+/g,
120
121
  ],
121
122
  },
122
123
 
124
+ // ── Docker-compose image-tag defaults. Root compose + generator + cyberia runtime compose.
125
+ // Tags live in `${VAR:-vX.Y.Z}` / `VAR=vX.Y.Z` shapes bumpp cannot detect. ──
126
+ {
127
+ file: 'docker-compose.yml',
128
+ patterns: /(_TAG:-v)\d+\.\d+\.\d+/g,
129
+ },
130
+ {
131
+ file: 'src/cli/docker-compose.js',
132
+ patterns: /(_TAG=v)\d+\.\d+\.\d+/g,
133
+ },
134
+ {
135
+ file: 'src/runtime/engine-cyberia/docker-compose.yml',
136
+ patterns: /(_TAG:-v)\d+\.\d+\.\d+/g,
137
+ },
138
+
139
+ // ── Cyberia CLI dev image tar/name defaults (bin/cyberia.js). ──
140
+ {
141
+ file: 'bin/cyberia.js',
142
+ patterns: [/(-dev_v)\d+\.\d+\.\d+(?=\.tar)/g, /(-dev:v)\d+\.\d+\.\d+/g],
143
+ },
144
+
145
+ // ── Runtime Dockerfiles: `ARG UNDERPOST_VERSION=X.Y.Z` build-arg defaults. ──
146
+ {
147
+ dir: 'src/runtime',
148
+ match: /^Dockerfile(\.\w+)?$/,
149
+ patterns: /(ARG UNDERPOST_VERSION=)\d+\.\d+\.\d+/g,
150
+ recursive: true,
151
+ },
152
+
153
+ // ── Runtime compose.env shipped tag defaults ──
154
+ {
155
+ dir: 'src/runtime',
156
+ match: /^compose\.env$/,
157
+ patterns: /(_TAG=v)\d+\.\d+\.\d+/g,
158
+ recursive: true,
159
+ },
160
+
161
+ // ── Deploy-monitor smoke-test image default (scripts/test-monitor.sh). ──
162
+ {
163
+ file: 'scripts/test-monitor.sh',
164
+ patterns: /(underpost\/[a-z0-9-]+:v)\d+\.\d+\.\d+/g,
165
+ },
166
+
123
167
  // ── engine-private confs (gitignored — bumped only if present). ──
124
168
  {
125
169
  dir: 'engine-private/conf',
@@ -448,11 +492,10 @@ class UnderpostRelease {
448
492
  let commitMsg = message;
449
493
  if (!commitMsg) {
450
494
  shellCd('/home/dd/engine');
451
- const rawMsg = shellExec(`node bin cmt --changelog 1 --changelog-no-hash`, {
495
+ commitMsg = shellExec(`node bin cmt --changelog-msg --changelog-no-hash`, {
452
496
  stdout: true,
453
497
  silent: true,
454
498
  }).trim();
455
- commitMsg = Underpost.repo.sanitizeChangelogMessage(rawMsg);
456
499
  shellCd('/home/dd');
457
500
  }
458
501
  commitMsg = (commitMsg || '').trim() || `Update ${repoName} repository`;
@@ -492,11 +535,10 @@ class UnderpostRelease {
492
535
  let commitMsg = message;
493
536
  if (!commitMsg) {
494
537
  shellCd('/home/dd/engine');
495
- const rawMsg = shellExec(`node bin cmt --changelog 1 --changelog-no-hash`, {
538
+ commitMsg = shellExec(`node bin cmt --changelog-msg --changelog-no-hash`, {
496
539
  stdout: true,
497
540
  silent: true,
498
541
  }).trim();
499
- commitMsg = Underpost.repo.sanitizeChangelogMessage(rawMsg);
500
542
  }
501
543
  commitMsg = (commitMsg || '').trim() || `Update pwa-microservices-template repository`;
502
544
  shellCd('/home/dd');