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
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module deploy-monitor.test
|
|
3
|
+
* @description End-to-end test of the two-phase deployment readiness contract
|
|
4
|
+
* between the in-pod runtime (`start.js` / `runtime-status.js`) and the CD-runner
|
|
5
|
+
* monitor (`Underpost.monitor.monitorReadyRunner`), exercised as real OS
|
|
6
|
+
* processes coordinating through the shared underpost env file and a real HTTP
|
|
7
|
+
* internal status endpoint.
|
|
8
|
+
*
|
|
9
|
+
* Contract under test:
|
|
10
|
+
*
|
|
11
|
+
* - The in-pod runtime publishes only `container-status` (Phase 2) and serves
|
|
12
|
+
* it over `GET /_internal/status`. It never propagates an exit code.
|
|
13
|
+
*
|
|
14
|
+
* - monitorReadyRunner (CD runner) confirms BOTH phases before exiting 0:
|
|
15
|
+
* Phase 1 — Kubernetes pod `Ready` condition (kubectl get pod -o json).
|
|
16
|
+
* Phase 2 — runtime `running-deployment` read over HTTP via
|
|
17
|
+
* `kubectl port-forward` to the internal endpoint.
|
|
18
|
+
* It throws (→ exit 1) on explicit runtime `error`, and returns (→ exit 0)
|
|
19
|
+
* only once both phases are satisfied.
|
|
20
|
+
*
|
|
21
|
+
* The cluster surface is supplied by fake `sudo`/`kubectl` binaries on PATH:
|
|
22
|
+
* - `get pods` / `get pod -o json` report one pod whose Ready condition is
|
|
23
|
+
* driven by FAKE_POD_READY.
|
|
24
|
+
* - `port-forward` is a no-op sleep; the monitor's HTTP GET reaches a REAL
|
|
25
|
+
* internal status server bound in this test process (localPort == port),
|
|
26
|
+
* which reads the same env file the runtime writes.
|
|
27
|
+
*
|
|
28
|
+
* The env file is redirected under a temp `npm_config_prefix`, so the test
|
|
29
|
+
* needs no cluster, no root, and never touches the machine's global install.
|
|
30
|
+
*
|
|
31
|
+
* Uses 'chai' for assertions.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { expect } from 'chai';
|
|
35
|
+
import fs from 'fs-extra';
|
|
36
|
+
import os from 'node:os';
|
|
37
|
+
import path from 'node:path';
|
|
38
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
39
|
+
import Underpost from '../src/index.js';
|
|
40
|
+
import { shellExec } from '../src/server/process.js';
|
|
41
|
+
import { startInternalStatusServer, stopInternalStatusServer } from '../src/server/runtime-status.js';
|
|
42
|
+
|
|
43
|
+
const node = process.execPath;
|
|
44
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
45
|
+
|
|
46
|
+
const DEPLOY_ID = 'dd-test';
|
|
47
|
+
const ENV = 'production';
|
|
48
|
+
const TRAFFIC = 'green';
|
|
49
|
+
const POD_NAME = `${DEPLOY_ID}-${ENV}-${TRAFFIC}-pod`;
|
|
50
|
+
const RUNNING_STATUS = `${DEPLOY_ID}-${ENV}-running-deployment`;
|
|
51
|
+
const INIT_STATUS = `${DEPLOY_ID}-${ENV}-initializing-deployment`;
|
|
52
|
+
const BUILD_STATUS = `${DEPLOY_ID}-${ENV}-build-deployment`;
|
|
53
|
+
|
|
54
|
+
const INTERNAL_PORT = 39517; // internal status endpoint (real server bound here)
|
|
55
|
+
const CLOSED_PORT = 39518; // no server — used to force a transport failure
|
|
56
|
+
|
|
57
|
+
describe('Deploy monitor — two-phase state machine (e2e, real HTTP transport)', function () {
|
|
58
|
+
this.timeout(60000);
|
|
59
|
+
|
|
60
|
+
let prevPrefix;
|
|
61
|
+
let tmpPrefix;
|
|
62
|
+
let fakeBinDir;
|
|
63
|
+
let envFile;
|
|
64
|
+
let monitorScriptPath;
|
|
65
|
+
|
|
66
|
+
before(() => {
|
|
67
|
+
prevPrefix = process.env.npm_config_prefix;
|
|
68
|
+
tmpPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'underpost-e2e-'));
|
|
69
|
+
process.env.npm_config_prefix = tmpPrefix;
|
|
70
|
+
|
|
71
|
+
Underpost.env.set('container-status', 'init');
|
|
72
|
+
const npmRoot = shellExec('npm root -g', { stdout: true, silent: true, disableLog: true }).trim();
|
|
73
|
+
envFile = path.join(npmRoot, 'underpost', '.env');
|
|
74
|
+
|
|
75
|
+
// Real in-pod internal status server: serves container-status from the same
|
|
76
|
+
// env file the runtime writes. Bound in this test process; the monitor's
|
|
77
|
+
// port-forward tunnel (localPort == INTERNAL_PORT) resolves straight to it.
|
|
78
|
+
process.env.UNDERPOST_INTERNAL_PORT = String(INTERNAL_PORT);
|
|
79
|
+
startInternalStatusServer(INTERNAL_PORT);
|
|
80
|
+
|
|
81
|
+
fakeBinDir = path.join(tmpPrefix, 'fakebin');
|
|
82
|
+
fs.ensureDirSync(fakeBinDir);
|
|
83
|
+
|
|
84
|
+
const sudoPath = path.join(fakeBinDir, 'sudo');
|
|
85
|
+
fs.writeFileSync(
|
|
86
|
+
sudoPath,
|
|
87
|
+
`#!/usr/bin/env bash
|
|
88
|
+
while [[ "$1" == -* || "$1" == "--" ]]; do shift; done
|
|
89
|
+
exec "$@"
|
|
90
|
+
`,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const kubectlPath = path.join(fakeBinDir, 'kubectl');
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
kubectlPath,
|
|
96
|
+
`#!/usr/bin/env bash
|
|
97
|
+
verb="$1"; kind="$2"
|
|
98
|
+
if [[ "$verb" == "get" && "$kind" == "pods" ]]; then
|
|
99
|
+
printf 'NAME READY STATUS RESTARTS AGE\\n'
|
|
100
|
+
printf '%s 1/1 Running 0 1m\\n' "$POD_NAME"
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
if [[ "$verb" == "get" && "$kind" == "pod" ]]; then
|
|
104
|
+
printf '{"status":{"conditions":[{"type":"Ready","status":"%s"}]}}\\n' "\${FAKE_POD_READY:-True}"
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
if [[ "$verb" == "port-forward" ]]; then
|
|
108
|
+
sleep 30
|
|
109
|
+
exit 0
|
|
110
|
+
fi
|
|
111
|
+
if [[ "$verb" == "exec" ]]; then
|
|
112
|
+
grep -E '^container-status=' "$UNDERPOST_ENV_FILE" 2>/dev/null | tail -n1 | sed -E 's/^container-status=//'
|
|
113
|
+
exit 0
|
|
114
|
+
fi
|
|
115
|
+
exit 0
|
|
116
|
+
`,
|
|
117
|
+
);
|
|
118
|
+
fs.chmodSync(sudoPath, 0o755);
|
|
119
|
+
fs.chmodSync(kubectlPath, 0o755);
|
|
120
|
+
|
|
121
|
+
monitorScriptPath = path.join(tmpPrefix, 'monitor-ready.mjs');
|
|
122
|
+
fs.writeFileSync(
|
|
123
|
+
monitorScriptPath,
|
|
124
|
+
`import Underpost from ${JSON.stringify(pathToFileURL(path.join(repoRoot, 'src/index.js')).href)};
|
|
125
|
+
const options = {};
|
|
126
|
+
if (process.env.MON_READY_GATE) options.readyGate = process.env.MON_READY_GATE;
|
|
127
|
+
if (process.env.MON_TRANSPORT) options.statusTransport = process.env.MON_TRANSPORT;
|
|
128
|
+
try {
|
|
129
|
+
await Underpost.monitor.monitorReadyRunner(${JSON.stringify(DEPLOY_ID)}, ${JSON.stringify(ENV)}, ${JSON.stringify(
|
|
130
|
+
TRAFFIC,
|
|
131
|
+
)}, [], 'default', options);
|
|
132
|
+
process.exit(0);
|
|
133
|
+
} catch (_) {
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
`,
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
after(async () => {
|
|
141
|
+
await stopInternalStatusServer();
|
|
142
|
+
delete process.env.UNDERPOST_INTERNAL_PORT;
|
|
143
|
+
if (prevPrefix === undefined) delete process.env.npm_config_prefix;
|
|
144
|
+
else process.env.npm_config_prefix = prevPrefix;
|
|
145
|
+
fs.removeSync(tmpPrefix);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
beforeEach(() => {
|
|
149
|
+
// Deploy in flight: app not yet reporting running.
|
|
150
|
+
Underpost.env.set('container-status', INIT_STATUS);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Spawns the real monitorReadyRunner with the fake cluster on PATH; resolves
|
|
154
|
+
// with its exit code. `overrides` inject deterministic timing / target port.
|
|
155
|
+
const spawnMonitor = (overrides = {}) =>
|
|
156
|
+
new Promise((resolve) => {
|
|
157
|
+
const envVars = {
|
|
158
|
+
PATH: `${fakeBinDir}:${process.env.PATH}`,
|
|
159
|
+
UNDERPOST_ENV_FILE: envFile,
|
|
160
|
+
POD_NAME,
|
|
161
|
+
npm_config_prefix: tmpPrefix,
|
|
162
|
+
UNDERPOST_INTERNAL_PORT: String(INTERNAL_PORT),
|
|
163
|
+
// Pin the tunnel's local port so the no-op fake port-forward + the real
|
|
164
|
+
// internal server (bound to INTERNAL_PORT in this process) resolve to the
|
|
165
|
+
// same address the monitor's HTTP GET targets.
|
|
166
|
+
UNDERPOST_PF_LOCAL_PORT: String(INTERNAL_PORT),
|
|
167
|
+
UNDERPOST_MONITOR_DELAY_MS: '100',
|
|
168
|
+
UNDERPOST_MONITOR_MAX_ITERATIONS: '60',
|
|
169
|
+
UNDERPOST_PF_ATTEMPTS: '3',
|
|
170
|
+
FAKE_POD_READY: 'True',
|
|
171
|
+
...overrides,
|
|
172
|
+
};
|
|
173
|
+
const prefix = Object.entries(envVars)
|
|
174
|
+
.map(([k, v]) => `${k}="${v}"`)
|
|
175
|
+
.join(' ');
|
|
176
|
+
shellExec(`${prefix} ${node} ${monitorScriptPath}`, {
|
|
177
|
+
async: true,
|
|
178
|
+
silent: true,
|
|
179
|
+
disableLog: true,
|
|
180
|
+
callback: (code) => resolve(code),
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('success (default exec transport): both phases satisfied → monitor exits 0', async () => {
|
|
185
|
+
Underpost.env.set('container-status', RUNNING_STATUS);
|
|
186
|
+
const code = await spawnMonitor({ FAKE_POD_READY: 'True' });
|
|
187
|
+
expect(code).to.equal(0);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('success (opt-in http transport): both phases satisfied → monitor exits 0', async () => {
|
|
191
|
+
Underpost.env.set('container-status', RUNNING_STATUS);
|
|
192
|
+
const code = await spawnMonitor({ FAKE_POD_READY: 'True', MON_TRANSPORT: 'http' });
|
|
193
|
+
expect(code).to.equal(0);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('runtime failure: container-status=error → monitor exits 1', async () => {
|
|
197
|
+
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'True' });
|
|
198
|
+
Underpost.env.set('container-status', 'error');
|
|
199
|
+
expect(await monitorExit).to.equal(1);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('readiness mismatch: runtime running but pod not Ready → never succeeds (exits 1)', async () => {
|
|
203
|
+
// Phase 2 satisfied, Phase 1 not: success requires BOTH, so it must time out.
|
|
204
|
+
Underpost.env.set('container-status', RUNNING_STATUS);
|
|
205
|
+
const code = await spawnMonitor({ FAKE_POD_READY: 'False', UNDERPOST_MONITOR_MAX_ITERATIONS: '4' });
|
|
206
|
+
expect(code).to.equal(1);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('transport failure (http): endpoint unreachable is never success (exits 1)', async () => {
|
|
210
|
+
// Opt into http and point the monitor at a port with no internal server; the
|
|
211
|
+
// HTTP read always fails, so runtime readiness is never confirmed → timeout.
|
|
212
|
+
Underpost.env.set('container-status', RUNNING_STATUS);
|
|
213
|
+
const code = await spawnMonitor({
|
|
214
|
+
MON_TRANSPORT: 'http',
|
|
215
|
+
UNDERPOST_INTERNAL_PORT: String(CLOSED_PORT),
|
|
216
|
+
UNDERPOST_PF_LOCAL_PORT: String(CLOSED_PORT),
|
|
217
|
+
UNDERPOST_MONITOR_MAX_ITERATIONS: '3',
|
|
218
|
+
});
|
|
219
|
+
expect(code).to.equal(1);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('timeout: runtime stuck initializing → monitor exits 1', async () => {
|
|
223
|
+
Underpost.env.set('container-status', INIT_STATUS);
|
|
224
|
+
const code = await spawnMonitor({ FAKE_POD_READY: 'True', UNDERPOST_MONITOR_MAX_ITERATIONS: '4' });
|
|
225
|
+
expect(code).to.equal(1);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('regression: advanced pod whose runtime status falls back → monitor exits 1', async () => {
|
|
229
|
+
// Pod advances past build, then its reported status regresses (pod restart);
|
|
230
|
+
// the monitor must treat this as a failure rather than wait it out.
|
|
231
|
+
Underpost.env.set('container-status', INIT_STATUS);
|
|
232
|
+
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'False', UNDERPOST_MONITOR_MAX_ITERATIONS: '120' });
|
|
233
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
234
|
+
Underpost.env.set('container-status', BUILD_STATUS);
|
|
235
|
+
expect(await monitorExit).to.equal(1);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Custom instances (cyberia-*) gate on K8s Ready and read status via exec;
|
|
239
|
+
// their runtime never stamps `running-deployment` (stays `initializing`).
|
|
240
|
+
it('instance (kubernetes gate + exec): K8s Ready with initializing status → exits 0', async () => {
|
|
241
|
+
Underpost.env.set('container-status', INIT_STATUS);
|
|
242
|
+
const code = await spawnMonitor({ FAKE_POD_READY: 'True', MON_READY_GATE: 'kubernetes', MON_TRANSPORT: 'exec' });
|
|
243
|
+
expect(code).to.equal(0);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('instance (kubernetes gate + exec): container-status=error → exits 1', async () => {
|
|
247
|
+
const monitorExit = spawnMonitor({ FAKE_POD_READY: 'True', MON_READY_GATE: 'kubernetes', MON_TRANSPORT: 'exec' });
|
|
248
|
+
Underpost.env.set('container-status', 'error');
|
|
249
|
+
expect(await monitorExit).to.equal(1);
|
|
250
|
+
});
|
|
251
|
+
});
|
package/bin/file.js
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
|
|
3
|
-
import { loggerFactory } from '../src/server/logger.js';
|
|
4
|
-
import {
|
|
5
|
-
cap,
|
|
6
|
-
getCapVariableName,
|
|
7
|
-
getDirname,
|
|
8
|
-
newInstance,
|
|
9
|
-
uniqueArray,
|
|
10
|
-
} from '../src/client/components/core/CommonJs.js';
|
|
11
|
-
import { shellCd, shellExec } from '../src/server/process.js';
|
|
12
|
-
import walk from 'ignore-walk';
|
|
13
|
-
import { validateTemplatePath } from '../src/server/conf.js';
|
|
14
|
-
import dotenv from 'dotenv';
|
|
15
|
-
|
|
16
|
-
const logger = loggerFactory(import.meta);
|
|
17
|
-
|
|
18
|
-
dotenv.config({ path: `./engine-private/conf/dd-cron/.env.production`, override: true });
|
|
19
|
-
|
|
20
|
-
logger.info('argv', process.argv);
|
|
21
|
-
|
|
22
|
-
let [exe, dir, type] = process.argv;
|
|
23
|
-
let rawPath = process.argv[3].replaceAll(`'`, '');
|
|
24
|
-
let toPath = process.argv[4].replaceAll(`'`, '');
|
|
25
|
-
let path = `${rawPath}`.split('/');
|
|
26
|
-
path.pop();
|
|
27
|
-
path = path.join('/');
|
|
28
|
-
const file = `${rawPath}`.split('/').pop();
|
|
29
|
-
const ext = file.split('.')[1];
|
|
30
|
-
let name = getCapVariableName(file.split('.')[0]);
|
|
31
|
-
let content = '';
|
|
32
|
-
|
|
33
|
-
logger.info('File metadata', { path, file, ext, name });
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
switch (type) {
|
|
37
|
-
case 'update-template':
|
|
38
|
-
case 'copy-src':
|
|
39
|
-
console.log({ rawPath, toPath });
|
|
40
|
-
|
|
41
|
-
let result = await new Promise((resolve) =>
|
|
42
|
-
walk(
|
|
43
|
-
{
|
|
44
|
-
path: rawPath, // root dir to start in. defaults to process.cwd()
|
|
45
|
-
ignoreFiles: [`.gitignore`], // list of filenames. defaults to ['.ignore']
|
|
46
|
-
includeEmpty: false, // true to include empty dirs, default false
|
|
47
|
-
follow: false, // true to follow symlink dirs, default false
|
|
48
|
-
},
|
|
49
|
-
(...args) => resolve(args[1]),
|
|
50
|
-
),
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
result = result.filter((path) => !path.startsWith('.git'));
|
|
54
|
-
|
|
55
|
-
console.log('copy paths', result);
|
|
56
|
-
|
|
57
|
-
if (type === 'update-template') {
|
|
58
|
-
if (!fs.existsSync(toPath))
|
|
59
|
-
shellExec(`cd .. && underpost clone ${process.env.GITHUB_USERNAME}/pwa-microservices-template`);
|
|
60
|
-
else {
|
|
61
|
-
shellExec(`cd ${toPath} && git reset && git checkout . && git clean -f -d`);
|
|
62
|
-
shellExec(`underpost pull ${toPath} ${process.env.GITHUB_USERNAME}/pwa-microservices-template`);
|
|
63
|
-
shellExec(`sudo rm -rf ${toPath}/engine-private`);
|
|
64
|
-
shellExec(`sudo rm -rf ${toPath}/logs`);
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
fs.removeSync(toPath);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
for (const copyPath of result) {
|
|
71
|
-
if (copyPath === 'NaN') continue;
|
|
72
|
-
const folder = getDirname(`${toPath}/${copyPath}`);
|
|
73
|
-
const absolutePath = `${rawPath}/${copyPath}`;
|
|
74
|
-
|
|
75
|
-
if (type === 'update-template' && !validateTemplatePath(absolutePath)) continue;
|
|
76
|
-
|
|
77
|
-
if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
|
|
78
|
-
|
|
79
|
-
logger.info('build', `${toPath}/${copyPath}`);
|
|
80
|
-
|
|
81
|
-
fs.copyFileSync(absolutePath, `${toPath}/${copyPath}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (type === 'update-template') {
|
|
85
|
-
fs.copySync(`./.vscode`, `../pwa-microservices-template/.vscode`);
|
|
86
|
-
// fs.copySync(`./.github`, `../pwa-microservices-template/.github`);
|
|
87
|
-
fs.copySync(`./src/client/public/default`, `../pwa-microservices-template/src/client/public/default`);
|
|
88
|
-
|
|
89
|
-
for (const checkoutPath of ['README.md', 'package.json'])
|
|
90
|
-
shellExec(`cd ../pwa-microservices-template && git checkout ${checkoutPath}`);
|
|
91
|
-
|
|
92
|
-
for (const deletePath of [
|
|
93
|
-
'./.github',
|
|
94
|
-
'./manifests/deployment/dd-lampp-development',
|
|
95
|
-
'./manifests/deployment/dd-cyberia-development',
|
|
96
|
-
'./manifests/deployment/dd-core-development',
|
|
97
|
-
'./manifests/deployment/dd-template-development',
|
|
98
|
-
'./src/server/object-layer.js',
|
|
99
|
-
'./src/server/atlas-sprite-sheet-generator.js',
|
|
100
|
-
'./src/server/shape-generator.js',
|
|
101
|
-
'./src/server/semantic-layer-generator.js',
|
|
102
|
-
'./src/server/semantic-layer-generator-floor.js',
|
|
103
|
-
'./src/server/semantic-layer-generator-skin.js',
|
|
104
|
-
'./src/server/semantic-layer-generator-resource.js',
|
|
105
|
-
'./src/server/besu-genesis-generator.js',
|
|
106
|
-
'./src/grpc/cyberia',
|
|
107
|
-
'./src/runtime/cyberia-server',
|
|
108
|
-
'./src/runtime/cyberia-client',
|
|
109
|
-
'./test/shape-generator.test.js',
|
|
110
|
-
'./src/client/public/cyberia-docs',
|
|
111
|
-
'bin/cyberia.js',
|
|
112
|
-
]) {
|
|
113
|
-
if (fs.existsSync(deletePath)) fs.removeSync('../pwa-microservices-template/' + deletePath);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
fs.mkdirSync(`../pwa-microservices-template/.github/workflows`, {
|
|
117
|
-
recursive: true,
|
|
118
|
-
});
|
|
119
|
-
for (const _path of [
|
|
120
|
-
`./.github/workflows/pwa-microservices-template-page.cd.yml`,
|
|
121
|
-
`./.github/workflows/pwa-microservices-template-test.ci.yml`,
|
|
122
|
-
`./.github/workflows/npmpkg.ci.yml`,
|
|
123
|
-
`./.github/workflows/ghpkg.ci.yml`,
|
|
124
|
-
`./.github/workflows/gitlab.ci.yml`,
|
|
125
|
-
`./.github/workflows/publish.ci.yml`,
|
|
126
|
-
`./.github/workflows/release.cd.yml`,
|
|
127
|
-
`./src/client/services/user/guest.service.js`,
|
|
128
|
-
'./src/api/user/guest.service.js',
|
|
129
|
-
'./src/ws/IoInterface.js',
|
|
130
|
-
'./src/ws/IoServer.js',
|
|
131
|
-
])
|
|
132
|
-
fs.copyFileSync(_path, `../pwa-microservices-template/${_path}`);
|
|
133
|
-
|
|
134
|
-
const originPackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
135
|
-
const templatePackageJson = JSON.parse(fs.readFileSync('../pwa-microservices-template/package.json', 'utf8'));
|
|
136
|
-
|
|
137
|
-
const name = templatePackageJson.name;
|
|
138
|
-
const description = templatePackageJson.description;
|
|
139
|
-
const dev = templatePackageJson.scripts.dev;
|
|
140
|
-
const build = templatePackageJson.scripts.build;
|
|
141
|
-
|
|
142
|
-
templatePackageJson.dependencies = originPackageJson.dependencies;
|
|
143
|
-
templatePackageJson.devDependencies = originPackageJson.devDependencies;
|
|
144
|
-
templatePackageJson.version = originPackageJson.version;
|
|
145
|
-
templatePackageJson.scripts = originPackageJson.scripts;
|
|
146
|
-
templatePackageJson.overrides = originPackageJson.overrides;
|
|
147
|
-
templatePackageJson.name = name;
|
|
148
|
-
templatePackageJson.description = description;
|
|
149
|
-
// templatePackageJson.scripts.dev = dev;
|
|
150
|
-
// templatePackageJson.scripts.build = build;
|
|
151
|
-
templatePackageJson.keywords = uniqueArray(
|
|
152
|
-
['pwa', 'microservices', 'template', 'builder'].concat(templatePackageJson.keywords),
|
|
153
|
-
);
|
|
154
|
-
delete templatePackageJson.scripts['update:template'];
|
|
155
|
-
fs.writeFileSync(
|
|
156
|
-
'../pwa-microservices-template/package.json',
|
|
157
|
-
JSON.stringify(templatePackageJson, null, 4),
|
|
158
|
-
'utf8',
|
|
159
|
-
);
|
|
160
|
-
const originPackageLockJson = JSON.parse(fs.readFileSync('./package-lock.json', 'utf8'));
|
|
161
|
-
|
|
162
|
-
const templatePackageLockJson = JSON.parse(
|
|
163
|
-
fs.readFileSync('../pwa-microservices-template/package-lock.json', 'utf8'),
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const originBasePackageLock = newInstance(templatePackageLockJson.packages['']);
|
|
167
|
-
templatePackageLockJson.name = name;
|
|
168
|
-
templatePackageLockJson.version = originPackageLockJson.version;
|
|
169
|
-
templatePackageLockJson.packages = originPackageLockJson.packages;
|
|
170
|
-
templatePackageLockJson.packages[''].name = name;
|
|
171
|
-
templatePackageLockJson.packages[''].version = originPackageLockJson.version;
|
|
172
|
-
templatePackageLockJson.packages[''].hasInstallScript = originBasePackageLock.hasInstallScript;
|
|
173
|
-
templatePackageLockJson.packages[''].license = originBasePackageLock.license;
|
|
174
|
-
fs.writeFileSync(
|
|
175
|
-
'../pwa-microservices-template/package-lock.json',
|
|
176
|
-
JSON.stringify(templatePackageLockJson, null, 4),
|
|
177
|
-
'utf8',
|
|
178
|
-
);
|
|
179
|
-
// Regenerate package-lock.json to match the modified package.json
|
|
180
|
-
// shellExec(`cd ../pwa-microservices-template && npm install --package-lock-only --ignore-scripts`);
|
|
181
|
-
fs.writeFileSync(
|
|
182
|
-
'../pwa-microservices-template/README.md',
|
|
183
|
-
fs
|
|
184
|
-
.readFileSync('./README.md', 'utf8')
|
|
185
|
-
.replace('<!-- template-title -->', '#### Base template for pwa/api-rest projects.'),
|
|
186
|
-
'utf8',
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
break;
|
|
191
|
-
case 'create':
|
|
192
|
-
const buildPath = `${path}/${name}${ext ? `.${ext}` : ''}`;
|
|
193
|
-
logger.info('Build path', buildPath);
|
|
194
|
-
fs.mkdirSync(path, { recursive: true });
|
|
195
|
-
fs.writeFileSync(buildPath, content, 'utf8');
|
|
196
|
-
default:
|
|
197
|
-
logger.error('not found operator');
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
} catch (error) {
|
|
201
|
-
logger.error(error, error.stack);
|
|
202
|
-
}
|
package/bin/vs.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import { shellExec } from '../src/server/process.js';
|
|
3
|
-
import { loggerFactory } from '../src/server/logger.js';
|
|
4
|
-
|
|
5
|
-
const logger = loggerFactory(import.meta);
|
|
6
|
-
|
|
7
|
-
const vsCodeRootPath = '/root/.vscode-root';
|
|
8
|
-
const vsConfigRootPath = '/root/.config/Code';
|
|
9
|
-
|
|
10
|
-
const vsProgram = 'code';
|
|
11
|
-
|
|
12
|
-
switch (process.argv[2]) {
|
|
13
|
-
case 'info': {
|
|
14
|
-
logger.info('Formatted', 'Ctrl shift I');
|
|
15
|
-
logger.info('Command', 'Ctrl shift P');
|
|
16
|
-
logger.info('Search', 'Ctrl shift F');
|
|
17
|
-
logger.info('Debug', 'Ctrl shift D');
|
|
18
|
-
logger.info('New File', 'Ctrl N');
|
|
19
|
-
logger.info('Change tab', 'Ctrl Tab');
|
|
20
|
-
logger.info('Fold All', 'Ctrl K + Ctrl 0');
|
|
21
|
-
logger.info('Unfold All', 'Ctrl K + Ctrl J');
|
|
22
|
-
logger.info('Close All tabs', 'Ctrl K + W');
|
|
23
|
-
logger.info('Go to line number', 'Ctrl G');
|
|
24
|
-
logger.info('Change current project folder', 'Ctrl K + Ctrl O');
|
|
25
|
-
logger.info('Open new vs windows', 'Ctrl Shift N');
|
|
26
|
-
logger.info('Close current vs windows', 'Ctrl Shift W');
|
|
27
|
-
logger.info('Preview md', 'Ctrl shift V');
|
|
28
|
-
logger.info('Open git changes', 'Ctrl G + G');
|
|
29
|
-
logger.warn('Terminal shortcut configure with command pallette', 'Ctl shift T');
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
case 'import':
|
|
33
|
-
{
|
|
34
|
-
const extensions = JSON.parse(fs.readFileSync(`./.vscode/extensions.json`, 'utf8'));
|
|
35
|
-
extensions.recommendations.map((extension) => {
|
|
36
|
-
if (extension)
|
|
37
|
-
shellExec(
|
|
38
|
-
`sudo ${vsProgram} --user-data-dir="${vsCodeRootPath}" --no-sandbox --install-extension ${extension}`,
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
break;
|
|
43
|
-
case 'export':
|
|
44
|
-
{
|
|
45
|
-
shellExec(
|
|
46
|
-
`sudo ${vsProgram} --user-data-dir="${vsCodeRootPath}" --no-sandbox --list-extensions > vs-extensions.txt`,
|
|
47
|
-
);
|
|
48
|
-
fs.writeFileSync(
|
|
49
|
-
`./.vscode/extensions.json`,
|
|
50
|
-
JSON.stringify(
|
|
51
|
-
{
|
|
52
|
-
recommendations: fs
|
|
53
|
-
.readFileSync(`./vs-extensions.txt`, 'utf8')
|
|
54
|
-
.split(`\n`)
|
|
55
|
-
.filter((ext) => ext.trim()),
|
|
56
|
-
},
|
|
57
|
-
null,
|
|
58
|
-
4,
|
|
59
|
-
),
|
|
60
|
-
'utf8',
|
|
61
|
-
);
|
|
62
|
-
fs.removeSync(`./vs-extensions.txt`);
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
|
|
66
|
-
case 'clean': {
|
|
67
|
-
shellExec(`sudo rm -rf ${vsCodeRootPath}/*`);
|
|
68
|
-
shellExec(`sudo rm -rf ${vsConfigRootPath}`);
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
default:
|
|
72
|
-
shellExec(`sudo ${vsProgram} ${process.argv[2]} --user-data-dir="${vsCodeRootPath}" --no-sandbox`);
|
|
73
|
-
break;
|
|
74
|
-
}
|
package/bin/zed.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { shellExec } from '../src/server/process.js';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import { loggerFactory } from '../src/server/logger.js';
|
|
4
|
-
import { getUnderpostRootPath } from '../src/server/conf.js';
|
|
5
|
-
|
|
6
|
-
const logger = loggerFactory(import.meta);
|
|
7
|
-
const underpostRoot = getUnderpostRootPath();
|
|
8
|
-
|
|
9
|
-
const settings = {
|
|
10
|
-
ui_font_size: 16,
|
|
11
|
-
buffer_font_size: 15,
|
|
12
|
-
theme: {
|
|
13
|
-
mode: 'system',
|
|
14
|
-
light: 'One Dark',
|
|
15
|
-
dark: 'One Dark',
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
features: {
|
|
19
|
-
edit_prediction_provider: 'copilot',
|
|
20
|
-
copilot: true,
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
show_edit_predictions: true,
|
|
24
|
-
|
|
25
|
-
edit_predictions: {
|
|
26
|
-
mode: 'eager',
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const keyMap = [
|
|
31
|
-
{
|
|
32
|
-
context: 'Editor',
|
|
33
|
-
bindings: {
|
|
34
|
-
'ctrl-c': 'editor::Copy',
|
|
35
|
-
'ctrl-x': 'editor::Cut',
|
|
36
|
-
'ctrl-v': 'editor::Paste',
|
|
37
|
-
'ctrl-shift-c': 'editor::CopyAndTrim',
|
|
38
|
-
'ctrl-shift-v': 'editor::Paste',
|
|
39
|
-
'cmd-c': 'editor::Copy',
|
|
40
|
-
'cmd-x': 'editor::Cut',
|
|
41
|
-
'cmd-v': 'editor::Paste',
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
context: 'Terminal',
|
|
46
|
-
bindings: {
|
|
47
|
-
'ctrl-shift-c': 'terminal::Copy',
|
|
48
|
-
'ctrl-shift-v': 'terminal::Paste',
|
|
49
|
-
'cmd-shift-c': 'terminal::Copy',
|
|
50
|
-
'cmd-shift-v': 'terminal::Paste',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
context: 'Editor && edit_prediction',
|
|
55
|
-
bindings: {
|
|
56
|
-
tab: 'editor::AcceptEditPrediction',
|
|
57
|
-
'alt-tab': 'editor::AcceptEditPrediction',
|
|
58
|
-
'alt-l': null,
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
context: 'Editor && edit_prediction_conflict',
|
|
63
|
-
bindings: {
|
|
64
|
-
'alt-l': 'editor::AcceptEditPrediction',
|
|
65
|
-
tab: 'editor::ComposeCompletion',
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
if (!fs.existsSync('/root/.config/zed')) fs.mkdirSync('/root/.config/zed', { recursive: true });
|
|
71
|
-
fs.writeFileSync(`/root/.config/zed/settings.json`, JSON.stringify(settings, null, 4), 'utf8');
|
|
72
|
-
fs.writeFileSync(`/root/.config/zed/keymap.json`, JSON.stringify(keyMap, null, 4), 'utf8');
|
|
73
|
-
|
|
74
|
-
shellExec(`ZED_ALLOW_ROOT=true zed ${process.argv[2] ? process.argv[2] : '.'}`);
|
|
75
|
-
|
|
76
|
-
logger.info('Connect copilot device', 'https://github.com/login/device');
|
|
77
|
-
logger.info('Comments', 'Ctrl shift 7');
|
|
78
|
-
logger.info('Unfold', 'Ctrl K + Ctrl J');
|
|
79
|
-
logger.info('Fold', 'Ctrl K + Ctrl 0');
|
|
80
|
-
logger.info('Command Palette', 'Ctrl Shift P');
|
|
81
|
-
logger.info('Open File', 'Ctrl P');
|
|
82
|
-
logger.info('Find in Files', 'Ctrl Shift F');
|
|
83
|
-
logger.info('Go to Line', 'Ctrl G');
|
|
84
|
-
logger.info('New file', 'Ctrl N');
|