cyberia 3.2.9 → 3.2.22
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/.github/workflows/engine-cyberia.cd.yml +7 -0
- package/.github/workflows/engine-cyberia.ci.yml +14 -2
- package/.github/workflows/ghpkg.ci.yml +1 -0
- package/.github/workflows/npmpkg.ci.yml +10 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.github/workflows/release.cd.yml +1 -0
- package/.vscode/extensions.json +9 -9
- package/.vscode/settings.json +20 -4
- package/CHANGELOG.md +363 -1
- package/CLI-HELP.md +975 -1061
- package/README.md +190 -348
- package/bin/build.js +102 -125
- package/bin/build.template.js +33 -0
- package/bin/cyberia.js +238 -56
- package/bin/deploy.js +16 -3
- package/bin/index.js +238 -56
- package/bump.config.js +26 -0
- package/conf.js +131 -24
- package/deployment.yaml +76 -2
- package/hardhat/package-lock.json +113 -144
- package/hardhat/package.json +4 -3
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +2 -2
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +76 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/kind-config-dev.yaml +8 -0
- package/manifests/lxd/lxd-admin-profile.yaml +12 -3
- package/manifests/mongodb/pv-pvc.yaml +44 -8
- package/manifests/mongodb/statefulset.yaml +55 -68
- package/manifests/mongodb-4.4/headless-service.yaml +10 -0
- package/manifests/mongodb-4.4/kustomization.yaml +3 -1
- package/manifests/mongodb-4.4/mongodb-nodeport.yaml +17 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +10 -14
- package/manifests/mongodb-4.4/statefulset.yaml +79 -0
- package/manifests/mongodb-4.4/storage-class.yaml +9 -0
- package/manifests/valkey/statefulset.yaml +1 -1
- package/manifests/valkey/valkey-nodeport.yaml +17 -0
- package/package.json +31 -19
- package/scripts/ipxe-setup.sh +52 -49
- package/scripts/k3s-node-setup.sh +81 -46
- package/scripts/link-local-underpost-cli.sh +6 -0
- package/scripts/lxd-vm-setup.sh +193 -8
- package/scripts/maas-nat-firewalld.sh +145 -0
- package/scripts/test-monitor.sh +250 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +38 -33
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +16 -16
- package/src/api/core/core.router.js +19 -14
- package/src/api/core/core.service.js +5 -5
- package/src/api/crypto/crypto.router.js +18 -12
- package/src/api/crypto/crypto.service.js +3 -3
- package/src/api/cyberia-action/cyberia-action.model.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +22 -18
- package/src/api/cyberia-action/cyberia-action.service.js +5 -5
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +74 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +99 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +98 -0
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +152 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +25 -20
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +6 -6
- package/src/api/cyberia-entity/cyberia-entity.router.js +22 -18
- package/src/api/cyberia-entity/cyberia-entity.service.js +5 -5
- package/src/api/cyberia-instance/cyberia-fallback-world.js +79 -4
- package/src/api/cyberia-instance/cyberia-instance.router.js +57 -52
- package/src/api/cyberia-instance/cyberia-instance.service.js +10 -10
- package/src/api/cyberia-instance/cyberia-world-generator.js +3 -3
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +14 -48
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +22 -18
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +5 -5
- package/src/api/cyberia-map/cyberia-map.router.js +35 -30
- package/src/api/cyberia-map/cyberia-map.service.js +7 -7
- package/src/api/cyberia-quest/cyberia-quest.model.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +22 -18
- package/src/api/cyberia-quest/cyberia-quest.service.js +5 -5
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +22 -18
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +5 -5
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +458 -0
- package/src/api/default/default.router.js +22 -18
- package/src/api/default/default.service.js +5 -5
- package/src/api/document/document.router.js +28 -23
- package/src/api/document/document.service.js +100 -23
- package/src/api/file/file.router.js +19 -13
- package/src/api/file/file.service.js +9 -7
- package/src/api/instance/instance.router.js +29 -24
- package/src/api/instance/instance.service.js +6 -6
- package/src/api/ipfs/ipfs.router.js +21 -16
- package/src/api/ipfs/ipfs.service.js +8 -8
- package/src/api/object-layer/object-layer.router.js +512 -507
- package/src/api/object-layer/object-layer.service.js +17 -14
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +22 -18
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +5 -5
- package/src/api/test/test.router.js +17 -12
- package/src/api/types.js +24 -0
- package/src/api/user/guest.service.js +5 -4
- package/src/api/user/user.router.js +297 -288
- package/src/api/user/user.service.js +100 -35
- package/src/cli/baremetal.js +132 -101
- package/src/cli/cluster.js +700 -232
- package/src/cli/db.js +59 -60
- package/src/cli/deploy.js +291 -294
- package/src/cli/env.js +1 -4
- package/src/cli/fs.js +13 -3
- package/src/cli/image.js +58 -4
- package/src/cli/index.js +127 -15
- package/src/cli/ipfs.js +4 -6
- package/src/cli/kubectl.js +4 -1
- package/src/cli/lxd.js +1099 -223
- package/src/cli/monitor.js +396 -9
- package/src/cli/release.js +355 -146
- package/src/cli/repository.js +169 -30
- package/src/cli/run.js +347 -117
- package/src/cli/secrets.js +11 -2
- package/src/cli/test.js +9 -3
- package/src/client/Default.index.js +9 -3
- package/src/client/components/core/Auth.js +5 -0
- package/src/client/components/core/ClientEvents.js +76 -0
- package/src/client/components/core/EventBus.js +4 -0
- package/src/client/components/core/Modal.js +82 -41
- package/src/client/components/core/PanelForm.js +14 -10
- package/src/client/components/core/Worker.js +162 -363
- package/src/client/components/cyberia/MapEngineCyberia.js +1 -1
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +330 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +55 -1
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +223 -361
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +114 -327
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +200 -222
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +212 -185
- package/src/client/public/cyberia-docs/CYBERIA.md +259 -0
- package/src/client/public/cyberia-docs/OFF-CHAIN-ECONOMY.md +2 -2
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +23 -1
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/UNDERPOST-PLATFORM.md +106 -0
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/services/cyberia-client-hints/cyberia-client-hints.service.js +99 -0
- package/src/client/ssr/views/CyberiaServerMetrics.js +982 -0
- package/src/client/sw/core.sw.js +174 -112
- package/src/db/DataBaseProvider.js +115 -15
- package/src/db/mariadb/MariaDB.js +2 -1
- package/src/db/mongo/MongoBootstrap.js +657 -0
- package/src/db/mongo/MongooseDB.js +130 -21
- package/src/grpc/cyberia/grpc-server.js +25 -57
- package/src/index.js +1 -1
- package/src/runtime/cyberia-client/Dockerfile +10 -7
- package/src/runtime/cyberia-client/Dockerfile.dev +67 -0
- package/src/runtime/cyberia-server/Dockerfile +11 -6
- package/src/runtime/cyberia-server/Dockerfile.dev +47 -0
- package/src/runtime/express/Express.js +2 -2
- package/src/runtime/wp/Dockerfile +3 -3
- package/src/runtime/wp/Wp.js +8 -5
- package/src/server/auth.js +2 -2
- package/src/server/catalog-underpost.js +61 -0
- package/src/server/catalog.js +77 -0
- package/src/server/client-build-docs.js +1 -1
- package/src/server/client-build.js +94 -129
- package/src/server/conf.js +496 -135
- package/src/server/ipfs-client.js +5 -3
- package/src/server/process.js +180 -19
- package/src/server/proxy.js +9 -2
- package/src/server/runtime-status.js +235 -0
- package/src/server/runtime.js +1 -1
- package/src/server/start.js +44 -11
- package/src/server/valkey.js +2 -0
- package/src/ws/IoInterface.js +16 -16
- package/src/ws/core/channels/core.ws.chat.js +11 -11
- package/src/ws/core/channels/core.ws.mailer.js +29 -29
- package/src/ws/core/channels/core.ws.stream.js +19 -19
- package/src/ws/core/core.ws.connection.js +8 -8
- package/src/ws/core/core.ws.server.js +6 -5
- package/src/ws/default/channels/default.ws.main.js +10 -10
- package/src/ws/default/default.ws.connection.js +4 -4
- package/src/ws/default/default.ws.server.js +4 -3
- package/test/deploy-monitor.test.js +251 -0
- package/bin/file.js +0 -202
- package/bin/vs.js +0 -74
- package/bin/zed.js +0 -84
- package/manifests/deployment/dd-test-development/deployment.yaml +0 -254
- package/manifests/deployment/dd-test-development/proxy.yaml +0 -102
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +0 -574
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +0 -467
- package/src/client/ssr/email/DefaultRecoverEmail.js +0 -21
- package/src/client/ssr/email/DefaultVerifyEmail.js +0 -17
- package/src/client/ssr/pages/CyberiaServerMetrics.js +0 -461
- /package/src/client/ssr/{offline → views}/Maintenance.js +0 -0
- /package/src/client/ssr/{offline → views}/NoNetworkConnection.js +0 -0
- /package/src/client/ssr/{pages → views}/Test.js +0 -0
package/src/cli/repository.js
CHANGED
|
@@ -8,6 +8,7 @@ import dotenv from 'dotenv';
|
|
|
8
8
|
import { commitData } from '../client/components/core/CommonJs.js';
|
|
9
9
|
import { pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
10
10
|
import { actionInitLog, loggerFactory } from '../server/logger.js';
|
|
11
|
+
import path from 'path';
|
|
11
12
|
import fs from 'fs-extra';
|
|
12
13
|
import {
|
|
13
14
|
getNpmRootPath,
|
|
@@ -133,10 +134,21 @@ class UnderpostRepository {
|
|
|
133
134
|
p: undefined,
|
|
134
135
|
bc: '',
|
|
135
136
|
isRemoteRepo: '',
|
|
137
|
+
hasChanges: false,
|
|
136
138
|
},
|
|
137
139
|
) {
|
|
138
140
|
if (!repoPath) repoPath = '.';
|
|
139
141
|
|
|
142
|
+
if (options.hasChanges) {
|
|
143
|
+
const status = shellExec(`cd ${repoPath} && git status --porcelain`, {
|
|
144
|
+
stdout: true,
|
|
145
|
+
silent: true,
|
|
146
|
+
disableLog: true,
|
|
147
|
+
}).trim();
|
|
148
|
+
process.stdout.write(status ? '1' : '');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
140
152
|
if (options.isRemoteRepo) {
|
|
141
153
|
const accessible = Underpost.repo.isRemoteRepo(options.isRemoteRepo);
|
|
142
154
|
console.log(accessible);
|
|
@@ -556,7 +568,7 @@ class UnderpostRepository {
|
|
|
556
568
|
// Handle sync-conf operation
|
|
557
569
|
if (options.syncConf) {
|
|
558
570
|
logger.info(`Syncing configuration for deploy ID: ${deployId}`);
|
|
559
|
-
shellExec(`node bin/build ${deployId} conf`);
|
|
571
|
+
shellExec(`node bin/build ${deployId} --conf`);
|
|
560
572
|
logger.info('Configuration synced successfully');
|
|
561
573
|
return resolve(true);
|
|
562
574
|
}
|
|
@@ -608,7 +620,8 @@ class UnderpostRepository {
|
|
|
608
620
|
const npmRoot = getNpmRootPath();
|
|
609
621
|
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|
|
610
622
|
const destFolder = `./${projectName}`;
|
|
611
|
-
|
|
623
|
+
const deployId = projectName.startsWith('dd-') ? projectName : `dd-${projectName}`;
|
|
624
|
+
logger.info('build app', { destFolder, deployId });
|
|
612
625
|
if (fs.existsSync(destFolder)) fs.removeSync(destFolder);
|
|
613
626
|
fs.mkdirSync(destFolder, { recursive: true });
|
|
614
627
|
if (!options.dev) {
|
|
@@ -621,8 +634,9 @@ class UnderpostRepository {
|
|
|
621
634
|
UnderpostRepository.API.initLocalRepo({ path: destFolder });
|
|
622
635
|
shellExec(`cd ${destFolder} && git add . && git commit -m "Base template implementation"`);
|
|
623
636
|
}
|
|
624
|
-
shellExec(`cd ${destFolder} &&
|
|
625
|
-
shellExec(`cd ${destFolder} &&
|
|
637
|
+
shellExec(`cd ${destFolder} && node bin new --deploy-id ${deployId} --default-conf`);
|
|
638
|
+
shellExec(`cd ${destFolder} && node bin client ${deployId}`);
|
|
639
|
+
shellExec(`cd ${destFolder} && DEPLOY_ID=${deployId} npm run dev`);
|
|
626
640
|
}
|
|
627
641
|
return resolve(true);
|
|
628
642
|
} catch (error) {
|
|
@@ -852,6 +866,7 @@ class UnderpostRepository {
|
|
|
852
866
|
}
|
|
853
867
|
}
|
|
854
868
|
await buildClient({
|
|
869
|
+
deployId: resolvedDeployId,
|
|
855
870
|
buildZip: options.buildZip || false,
|
|
856
871
|
split: options.split || '',
|
|
857
872
|
fullBuild: options.liteBuild ? false : true,
|
|
@@ -862,7 +877,12 @@ class UnderpostRepository {
|
|
|
862
877
|
logger.warn('Skip replica client build: replica folder not found', { replicaDeployId });
|
|
863
878
|
continue;
|
|
864
879
|
}
|
|
865
|
-
await Underpost.repo.client(replicaDeployId
|
|
880
|
+
await Underpost.repo.client(replicaDeployId, '', '', '', {
|
|
881
|
+
buildZip: options.buildZip || false,
|
|
882
|
+
split: options.split || '',
|
|
883
|
+
liteBuild: options.liteBuild || false,
|
|
884
|
+
iconsBuild: options.iconsBuild || false,
|
|
885
|
+
});
|
|
866
886
|
}
|
|
867
887
|
|
|
868
888
|
return resolve(true);
|
|
@@ -924,8 +944,6 @@ class UnderpostRepository {
|
|
|
924
944
|
shellExec(`cd ${privateRepoPath} && underpost pull . ${process.env.GITHUB_USERNAME}/${privateRepoName}`, {
|
|
925
945
|
silent: true,
|
|
926
946
|
});
|
|
927
|
-
shellExec(`underpost run secret`);
|
|
928
|
-
shellExec(`underpost run underpost-config`);
|
|
929
947
|
const packageJsonDeploy = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/package.json`, 'utf8'));
|
|
930
948
|
const packageJsonEngine = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
|
|
931
949
|
if (packageJsonDeploy.version !== packageJsonEngine.version) {
|
|
@@ -939,7 +957,7 @@ Prevent build private config repo.`,
|
|
|
939
957
|
deployVersion: packageJsonDeploy.version,
|
|
940
958
|
};
|
|
941
959
|
}
|
|
942
|
-
shellExec(`node bin/build ${deployId} conf`);
|
|
960
|
+
shellExec(`node bin/build ${deployId} --conf`);
|
|
943
961
|
return {
|
|
944
962
|
validVersion: true,
|
|
945
963
|
engineVersion: packageJsonEngine.version,
|
|
@@ -1008,11 +1026,14 @@ Prevent build private config repo.`,
|
|
|
1008
1026
|
const host = 'default.net';
|
|
1009
1027
|
const path = '/';
|
|
1010
1028
|
DefaultConf.server[host][path].valkey = {
|
|
1011
|
-
port: 6379,
|
|
1012
|
-
host: '
|
|
1029
|
+
port: 'env:VALKEY_PORT:int:6379',
|
|
1030
|
+
host: 'env:VALKEY_HOST:127.0.0.1',
|
|
1013
1031
|
};
|
|
1014
|
-
|
|
1015
|
-
DefaultConf.server[host][path].db.
|
|
1032
|
+
DefaultConf.server[host][path].db.host = 'env:DB_HOST:mongodb://127.0.0.1:27017';
|
|
1033
|
+
DefaultConf.server[host][path].db.replicaSet = 'env:DB_REPLICA_SET:rs0';
|
|
1034
|
+
DefaultConf.server[host][path].db.authSource = 'env:DB_AUTH_SOURCE:admin';
|
|
1035
|
+
DefaultConf.server[host][path].db.user = 'env:DB_USER:';
|
|
1036
|
+
DefaultConf.server[host][path].db.password = 'env:DB_PASSWORD:';
|
|
1016
1037
|
defaultConf = true;
|
|
1017
1038
|
break;
|
|
1018
1039
|
}
|
|
@@ -1048,9 +1069,9 @@ Prevent build private config repo.`,
|
|
|
1048
1069
|
*/
|
|
1049
1070
|
clean(options = { paths: [''] }) {
|
|
1050
1071
|
for (const path of options.paths) {
|
|
1051
|
-
shellExec(`cd ${path} && git reset`, { silent: true });
|
|
1052
|
-
shellExec(`cd ${path} && git checkout .`, { silent: true });
|
|
1053
|
-
shellExec(`cd ${path} && git clean -f -d`, { silent: true });
|
|
1072
|
+
shellExec(`cd ${path} && git reset`, { silentOnError: true, silent: true, disableLog: true });
|
|
1073
|
+
shellExec(`cd ${path} && git checkout .`, { silentOnError: true, silent: true, disableLog: true });
|
|
1074
|
+
shellExec(`cd ${path} && git clean -f -d`, { silentOnError: true, silent: true, disableLog: true });
|
|
1054
1075
|
}
|
|
1055
1076
|
},
|
|
1056
1077
|
|
|
@@ -1104,7 +1125,7 @@ Prevent build private config repo.`,
|
|
|
1104
1125
|
|
|
1105
1126
|
try {
|
|
1106
1127
|
// Fetch directory contents recursively
|
|
1107
|
-
const copiedFiles = await this.
|
|
1128
|
+
const copiedFiles = await this.fetchAndCopyGitHubDirectory({
|
|
1108
1129
|
apiUrl,
|
|
1109
1130
|
targetPath,
|
|
1110
1131
|
basePath: directoryPath,
|
|
@@ -1140,7 +1161,7 @@ Prevent build private config repo.`,
|
|
|
1140
1161
|
* @returns {Promise<array>} Array of copied file paths.
|
|
1141
1162
|
* @memberof UnderpostRepository
|
|
1142
1163
|
*/
|
|
1143
|
-
async
|
|
1164
|
+
async fetchAndCopyGitHubDirectory(options) {
|
|
1144
1165
|
const { apiUrl, targetPath, basePath, branch } = options;
|
|
1145
1166
|
const copiedFiles = [];
|
|
1146
1167
|
|
|
@@ -1175,14 +1196,12 @@ Prevent build private config repo.`,
|
|
|
1175
1196
|
|
|
1176
1197
|
logger.info(`Found ${contents.length} items in directory: ${basePath}`);
|
|
1177
1198
|
|
|
1178
|
-
// Process each item in the directory
|
|
1179
1199
|
for (const item of contents) {
|
|
1180
1200
|
const itemTargetPath = `${targetPath}/${item.name}`;
|
|
1181
1201
|
|
|
1182
1202
|
if (item.type === 'file') {
|
|
1183
1203
|
logger.info(`Downloading file: ${item.path}`);
|
|
1184
1204
|
|
|
1185
|
-
// Download file content
|
|
1186
1205
|
const fileResponse = await fetch(item.download_url);
|
|
1187
1206
|
if (!fileResponse.ok) {
|
|
1188
1207
|
logger.error(`Failed to download: ${item.download_url}`);
|
|
@@ -1192,16 +1211,14 @@ Prevent build private config repo.`,
|
|
|
1192
1211
|
const fileContent = await fileResponse.text();
|
|
1193
1212
|
fs.writeFileSync(itemTargetPath, fileContent);
|
|
1194
1213
|
|
|
1195
|
-
logger.info(
|
|
1214
|
+
logger.info(`Saved: ${itemTargetPath}`);
|
|
1196
1215
|
copiedFiles.push(itemTargetPath);
|
|
1197
1216
|
} else if (item.type === 'dir') {
|
|
1198
|
-
logger.info(
|
|
1217
|
+
logger.info(`Processing directory: ${item.path}`);
|
|
1199
1218
|
|
|
1200
|
-
// Create subdirectory
|
|
1201
1219
|
fs.mkdirSync(itemTargetPath, { recursive: true });
|
|
1202
1220
|
|
|
1203
|
-
|
|
1204
|
-
const subFiles = await this._fetchAndCopyGitHubDirectory({
|
|
1221
|
+
const subFiles = await this.fetchAndCopyGitHubDirectory({
|
|
1205
1222
|
apiUrl: item.url,
|
|
1206
1223
|
targetPath: itemTargetPath,
|
|
1207
1224
|
basePath: item.path,
|
|
@@ -1209,7 +1226,7 @@ Prevent build private config repo.`,
|
|
|
1209
1226
|
});
|
|
1210
1227
|
|
|
1211
1228
|
copiedFiles.push(...subFiles);
|
|
1212
|
-
logger.info(
|
|
1229
|
+
logger.info(`Completed directory: ${item.path} (${subFiles.length} files)`);
|
|
1213
1230
|
} else {
|
|
1214
1231
|
logger.warn(`Skipping unknown item type '${item.type}': ${item.path}`);
|
|
1215
1232
|
}
|
|
@@ -1295,7 +1312,7 @@ Prevent build private config repo.`,
|
|
|
1295
1312
|
},
|
|
1296
1313
|
/**
|
|
1297
1314
|
* Checks whether a remote Git repository URL is reachable.
|
|
1298
|
-
* Uses `
|
|
1315
|
+
* Uses `silentOnError` so a non-reachable remote returns false instead of throwing.
|
|
1299
1316
|
* Injects `GITHUB_TOKEN` into GitHub HTTPS URLs when available.
|
|
1300
1317
|
* @param {string} url - Full HTTPS clone URL to test (e.g. "https://github.com/org/repo.git").
|
|
1301
1318
|
* @returns {boolean} `true` when the remote responded with at least one ref hash.
|
|
@@ -1305,10 +1322,11 @@ Prevent build private config repo.`,
|
|
|
1305
1322
|
if (!url) return false;
|
|
1306
1323
|
const authUrl = Underpost.repo.resolveAuthUrl(url);
|
|
1307
1324
|
// GIT_TERMINAL_PROMPT=0 prevents git from hanging on credential prompts inside containers.
|
|
1308
|
-
const raw = shellExec(`GIT_TERMINAL_PROMPT=0 git ls-remote "${authUrl}" HEAD 2>&1
|
|
1325
|
+
const raw = shellExec(`GIT_TERMINAL_PROMPT=0 git ls-remote "${authUrl}" HEAD 2>&1`, {
|
|
1309
1326
|
stdout: true,
|
|
1310
1327
|
silent: true,
|
|
1311
1328
|
disableLog: true,
|
|
1329
|
+
silentOnError: true,
|
|
1312
1330
|
});
|
|
1313
1331
|
logger.info('isRemoteRepo', { url, raw: (raw || '').slice(0, 120) });
|
|
1314
1332
|
return typeof raw === 'string' && /^[0-9a-f]{40}\t/m.test(raw);
|
|
@@ -1376,15 +1394,17 @@ Prevent build private config repo.`,
|
|
|
1376
1394
|
const gitEmail = process.env.GITHUB_EMAIL || `development@underpost.net`;
|
|
1377
1395
|
|
|
1378
1396
|
if (!fs.existsSync(`${repoPath}/.git`)) {
|
|
1379
|
-
shellExec(`
|
|
1397
|
+
shellExec(`mkdir -p "${repoPath}" && git init "${repoPath}"`);
|
|
1380
1398
|
}
|
|
1399
|
+
|
|
1381
1400
|
shellExec(`cd "${repoPath}" && git config user.name '${gitUsername}'`);
|
|
1382
1401
|
shellExec(`cd "${repoPath}" && git config user.email '${gitEmail}'`);
|
|
1383
|
-
|
|
1402
|
+
shellExec(`cd "${repoPath}" && git config core.filemode false`);
|
|
1384
1403
|
if (origin) {
|
|
1385
|
-
const currentRemote = shellExec(`cd "${repoPath}" && git remote get-url origin
|
|
1404
|
+
const currentRemote = shellExec(`cd "${repoPath}" && git remote get-url origin`, {
|
|
1386
1405
|
stdout: true,
|
|
1387
1406
|
silent: true,
|
|
1407
|
+
silentOnError: true,
|
|
1388
1408
|
}).trim();
|
|
1389
1409
|
if (!currentRemote) {
|
|
1390
1410
|
shellExec(`cd "${repoPath}" && git remote add origin "${origin}"`);
|
|
@@ -1608,6 +1628,125 @@ Prevent build private config repo.`,
|
|
|
1608
1628
|
logger.info('engine-private in /home/dd removed');
|
|
1609
1629
|
}
|
|
1610
1630
|
},
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* Resolves the GitHub repository for a given instance runtime by scanning
|
|
1634
|
+
* every `conf.instances.json` listed in `./engine-private/deploy/dd.router`.
|
|
1635
|
+
*
|
|
1636
|
+
* Resolution order:
|
|
1637
|
+
* 1. If `runtime` is falsy, returns `${GITHUB_USERNAME}/engine`.
|
|
1638
|
+
* 2. Iterates each deploy ID found in `dd.router` and looks for an instance
|
|
1639
|
+
* whose `runtime` field matches the supplied value.
|
|
1640
|
+
* 3. When a match is found, returns `instance.metadata.repository`.
|
|
1641
|
+
* 4. Falls back to `${GITHUB_USERNAME}/engine` when no match is found.
|
|
1642
|
+
*
|
|
1643
|
+
* @param {string} [runtime=''] - The runtime identifier to look up (e.g. `'cyberia-server'`, `'cyberia-client'`).
|
|
1644
|
+
* @returns {string} The resolved `owner/repo` string.
|
|
1645
|
+
* @memberof UnderpostRepository
|
|
1646
|
+
*/
|
|
1647
|
+
resolveInstanceRepo(runtime = '') {
|
|
1648
|
+
const fallback = `${process.env.GITHUB_USERNAME}/engine`;
|
|
1649
|
+
if (!runtime) return fallback;
|
|
1650
|
+
const ddRouter = './engine-private/deploy/dd.router';
|
|
1651
|
+
const deployIds = fs.existsSync(ddRouter)
|
|
1652
|
+
? fs
|
|
1653
|
+
.readFileSync(ddRouter, 'utf8')
|
|
1654
|
+
.split(',')
|
|
1655
|
+
.map((s) => s.trim())
|
|
1656
|
+
.filter(Boolean)
|
|
1657
|
+
: [];
|
|
1658
|
+
for (const deployId of deployIds) {
|
|
1659
|
+
const confPath = `./engine-private/conf/${deployId}/conf.instances.json`;
|
|
1660
|
+
if (!fs.existsSync(confPath)) continue;
|
|
1661
|
+
try {
|
|
1662
|
+
const instances = JSON.parse(fs.readFileSync(confPath, 'utf8'));
|
|
1663
|
+
const match = instances.find((i) => i && i.runtime === runtime);
|
|
1664
|
+
if (match && match.metadata && match.metadata.repository) {
|
|
1665
|
+
logger.info(`[resolveInstanceRepo] resolved from ${confPath}`, {
|
|
1666
|
+
runtime,
|
|
1667
|
+
repo: match.metadata.repository,
|
|
1668
|
+
});
|
|
1669
|
+
return match.metadata.repository;
|
|
1670
|
+
}
|
|
1671
|
+
} catch (err) {
|
|
1672
|
+
logger.warn(`[resolveInstanceRepo] failed to parse ${confPath}: ${err.message}`);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
return fallback;
|
|
1676
|
+
},
|
|
1677
|
+
|
|
1678
|
+
/**
|
|
1679
|
+
* Performs a shallow sparse Git checkout of a single subdirectory from any
|
|
1680
|
+
* GitHub repository into a local target directory.
|
|
1681
|
+
*
|
|
1682
|
+
* Uses `--depth 1 --no-checkout` + `git sparse-checkout` so only the
|
|
1683
|
+
* requested path is fetched — no full clone of the remote repo.
|
|
1684
|
+
* Skips the clone entirely when `<targetDir>/<subPath>` already exists on
|
|
1685
|
+
* disk (idempotent).
|
|
1686
|
+
*
|
|
1687
|
+
* Requires `GITHUB_TOKEN` to be set in the environment for authenticated
|
|
1688
|
+
* access to private repositories.
|
|
1689
|
+
*
|
|
1690
|
+
* @param {string} subPath - The subdirectory path within the remote repo to
|
|
1691
|
+
* check out (e.g. `'conf/dd-prototype'`, `'src/api/payments'`).
|
|
1692
|
+
* @param {object} [options]
|
|
1693
|
+
* @param {string} [options.repoOwner='underpostnet'] - GitHub organisation or
|
|
1694
|
+
* user that owns the repository.
|
|
1695
|
+
* @param {string} [options.repoName='engine-private'] - Name of the
|
|
1696
|
+
* repository on GitHub.
|
|
1697
|
+
* @param {string} [options.targetDir='./engine-private'] - Local directory
|
|
1698
|
+
* where the repo will be cloned.
|
|
1699
|
+
* @returns {boolean} `true` when the checkout was performed, `false` when it
|
|
1700
|
+
* was skipped because the target path already existed.
|
|
1701
|
+
* @memberof UnderpostRepository
|
|
1702
|
+
*/
|
|
1703
|
+
sparseCheckoutDirectory(
|
|
1704
|
+
subPath,
|
|
1705
|
+
options = { repoOwner: 'underpostnet', repoName: 'engine-private', targetDir: './engine-private' },
|
|
1706
|
+
) {
|
|
1707
|
+
const { repoOwner = 'underpostnet', repoName = 'engine-private', targetDir = './engine-private' } = options;
|
|
1708
|
+
const localPath = `${targetDir}/${subPath}`;
|
|
1709
|
+
if (fs.existsSync(localPath)) {
|
|
1710
|
+
logger.info('[sparseCheckoutDirectory] path already present, skipping', localPath);
|
|
1711
|
+
return false;
|
|
1712
|
+
}
|
|
1713
|
+
const authUrl = `https://${process.env.GITHUB_TOKEN}@github.com/${repoOwner}/${repoName}.git`;
|
|
1714
|
+
shellExec(`git clone --depth 1 --no-checkout ${authUrl} ${targetDir}`, { disableLog: true });
|
|
1715
|
+
shellExec(`cd ${targetDir} && git sparse-checkout set ${subPath} && git checkout`, { disableLog: true });
|
|
1716
|
+
logger.info('[sparseCheckoutDirectory] sparse checkout complete', localPath);
|
|
1717
|
+
return true;
|
|
1718
|
+
},
|
|
1719
|
+
|
|
1720
|
+
/**
|
|
1721
|
+
* Ensures a deploy's public source repo (e.g. `engine-prototype`) is present
|
|
1722
|
+
* next to the engine and reset to a pristine HEAD, so catalog `sourceMoves`
|
|
1723
|
+
* can (re)pull custom sources even after a previous build moved them out of
|
|
1724
|
+
* the source tree.
|
|
1725
|
+
*
|
|
1726
|
+
* Clones `../<repoName>` when missing; otherwise restores a clean checkout
|
|
1727
|
+
* (`git checkout .` brings back any moved-out tracked files) and pulls latest.
|
|
1728
|
+
* Mirrors the sibling-repo handling used by `syncPrivateConf`.
|
|
1729
|
+
*
|
|
1730
|
+
* @param {string} repoName - Public source repo name (e.g. `engine-prototype`).
|
|
1731
|
+
* @returns {boolean} `true` when the repo is available on disk.
|
|
1732
|
+
* @memberof UnderpostRepository
|
|
1733
|
+
*/
|
|
1734
|
+
pullSourceRepo(repoName) {
|
|
1735
|
+
const username = process.env.GITHUB_USERNAME;
|
|
1736
|
+
if (!username || !repoName) return false;
|
|
1737
|
+
const repoPath = `../${repoName}`;
|
|
1738
|
+
const gitUri = `${username}/${repoName}`;
|
|
1739
|
+
if (!fs.existsSync(repoPath)) {
|
|
1740
|
+
shellExec(`cd .. && underpost clone ${gitUri}`, { silent: true });
|
|
1741
|
+
} else {
|
|
1742
|
+
const repoAbsPath = path.resolve(repoPath);
|
|
1743
|
+
shellExec(`git config --global --add safe.directory '${repoAbsPath}'`);
|
|
1744
|
+
shellExec(`cd ${repoPath} && git checkout . && git clean -f -d && underpost pull . ${gitUri}`, {
|
|
1745
|
+
silent: true,
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
return fs.existsSync(repoPath);
|
|
1749
|
+
},
|
|
1611
1750
|
};
|
|
1612
1751
|
}
|
|
1613
1752
|
|