underpost 3.2.80 → 3.3.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.
Files changed (84) hide show
  1. package/.github/workflows/ghpkg.ci.yml +7 -1
  2. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
  3. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  4. package/.github/workflows/release.cd.yml +1 -9
  5. package/CHANGELOG.md +291 -1
  6. package/CLI-HELP.md +174 -23
  7. package/README.md +5 -2
  8. package/bin/build.js +7 -5
  9. package/bin/deploy.js +19 -17
  10. package/deploy/lib/logging.sh +96 -0
  11. package/deploy/pwa-microservices-template/deploy.sh +72 -0
  12. package/deploy/release/deploy.sh +62 -0
  13. package/docker-compose.yml +1 -1
  14. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -1
  15. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  16. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +52 -0
  17. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  18. package/manifests/deployment/playwright/deployment.yaml +1 -1
  19. package/manifests/mongodb/kustomization.yaml +4 -1
  20. package/manifests/mongodb/statefulset.yaml +4 -0
  21. package/manifests/mongodb/storage-class.yaml +9 -2
  22. package/package.json +19 -19
  23. package/scripts/audit-selinux.sh +64 -0
  24. package/scripts/coverall-test.sh +24 -0
  25. package/scripts/gpu-diag.sh +0 -0
  26. package/scripts/ip-info.sh +0 -0
  27. package/scripts/k3s-node-setup.sh +18 -15
  28. package/scripts/kubeadm-node-setup.sh +12 -23
  29. package/scripts/link-local-underpost-cli.sh +0 -0
  30. package/scripts/lxd-vm-setup.sh +0 -0
  31. package/scripts/maas-nat-firewalld.sh +0 -0
  32. package/scripts/nat-iptables.sh +12 -4
  33. package/scripts/rhel-grpc-setup.sh +0 -0
  34. package/scripts/rocky-kickstart.sh +25 -9
  35. package/scripts/test-monitor.sh +4 -3
  36. package/src/cli/baremetal.js +1 -2
  37. package/src/cli/cloud-init.js +1 -1
  38. package/src/cli/cluster.js +786 -96
  39. package/src/cli/db.js +11 -4
  40. package/src/cli/deploy.js +1698 -177
  41. package/src/cli/docker-compose.js +19 -178
  42. package/src/cli/env.js +1 -1
  43. package/src/cli/image.js +15 -7
  44. package/src/cli/index.js +245 -44
  45. package/src/cli/ipfs.js +82 -11
  46. package/src/cli/lxd.js +1 -1
  47. package/src/cli/monitor.js +2 -2
  48. package/src/cli/release.js +57 -22
  49. package/src/cli/repository.js +12 -10
  50. package/src/cli/run.js +2195 -427
  51. package/src/cli/secrets.js +969 -0
  52. package/src/cli/ssh.js +206 -105
  53. package/src/cli/system.js +26 -13
  54. package/src/cli/test.js +1 -1
  55. package/src/cli/vultr.js +583 -0
  56. package/src/cli/wireguard.js +2125 -0
  57. package/src/client-builder/client-build.js +102 -13
  58. package/src/client-builder/ssr.js +27 -73
  59. package/src/db/mongo/MongoBootstrap.js +295 -54
  60. package/src/db/mongo/MongooseDB.js +51 -32
  61. package/src/index.js +25 -1
  62. package/src/projects/underpost/catalog-underpost.js +4 -1
  63. package/src/server/backup.js +1 -1
  64. package/src/server/conf.js +1216 -168
  65. package/src/server/cri.js +70 -0
  66. package/src/server/cron.js +249 -51
  67. package/src/server/dns.js +100 -6
  68. package/src/server/environment.js +98 -0
  69. package/src/server/forward-proxy.js +549 -0
  70. package/src/server/middlewares.js +56 -1
  71. package/src/server/process.js +0 -1
  72. package/src/server/selinux.js +185 -0
  73. package/src/server/systemd.js +205 -0
  74. package/src/server/underpost-compression.js +186 -0
  75. package/src/server/underpost-gateway.js +1083 -0
  76. package/src/server/underpost-ingress.js +380 -0
  77. package/test/cluster-instances.test.js +435 -0
  78. package/test/deploy-node-placement.test.js +45 -0
  79. package/test/instance-traffic-plan.test.js +710 -0
  80. package/test/selinux.test.js +71 -0
  81. package/test/sops-secret-store.test.js +612 -0
  82. package/test/underpost-gateway.test.js +510 -0
  83. package/test/underpost-ingress.test.js +305 -0
  84. package/test/wireguard-edge.test.js +1177 -0
