Skip to content

Commit 0ca3ca1

Browse files
authored
Merge pull request #27 from devanshu-puri/fix/run-command-services
fix: improve run command resilience, skip misconfigured services (#17)
2 parents 6c89c36 + 5a0126f commit 0ca3ca1

File tree

7 files changed

+195
-3639
lines changed

7 files changed

+195
-3639
lines changed

bin/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#!/usr/bin/env node
22
import { Command } from 'commander';
33
import chalk from 'chalk';
4+
45
import { scaffoldMonorepo, addService, scaffoldPlugin } from './lib/scaffold.js';
56
import { runDev } from './lib/dev.js';
67

78
const program = new Command();
89

10+
911
program
1012
.name('create-polyglot')
1113
.description('Scaffold a polyglot microservice monorepo');

bin/lib/dev.js

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ export async function runDev({ docker=false } = {}) {
4141
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
4242
const servicesDir = path.join(cwd, 'services');
4343
if (!fs.existsSync(servicesDir)) {
44-
console.error(chalk.red('services/ directory not found.'));
45-
process.exit(1);
46-
}
44+
console.log(chalk.yellow('⚠️ services/ directory not found. No local services will be started.'));
45+
//no return - continue to check cfg.services
46+
}
4747
if (docker) {
4848
console.log(chalk.cyan('🛳 Starting via docker compose...'));
4949
const compose = spawn('docker', ['compose', 'up', '--build'], { stdio: 'inherit' });
@@ -53,20 +53,44 @@ export async function runDev({ docker=false } = {}) {
5353
console.log(chalk.cyan('🚀 Starting services locally (best effort)...'));
5454
const procs = [];
5555
const healthPromises = [];
56+
57+
if (fs.existsSync(servicesDir)) {
5658
for (const svc of cfg.services) {
5759
const svcPath = path.join(cwd, svc.path);
60+
5861
if (!fs.existsSync(svcPath)) continue;
5962
// Only auto-run node & frontend services (others require language runtime dev tasks)
6063
if (!['node','frontend'].includes(svc.type)) continue;
64+
6165
const pkgPath = path.join(svcPath, 'package.json');
62-
if (!fs.existsSync(pkgPath)) continue;
63-
let pkg;
64-
try { pkg = JSON.parse(fs.readFileSync(pkgPath,'utf-8')); } catch { continue; }
65-
if (!pkg.scripts || !pkg.scripts.dev) continue;
66-
const color = colorFor(svc.name);
67-
const pm = detectPM(cwd);
68-
const cmd = pm === 'yarn' ? 'yarn' : pm === 'pnpm' ? 'pnpm' : pm === 'bun' ? 'bun' : 'npm';
69-
const args = pm === 'yarn' ? ['run','dev'] : ['run','dev'];
66+
if (!fs.existsSync(pkgPath)) {
67+
console.log(`Skipping ${svc.name} (no package.json)`);
68+
continue;
69+
}
70+
71+
let pkg;
72+
try {
73+
pkg = JSON.parse(fs.readFileSync(pkgPath,'utf-8'));
74+
} catch {
75+
console.log(chalk.yellow(`Skipping ${svc.name} (invalid package.json)`));
76+
continue;
77+
}
78+
79+
// Determine which script to run
80+
const useScript = pkg.scripts?.dev ? 'dev' : pkg.scripts?.start ? 'start' : null;
81+
if (!useScript) {
82+
console.log(chalk.yellow(`Skipping ${svc.name} (no "dev" or "start" script)`));
83+
continue;
84+
}
85+
if (useScript === 'start') {
86+
console.log(`running start instead of dev for ${svc.name}`);
87+
}
88+
89+
const color = colorFor(svc.name);
90+
const pm = detectPM(svcPath);
91+
const cmd = pm === 'yarn' ? 'yarn' : pm === 'pnpm' ? 'pnpm' : pm === 'bun' ? 'bun' : 'npm';
92+
const args = ['run', useScript];
93+
7094
const child = spawn(cmd, args, { cwd: svcPath, env: { ...process.env, PORT: String(svc.port) }, shell: true });
7195
procs.push(child);
7296
child.stdout.on('data', d => process.stdout.write(color(`[${svc.name}] `) + d.toString()));
@@ -76,18 +100,27 @@ export async function runDev({ docker=false } = {}) {
76100
});
77101
// health check
78102
const healthUrl = `http://localhost:${svc.port}/health`;
79-
const hp = waitForHealth(healthUrl).then(ok => {
103+
const hp = waitForHealth(healthUrl,30000).then(ok => {
80104
const msg = ok ? chalk.green(`✔ health OK ${svc.name} ${healthUrl}`) : chalk.yellow(`⚠ health timeout ${svc.name} ${healthUrl}`);
81105
console.log(msg);
82106
});
83107
healthPromises.push(hp);
84108
}
109+
}
110+
85111
if (!procs.length) {
86112
console.log(chalk.yellow('No auto-runnable Node/Frontend services found. Use --docker to start all via compose.'));
113+
// ✅ FIXED: Exit cleanly when running in CI/test mode
114+
if (process.env.CI === 'true') {
115+
process.exit(0);
116+
}
87117
}
88118
await Promise.all(healthPromises);
89-
console.log(chalk.blue('Watching services. Press Ctrl+C to exit.'));
90-
process.on('SIGINT', () => { procs.forEach(p => p.kill('SIGINT')); process.exit(0); });
119+
120+
if (procs.length > 0) {
121+
console.log(chalk.blue('Watching services. Press Ctrl+C to exit.'));
122+
process.on('SIGINT', () => { procs.forEach(p => p.kill('SIGINT')); process.exit(0); });
123+
}
91124
}
92125

93126
function detectPM(root) {

0 commit comments

Comments
 (0)