@_xtribe/cli 1.0.0-beta.12 → 1.0.0-beta.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.
Files changed (2) hide show
  1. package/install-tribe.js +134 -23
  2. package/package.json +1 -1
package/install-tribe.js CHANGED
@@ -392,14 +392,43 @@ async function checkColimaRunning() {
392
392
  }
393
393
  }
394
394
 
395
+ async function checkColimaHasKubernetes() {
396
+ try {
397
+ const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
398
+ const status = execSync(`${colimaPath} status`, { encoding: 'utf8' });
399
+ // Check if kubernetes is mentioned in the status
400
+ return status.toLowerCase().includes('kubernetes');
401
+ } catch {
402
+ return false;
403
+ }
404
+ }
405
+
395
406
  async function startColimaWithKubernetes() {
396
407
  const spinner = ora('Starting Colima with Kubernetes...').start();
397
408
 
398
409
  try {
399
410
  // Check if already running
400
411
  if (await checkColimaRunning()) {
401
- spinner.succeed('Colima is already running');
402
- return true;
412
+ // Check if it has Kubernetes enabled
413
+ if (await checkColimaHasKubernetes()) {
414
+ spinner.succeed('Colima is already running with Kubernetes');
415
+ return true;
416
+ } else {
417
+ spinner.text = 'Colima is running without Kubernetes. Restarting with Kubernetes...';
418
+
419
+ // Stop existing Colima
420
+ const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
421
+ try {
422
+ execSync(`${colimaPath} stop`, {
423
+ stdio: 'pipe',
424
+ timeout: 30000
425
+ });
426
+ // Wait for it to fully stop
427
+ await new Promise(resolve => setTimeout(resolve, 5000));
428
+ } catch (stopError) {
429
+ log.warning('Failed to stop Colima, attempting to start anyway...');
430
+ }
431
+ }
403
432
  }
404
433
 
405
434
  // Start Colima with Kubernetes enabled
@@ -407,9 +436,14 @@ async function startColimaWithKubernetes() {
407
436
  const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
408
437
  execSync(`${colimaPath} start --kubernetes --cpu 4 --memory 8 --disk 20`, {
409
438
  stdio: 'pipe',
410
- env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` }
439
+ env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` },
440
+ timeout: 300000 // 5 minute timeout for first start
411
441
  });
412
442
 
443
+ // Give Colima a moment to stabilize after starting
444
+ spinner.text = 'Waiting for Colima to stabilize...';
445
+ await new Promise(resolve => setTimeout(resolve, 5000));
446
+
413
447
  // Verify it's working and set context
414
448
  const kubectlPath = await findCommand('kubectl') || 'kubectl';
415
449
  execSync(`${kubectlPath} version --client`, { stdio: 'ignore' });
@@ -467,28 +501,89 @@ async function deployTribeCluster() {
467
501
  TRIBE_DEPLOYMENT_YAML: destYaml
468
502
  };
469
503
 
470
- // Wait for Kubernetes API to be ready
471
- spinner.text = 'Waiting for Kubernetes API server...';
504
+ // Wait for Kubernetes to be fully ready
505
+ spinner.text = 'Waiting for Kubernetes to be ready...';
506
+ const kubectlPath = await findCommand('kubectl') || 'kubectl';
472
507
  let apiReady = false;
508
+ let contextSet = false;
509
+
510
+ // First, wait for the API server to be accessible
473
511
  for (let i = 0; i < 30; i++) {
474
512
  try {
475
- const kubectlPath = await findCommand('kubectl') || 'kubectl';
476
- execSync(`${kubectlPath} cluster-info`, {
477
- stdio: 'ignore',
478
- env: env
513
+ // Try to get cluster info - this will work regardless of port
514
+ const clusterInfo = execSync(`${kubectlPath} cluster-info`, {
515
+ encoding: 'utf8',
516
+ env: env,
517
+ stdio: 'pipe'
479
518
  });
480
- apiReady = true;
481
- break;
482
- } catch {
483
- // Wait 2 seconds and try again
519
+
520
+ // Check if we got valid cluster info
521
+ if (clusterInfo && clusterInfo.includes('is running at')) {
522
+ apiReady = true;
523
+ spinner.text = 'Kubernetes API server is ready';
524
+
525
+ // Extract the actual API server URL for logging
526
+ const urlMatch = clusterInfo.match(/is running at (https?:\/\/[^\s]+)/);
527
+ if (urlMatch) {
528
+ log.info(`Kubernetes API server: ${urlMatch[1]}`);
529
+ }
530
+ break;
531
+ }
532
+ } catch (error) {
533
+ spinner.text = `Waiting for Kubernetes API server... (${i+1}/30)`;
484
534
  await new Promise(resolve => setTimeout(resolve, 2000));
485
535
  }
486
536
  }
487
537
 
488
538
  if (!apiReady) {
489
- spinner.warn('Kubernetes API server not ready, deployment may fail');
539
+ spinner.warn('Kubernetes API server not ready after 60 seconds');
540
+ log.info('Deployment may fail. You can try running "tribe start" manually later.');
541
+ return false;
490
542
  }
491
543
 
544
+ // Set the kubectl context to colima
545
+ spinner.text = 'Setting kubectl context...';
546
+ try {
547
+ execSync(`${kubectlPath} config use-context colima`, {
548
+ stdio: 'ignore',
549
+ env: env
550
+ });
551
+ contextSet = true;
552
+ } catch {
553
+ log.warning('Could not set kubectl context to colima');
554
+ }
555
+
556
+ // Wait for the node to be ready
557
+ spinner.text = 'Waiting for Kubernetes node to be ready...';
558
+ let nodeReady = false;
559
+ for (let i = 0; i < 20; i++) {
560
+ try {
561
+ const nodeStatus = execSync(`${kubectlPath} get nodes -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}'`, {
562
+ encoding: 'utf8',
563
+ env: env
564
+ }).trim();
565
+
566
+ if (nodeStatus === 'True') {
567
+ nodeReady = true;
568
+ spinner.text = 'Kubernetes node is ready';
569
+ break;
570
+ }
571
+ } catch {
572
+ // Node might not be registered yet
573
+ }
574
+ spinner.text = `Waiting for Kubernetes node... (${i+1}/20)`;
575
+ await new Promise(resolve => setTimeout(resolve, 3000));
576
+ }
577
+
578
+ if (!nodeReady) {
579
+ spinner.warn('Kubernetes node not ready after 60 seconds');
580
+ log.info('The cluster may still be initializing. Proceeding with deployment...');
581
+ }
582
+
583
+ // Small delay to let everything stabilize
584
+ spinner.text = 'Starting TRIBE deployment...';
585
+ await new Promise(resolve => setTimeout(resolve, 2000));
586
+
492
587
  // Execute tribe start
493
588
  execSync(`${tribePath} start`, {
494
589
  stdio: 'pipe',
@@ -504,7 +599,19 @@ async function deployTribeCluster() {
504
599
  } catch (error) {
505
600
  spinner.fail('Failed to deploy TRIBE cluster');
506
601
  log.error(error.message);
507
- log.info('You can manually deploy later with: tribe start');
602
+
603
+ // Check if this is a Kubernetes connectivity issue
604
+ if (error.message && error.message.includes('connection refused')) {
605
+ log.warning('\nIt appears Kubernetes is not ready or not enabled.');
606
+ log.info('Troubleshooting steps:');
607
+ log.info('1. Check Colima status: colima status');
608
+ log.info('2. If running without Kubernetes, restart it:');
609
+ log.info(' colima stop');
610
+ log.info(' colima start --kubernetes');
611
+ log.info('3. Then run: tribe start');
612
+ } else {
613
+ log.info('You can manually deploy later with: tribe start');
614
+ }
508
615
  return false;
509
616
  }
510
617
  }
@@ -590,14 +697,11 @@ async function main() {
590
697
  console.log('\n' + chalk.bold.green('✨ TRIBE is ready!'));
591
698
  console.log('');
592
699
 
593
- // Check if PATH needs updating
594
- const needsPathUpdate = !process.env.PATH.includes(binDir);
595
- if (needsPathUpdate) {
596
- log.warning('PATH update required for current shell:');
597
- console.log(chalk.yellow(` source ~/.${process.env.SHELL?.includes('zsh') ? 'zshrc' : 'bashrc'}`));
598
- console.log(' ' + chalk.gray('or restart your terminal'));
599
- console.log('');
600
- }
700
+ // Always show PATH update reminder since npx runs in a subprocess
701
+ log.warning('To use tribe commands, update your PATH:');
702
+ console.log(chalk.yellow(` source ~/.${process.env.SHELL?.includes('zsh') ? 'zshrc' : 'bashrc'}`));
703
+ console.log(' ' + chalk.gray('or restart your terminal'));
704
+ console.log('');
601
705
 
602
706
  log.info('Quick start:');
603
707
  console.log(' tribe # Launch interactive CLI');
@@ -618,6 +722,13 @@ async function main() {
618
722
  console.log('\n' + chalk.bold.green('✨ TRIBE is ready!'));
619
723
  log.success('Cluster is already running');
620
724
  console.log('');
725
+
726
+ // Always show PATH update reminder since npx runs in a subprocess
727
+ log.warning('To use tribe commands, update your PATH:');
728
+ console.log(chalk.yellow(` source ~/.${process.env.SHELL?.includes('zsh') ? 'zshrc' : 'bashrc'}`));
729
+ console.log(' ' + chalk.gray('or restart your terminal'));
730
+ console.log('');
731
+
621
732
  log.info('Commands:');
622
733
  console.log(' tribe # Launch interactive CLI');
623
734
  console.log(' tribe status # Check status');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_xtribe/cli",
3
- "version": "1.0.0-beta.12",
3
+ "version": "1.0.0-beta.15",
4
4
  "description": "TRIBE multi-agent development system - Zero to productive with one command",
5
5
  "main": "install-tribe.js",
6
6
  "bin": {