@@ -56,6 +56,10 @@ const buildVersionBumpTargets = () => [
56
56
  file: 'src/index.js',
57
57
  patterns: /(static version = ['"]v)\d+\.\d+\.\d+(?=['"])/g,
58
58
  },
59
+ {
60
+ file: 'src/cli/run.js',
61
+ patterns: /(const version = ['"]v)\d+\.\d+\.\d+(?=['"])/g,
62
+ },
59
63
 
60
64
  // ── README + CLI-HELP fallbacks. CLI-HELP is regenerated by `deploy cli-docs`, but bump
61
65
  // it too so the file is consistent if the regeneration step is skipped. ──
@@ -107,6 +111,14 @@ const buildVersionBumpTargets = () => [
107
111
  recursive: true,
108
112
  },
109
113
 
114
+ // ── Deployment runner scripts carry image defaults passed to deploy/sync commands. ──
115
+ {
116
+ dir: 'deploy',
117
+ match: /\.sh$/,
118
+ patterns: /(underpost\/[a-z0-9-]+:v)\d+\.\d+\.\d+/g,
119
+ recursive: true,
120
+ },
121
+
110
122
  // ── GitHub Actions workflows. Single sweep across docker-image.*.ci.yml, engine-*.cd.yml,
111
123
  // and the root docker-image.ci.yml — replaces previous three separate loops. ──
112
124
  {
@@ -261,6 +273,19 @@ const bumpAuxiliaryFiles = (oldVersion, newVersion, { dryRun = false } = {}) =>
261
273
  return report;
262
274
  };
263
275
 
276
+ /**
277
+ * Returns whether a manifest's canonical top-level version would change. Used by dry-runs
278
+ * because bumpp has no non-mutating API option.
279
+ */
280
+ const wouldBumpManifestVersion = (filePath, newVersion) => {
281
+ try {
282
+ const manifest = JSON.parse(fs.readFileSync(filePath, 'utf8'));
283
+ return typeof manifest.version === 'string' && manifest.version !== newVersion;
284
+ } catch {
285
+ return false;
286
+ }
287
+ };
288
+
264
289
  /**
265
290
  * Prints a per-file change summary table.
266
291
  */
@@ -379,8 +404,8 @@ class UnderpostRelease {
379
404
  * 1. Loads production env and pulls latest code; kills dev servers on ports 4001-4003.
380
405
  * 2. Builds and smoke-tests the pwa-microservices-template (aborts on error).
381
406
  * 3. Canonical version files: delegates to `bumpp` (driven by `bump.config.js`). Bumps
382
- * package.json, package-lock.json (root + packages['']), and every
383
- * engine-private/conf/**\/package.json.
407
+ * package.json, package-lock.json (root + packages['']), Hardhat's package metadata,
408
+ * and every engine-private/conf/**\/package.json.
384
409
  * 4. Auxiliary files: anchored-regex walker over VERSION_BUMP_TARGETS — covers
385
410
  * src/index.js, README, cyberia-docs, nexodev docs, manifests (deployment + cronjobs),
386
411
  * .github/workflows (image tags, type=raw, UNDERPOST_VERSION build-args), and
@@ -420,26 +445,36 @@ class UnderpostRelease {
420
445
  if (!templateOk) return;
421
446
  }
422
447
 
423
- // ── Canonical version files: delegate to bumpp (package.json, package-lock.json,
424
- // engine-private/conf/**/package.json). bumpp owns lockfile semantics (root version
425
- // + packages[''].version) so we don't reimplement them. ──
426
- const { versionBump } = await import('bumpp');
427
- const bumppResult = await versionBump({
428
- release: newVersion,
429
- files: [
430
- 'package.json',
431
- 'package-lock.json',
432
- ...(fs.existsSync('./engine-private/conf') ? ['engine-private/conf/**/package.json'] : []),
433
- ],
434
- commit: false,
435
- tag: false,
436
- push: false,
437
- confirm: false,
438
- recursive: false,
439
- ignoreScripts: true,
440
- dry: dryRun,
441
- });
442
- logger.info(`bumpp updated ${bumppResult?.files?.length ?? 0} canonical file(s).`);
448
+ // ── Canonical version files: bumpp owns lockfile semantics (root version +
449
+ // packages[''].version). Its API has no non-mutating dry-run, so previews inspect
450
+ // manifest versions directly rather than invoking it. ──
451
+ const canonicalVersionFiles = [
452
+ 'package.json',
453
+ 'package-lock.json',
454
+ 'hardhat/package.json',
455
+ 'hardhat/package-lock.json',
456
+ ...walkDir('engine-private/conf', /^package\.json$/, true),
457
+ ];
458
+ if (dryRun) {
459
+ const pendingCanonicalFiles = canonicalVersionFiles.filter((file) =>
460
+ wouldBumpManifestVersion(file, newVersion),
461
+ );
462
+ logger.info(`bumpp would update ${pendingCanonicalFiles.length} canonical file(s).`);
463
+ for (const file of pendingCanonicalFiles) console.log(` ${file}`);
464
+ } else {
465
+ const { versionBump } = await import('bumpp');
466
+ const bumppResult = await versionBump({
467
+ release: newVersion,
468
+ files: canonicalVersionFiles,
469
+ commit: false,
470
+ tag: false,
471
+ push: false,
472
+ confirm: false,
473
+ recursive: false,
474
+ ignoreScripts: true,
475
+ });
476
+ logger.info(`bumpp updated ${bumppResult?.updatedFiles?.length ?? 0} canonical file(s).`);
477
+ }
443
478
 
444
479
  // ── Auxiliary files: anchored-regex walker over VERSION_BUMP_TARGETS. ──
445
480
  const report = bumpAuxiliaryFiles(version, newVersion, { dryRun });
@@ -11,7 +11,6 @@ import { actionInitLog, loggerFactory } from '../server/logger.js';
11
11
  import path from 'path';
12
12
  import fs from 'fs-extra';
13
13
  import {
14
- getNpmRootPath,
15
14
  Config,
16
15
  loadConf,
17
16
  readConfJson,
@@ -20,9 +19,9 @@ import {
20
19
  loadConfServerJson,
21
20
  getDataDeploy,
22
21
  buildReplicaId,
23
- writeEnv,
24
22
  readConfInstances,
25
23
  } from '../server/conf.js';
24
+ import { getNpmRootPath, writeEnv } from '../server/environment.js';
26
25
  import { buildClient, unzipClientBuild, mergeClientBuildZip } from '../client-builder/client-build.js';
27
26
  import { DefaultConf } from '../../conf.js';
28
27
  import Underpost from '../index.js';
@@ -109,7 +108,7 @@ class UnderpostRepository {
109
108
  * @param {boolean} [options.changelogNoHash=false] - If true, omits commit hashes from the changelog entries.
110
109
  * @param {boolean} [options.remoteUrl=false] - If true, prints the current git remote URL (origin) in plain text and returns.
111
110
  * @param {string} [options.switchRepo=''] - If set, switches the remote `origin` to this URL and force-pulls the target branch, overwriting the current working tree.
112
- * @param {string} [options.targetBranch=''] - Target branch for `switchRepo` (defaults to `master`).
111
+ * @param {string} [options.targetBranch=''] - Target branch for `switchRepo` (defaults to the remote's default branch).
113
112
  * @memberof UnderpostRepository
114
113
  */
115
114
  commit(
@@ -181,7 +180,7 @@ class UnderpostRepository {
181
180
  Underpost.repo.switchRemote({
182
181
  path: repoPath,
183
182
  url: options.switchRepo,
184
- branch: options.targetBranch || 'master',
183
+ branch: options.targetBranch,
185
184
  });
186
185
  return;
187
186
  }
@@ -906,6 +905,7 @@ class UnderpostRepository {
906
905
  split: options.split || '',
907
906
  fullBuild: options.liteBuild ? false : true,
908
907
  iconsBuild: options.iconsBuild || false,
908
+ ssrOnly: options.ssr || false,
909
909
  });
910
910
  for (const replicaDeployId of deployIdSingleReplicas) {
911
911
  if (!fs.existsSync(`./engine-private/replica/${replicaDeployId}`)) {
@@ -917,6 +917,7 @@ class UnderpostRepository {
917
917
  split: options.split || '',
918
918
  liteBuild: options.liteBuild || false,
919
919
  iconsBuild: options.iconsBuild || false,
920
+ ssr: options.ssr || false,
920
921
  });
921
922
  }
922
923
 
@@ -1428,14 +1429,15 @@ Prevent build private config repo.`,
1428
1429
  * @param {object} opts
1429
1430
  * @param {string} opts.url - New remote URL (full URL or "owner/repo" short form).
1430
1431
  * @param {string} [opts.path='.'] - Path to the git repository.
1431
- * @param {string} [opts.branch='master'] - Target branch to overwrite the current tree with.
1432
+ * @param {string} [opts.branch] - Target branch to overwrite the current tree with. Defaults to the remote's default branch.
1432
1433
  * @param {string} [opts.remote='origin'] - Remote name to set and fetch from.
1433
1434
  * @returns {void}
1434
1435
  * @memberof UnderpostRepository
1435
1436
  */
1436
- switchRemote({ url, path: repoPath = '.', branch = 'master', remote = 'origin' }) {
1437
+ switchRemote({ url, path: repoPath = '.', branch = '', remote = 'origin' }) {
1437
1438
  if (!url) throw new Error('switchRemote requires a target remote url');
1438
1439
  if (!fs.existsSync(`${repoPath}/.git`)) throw new Error(`switchRemote: not a git repository: ${repoPath}`);
1440
+ const targetBranch = branch || Underpost.repo.getDefaultBranch(url);
1439
1441
  // Token-free URL for the stored remote; auth-injected URL only for the fetch.
1440
1442
  let normalized = url;
1441
1443
  if (!url.startsWith('http://') && !url.startsWith('https://') && !url.startsWith('git@')) {
@@ -1445,12 +1447,12 @@ Prevent build private config repo.`,
1445
1447
  const current = Underpost.repo.getRemoteUrl({ path: repoPath, remote });
1446
1448
  if (!current) shellExec(`cd "${repoPath}" && git remote add ${remote} "${normalized}"`);
1447
1449
  else shellExec(`cd "${repoPath}" && git remote set-url ${remote} "${normalized}"`);
1448
- logger.info('switchRemote', { path: repoPath, remote, branch, url: normalized });
1449
- shellExec(`cd "${repoPath}" && GIT_TERMINAL_PROMPT=0 git fetch --force "${authUrl}" ${branch}`);
1450
+ logger.info('switchRemote', { path: repoPath, remote, branch: targetBranch, url: normalized });
1451
+ shellExec(`cd "${repoPath}" && GIT_TERMINAL_PROMPT=0 git fetch --force "${authUrl}" ${targetBranch}`);
1450
1452
  // reset --hard first clears the worktree so the checkout cannot be blocked
1451
1453
  // by conflicting local changes; -B points the target branch at the fetched tip.
1452
1454
  shellExec(`cd "${repoPath}" && git reset --hard FETCH_HEAD`);
1453
- shellExec(`cd "${repoPath}" && git checkout -B ${branch} FETCH_HEAD`);
1455
+ shellExec(`cd "${repoPath}" && git checkout -B ${targetBranch} FETCH_HEAD`);
1454
1456
  },
1455
1457
 
1456
1458
  /**
@@ -1706,7 +1708,7 @@ Prevent build private config repo.`,
1706
1708
  }
1707
1709
 
1708
1710
  // Resolve the active blue/green traffic colour so we target the correct pod
1709
- const traffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace });
1711
+ const traffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace, env });
1710
1712
  if (!traffic) {
1711
1713
  logger.warn(`backupPodRepositories: could not resolve current traffic for ${deployId} — skipping`);
1712
1714
  return;