genbox 1.0.14 → 1.0.15
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/dist/commands/connect.js +7 -2
- package/dist/commands/create.js +51 -115
- package/dist/commands/init.js +360 -105
- package/dist/commands/profiles.js +49 -13
- package/dist/commands/scan.js +64 -2
- package/dist/commands/ssh-setup.js +34 -0
- package/dist/config-explainer.js +2 -1
- package/dist/config-loader.js +131 -41
- package/dist/index.js +3 -1
- package/dist/profile-resolver.js +35 -18
- package/package.json +1 -1
package/dist/commands/connect.js
CHANGED
|
@@ -41,6 +41,7 @@ const commander_1 = require("commander");
|
|
|
41
41
|
const chalk_1 = __importDefault(require("chalk"));
|
|
42
42
|
const api_1 = require("../api");
|
|
43
43
|
const genbox_selector_1 = require("../genbox-selector");
|
|
44
|
+
const ssh_config_1 = require("../ssh-config");
|
|
44
45
|
const os = __importStar(require("os"));
|
|
45
46
|
const path = __importStar(require("path"));
|
|
46
47
|
const fs = __importStar(require("fs"));
|
|
@@ -80,9 +81,13 @@ exports.connectCommand = new commander_1.Command('connect')
|
|
|
80
81
|
console.error(chalk_1.default.yellow(`Genbox '${target.name}' is still provisioning (no IP). Please wait.`));
|
|
81
82
|
return;
|
|
82
83
|
}
|
|
83
|
-
// 2.
|
|
84
|
+
// 2. Ensure SSH config exists (in case background setup hasn't finished)
|
|
85
|
+
if (!(0, ssh_config_1.hasSshConfigEntry)(target.name)) {
|
|
86
|
+
(0, ssh_config_1.addSshConfigEntry)({ name: target.name, ipAddress: target.ipAddress });
|
|
87
|
+
}
|
|
88
|
+
// 3. Get Key
|
|
84
89
|
const keyPath = getPrivateSshKey();
|
|
85
|
-
//
|
|
90
|
+
// 4. Connect
|
|
86
91
|
console.log(chalk_1.default.dim(`Connecting to ${chalk_1.default.bold(target.name)} (${target.ipAddress})...`));
|
|
87
92
|
const sshArgs = [
|
|
88
93
|
'-i', keyPath,
|
package/dist/commands/create.js
CHANGED
|
@@ -48,64 +48,22 @@ const config_loader_1 = require("../config-loader");
|
|
|
48
48
|
const profile_resolver_1 = require("../profile-resolver");
|
|
49
49
|
const api_1 = require("../api");
|
|
50
50
|
const ssh_config_1 = require("../ssh-config");
|
|
51
|
+
const schema_v4_1 = require("../schema-v4");
|
|
51
52
|
const child_process_1 = require("child_process");
|
|
52
53
|
/**
|
|
53
|
-
*
|
|
54
|
+
* Spawn a background process to poll for IP and add SSH config
|
|
55
|
+
* This runs detached so the main process can exit immediately
|
|
54
56
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
67
|
-
}
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Find SSH private key
|
|
72
|
-
*/
|
|
73
|
-
function findSshKeyPath() {
|
|
74
|
-
const home = os.homedir();
|
|
75
|
-
const keyPaths = [
|
|
76
|
-
path.join(home, '.ssh', 'id_ed25519'),
|
|
77
|
-
path.join(home, '.ssh', 'id_rsa'),
|
|
78
|
-
];
|
|
79
|
-
for (const keyPath of keyPaths) {
|
|
80
|
-
if (fs.existsSync(keyPath)) {
|
|
81
|
-
return keyPath;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Wait for SSH to be available on the server
|
|
88
|
-
*/
|
|
89
|
-
async function waitForSsh(ipAddress, maxAttempts = 30, delayMs = 5000) {
|
|
90
|
-
const keyPath = findSshKeyPath();
|
|
91
|
-
if (!keyPath)
|
|
92
|
-
return false;
|
|
93
|
-
const sshOpts = `-i ${keyPath} -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=5`;
|
|
94
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
95
|
-
try {
|
|
96
|
-
(0, child_process_1.execSync)(`ssh ${sshOpts} dev@${ipAddress} "echo 'SSH ready'"`, {
|
|
97
|
-
encoding: 'utf8',
|
|
98
|
-
timeout: 10000,
|
|
99
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
100
|
-
});
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
// SSH not ready yet
|
|
105
|
-
}
|
|
106
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
107
|
-
}
|
|
108
|
-
return false;
|
|
57
|
+
function spawnSshConfigSetup(genboxId, name) {
|
|
58
|
+
// Get the path to the CLI executable
|
|
59
|
+
const cliPath = process.argv[1];
|
|
60
|
+
// Spawn genbox ssh-setup in background
|
|
61
|
+
const child = (0, child_process_1.spawn)(process.execPath, [cliPath, 'ssh-setup', genboxId, name], {
|
|
62
|
+
detached: true,
|
|
63
|
+
stdio: 'ignore',
|
|
64
|
+
});
|
|
65
|
+
// Allow parent to exit independently
|
|
66
|
+
child.unref();
|
|
109
67
|
}
|
|
110
68
|
async function provisionGenbox(payload) {
|
|
111
69
|
return (0, api_1.fetchApi)('/genboxes', {
|
|
@@ -159,11 +117,13 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
159
117
|
// Load configuration
|
|
160
118
|
const configLoader = new config_loader_1.ConfigLoader();
|
|
161
119
|
const loadResult = await configLoader.load();
|
|
162
|
-
|
|
120
|
+
const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
|
|
121
|
+
if (!loadResult.config || configVersion === 'unknown') {
|
|
163
122
|
// Fall back to legacy v1/v2 handling
|
|
164
123
|
await createLegacy(name, options);
|
|
165
124
|
return;
|
|
166
125
|
}
|
|
126
|
+
// Support both v3 and v4 configs
|
|
167
127
|
const config = loadResult.config;
|
|
168
128
|
const profileResolver = new profile_resolver_1.ProfileResolver(configLoader);
|
|
169
129
|
// Build create options
|
|
@@ -210,7 +170,8 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
210
170
|
const publicKey = getPublicSshKey();
|
|
211
171
|
// Check if SSH auth is needed for git
|
|
212
172
|
let privateKeyContent;
|
|
213
|
-
const
|
|
173
|
+
const v3Config = config;
|
|
174
|
+
const usesSSH = v3Config.git_auth?.method === 'ssh' ||
|
|
214
175
|
Object.values(config.repos || {}).some(r => r.auth === 'ssh');
|
|
215
176
|
if (usesSSH && !options.yes) {
|
|
216
177
|
const injectKey = await prompts.confirm({
|
|
@@ -231,40 +192,23 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
231
192
|
try {
|
|
232
193
|
const genbox = await provisionGenbox(payload);
|
|
233
194
|
spinner.succeed(chalk_1.default.green(`Genbox '${name}' created!`));
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (ipAddress) {
|
|
240
|
-
spinner.succeed(`IP address assigned: ${ipAddress}`);
|
|
241
|
-
genbox.ipAddress = ipAddress;
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
spinner.fail('Timed out waiting for IP. Run `genbox status` to check later.');
|
|
245
|
-
displayGenboxInfo(genbox, resolved);
|
|
246
|
-
return;
|
|
195
|
+
// Add SSH config immediately if IP available, otherwise spawn background process
|
|
196
|
+
if (genbox.ipAddress) {
|
|
197
|
+
const sshAdded = (0, ssh_config_1.addSshConfigEntry)({ name, ipAddress: genbox.ipAddress });
|
|
198
|
+
if (sshAdded) {
|
|
199
|
+
console.log(chalk_1.default.dim(` SSH config added: ssh ${(0, ssh_config_1.getSshAlias)(name)}`));
|
|
247
200
|
}
|
|
248
201
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
spinner.succeed(chalk_1.default.green('SSH is ready!'));
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
spinner.warn('SSH not ready yet. Server may still be booting.');
|
|
257
|
-
}
|
|
258
|
-
// Add SSH config
|
|
259
|
-
const sshAdded = (0, ssh_config_1.addSshConfigEntry)({
|
|
260
|
-
name,
|
|
261
|
-
ipAddress,
|
|
262
|
-
});
|
|
263
|
-
if (sshAdded) {
|
|
264
|
-
console.log(chalk_1.default.dim(` SSH config added: ssh ${(0, ssh_config_1.getSshAlias)(name)}`));
|
|
202
|
+
else if (genbox._id) {
|
|
203
|
+
// Spawn background process to poll for IP and add SSH config
|
|
204
|
+
spawnSshConfigSetup(genbox._id, name);
|
|
205
|
+
console.log(chalk_1.default.dim(' SSH config will be added once IP is assigned.'));
|
|
265
206
|
}
|
|
266
207
|
// Display results
|
|
267
208
|
displayGenboxInfo(genbox, resolved);
|
|
209
|
+
// Inform user about server provisioning
|
|
210
|
+
console.log('');
|
|
211
|
+
console.log(chalk_1.default.dim('Server is provisioning. Run `genbox connect` once ready.'));
|
|
268
212
|
}
|
|
269
213
|
catch (error) {
|
|
270
214
|
spinner.fail(chalk_1.default.red(`Failed to create Genbox: ${error.message}`));
|
|
@@ -449,9 +393,12 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
|
|
|
449
393
|
envVarsFromFile[match[1]] = value;
|
|
450
394
|
}
|
|
451
395
|
}
|
|
452
|
-
// Determine API_URL based on profile's connect_to
|
|
453
|
-
|
|
454
|
-
|
|
396
|
+
// Determine API_URL based on profile's connect_to (v3) or default_connection (v4)
|
|
397
|
+
let connectTo;
|
|
398
|
+
if (resolved.profile && config.profiles?.[resolved.profile]) {
|
|
399
|
+
const profile = config.profiles[resolved.profile];
|
|
400
|
+
connectTo = (0, config_loader_1.getProfileConnection)(profile);
|
|
401
|
+
}
|
|
455
402
|
let apiUrl;
|
|
456
403
|
if (connectTo) {
|
|
457
404
|
// Use the environment-specific API URL (e.g., STAGING_API_URL)
|
|
@@ -699,39 +646,28 @@ async function createLegacy(name, options) {
|
|
|
699
646
|
gitToken: envVars.GIT_TOKEN,
|
|
700
647
|
});
|
|
701
648
|
spinner.succeed(chalk_1.default.green(`Genbox '${name}' created!`));
|
|
702
|
-
//
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (ipAddress) {
|
|
708
|
-
spinner.succeed(`IP address assigned: ${ipAddress}`);
|
|
709
|
-
genbox.ipAddress = ipAddress;
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
spinner.fail('Timed out waiting for IP. Run `genbox status` to check later.');
|
|
713
|
-
return;
|
|
649
|
+
// Add SSH config immediately if IP available, otherwise spawn background process
|
|
650
|
+
if (genbox.ipAddress) {
|
|
651
|
+
const sshAdded = (0, ssh_config_1.addSshConfigEntry)({ name, ipAddress: genbox.ipAddress });
|
|
652
|
+
if (sshAdded) {
|
|
653
|
+
console.log(chalk_1.default.dim(` SSH config added: ssh ${(0, ssh_config_1.getSshAlias)(name)}`));
|
|
714
654
|
}
|
|
715
655
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
spinner.succeed(chalk_1.default.green('SSH is ready!'));
|
|
721
|
-
}
|
|
722
|
-
else {
|
|
723
|
-
spinner.warn('SSH not ready yet. Server may still be booting.');
|
|
724
|
-
}
|
|
725
|
-
// Add SSH config
|
|
726
|
-
const sshAdded = (0, ssh_config_1.addSshConfigEntry)({ name, ipAddress });
|
|
727
|
-
if (sshAdded) {
|
|
728
|
-
console.log(chalk_1.default.dim(` SSH config added: ssh ${(0, ssh_config_1.getSshAlias)(name)}`));
|
|
656
|
+
else if (genbox._id) {
|
|
657
|
+
// Spawn background process to poll for IP and add SSH config
|
|
658
|
+
spawnSshConfigSetup(genbox._id, name);
|
|
659
|
+
console.log(chalk_1.default.dim(' SSH config will be added once IP is assigned.'));
|
|
729
660
|
}
|
|
730
661
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
731
662
|
console.log(` ${chalk_1.default.bold('Environment:')} ${name}`);
|
|
732
663
|
console.log(` ${chalk_1.default.bold('Status:')} ${chalk_1.default.yellow(genbox.status)}`);
|
|
733
|
-
|
|
664
|
+
if (genbox.ipAddress) {
|
|
665
|
+
console.log(` ${chalk_1.default.bold('IP:')} ${genbox.ipAddress}`);
|
|
666
|
+
}
|
|
734
667
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
668
|
+
// Inform user about server provisioning
|
|
669
|
+
console.log('');
|
|
670
|
+
console.log(chalk_1.default.dim('Server is provisioning. Run `genbox connect` once ready.'));
|
|
735
671
|
}
|
|
736
672
|
catch (error) {
|
|
737
673
|
spinner.fail(chalk_1.default.red(`Failed: ${error.message}`));
|