Skip to content

Commit c903358

Browse files
committed
fix: install pnpm/yarn/bun on remote, read entry point from package.json, fix PM2 log fetch
- Install pnpm/yarn/bun globally via npm when detected as pkg manager and not yet present on the remote server (was: command not found) - Read PM2 script path from package.json `main` field, default to index.js — was hardcoded to `index` which caused PM2 start failure - Read PM2 log files directly (~/.pm2/logs/*.log) instead of using `pm2 logs --nostream` which streamed indefinitely instead of dumping
1 parent b65c830 commit c903358

2 files changed

Lines changed: 28 additions & 8 deletions

File tree

src/domain/deploy/backend-strategy.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { execa } from 'execa';
2+
import { readFile } from 'node:fs/promises';
23
import { pathExists } from 'fs-extra';
34
import { resolve } from 'path';
45
import type { ShipnodeConfig } from '../../shared/types.js';
@@ -52,6 +53,15 @@ export class BackendStrategy implements DeploymentStrategy {
5253
commands.push(`ln -sf "${this.config.remotePath}/shared/.env" .env`);
5354
}
5455

56+
// Ensure third-party package managers are available on the remote
57+
if (pkgManager === 'pnpm') {
58+
commands.push(`command -v pnpm &>/dev/null || npm install -g pnpm`);
59+
} else if (pkgManager === 'yarn') {
60+
commands.push(`command -v yarn &>/dev/null || npm install -g yarn`);
61+
} else if (pkgManager === 'bun') {
62+
commands.push(`command -v bun &>/dev/null || npm install -g bun`);
63+
}
64+
5565
commands.push(installCmd);
5666

5767
if (!ctx.skipBuild) {
@@ -66,7 +76,8 @@ export class BackendStrategy implements DeploymentStrategy {
6676
async startApp(ctx: StrategyContext): Promise<void> {
6777
if (!this.config.pm2) return;
6878

69-
const ecosystemContent = this.generateEcosystemFile();
79+
const script = await this.resolveEntryPoint();
80+
const ecosystemContent = this.generateEcosystemFile(script);
7081
const ecosystemPath = this.config.zeroDowntime
7182
? `${this.config.remotePath}/shared/ecosystem.config.cjs`
7283
: `${ctx.workDir}/ecosystem.config.cjs`;
@@ -83,7 +94,17 @@ export class BackendStrategy implements DeploymentStrategy {
8394
);
8495
}
8596

86-
private generateEcosystemFile(): string {
97+
private async resolveEntryPoint(): Promise<string> {
98+
try {
99+
const pkg = JSON.parse(await readFile(resolve(this.cwd, 'package.json'), 'utf-8'));
100+
if (pkg.main) return pkg.main;
101+
} catch {
102+
// ignore
103+
}
104+
return 'index.js';
105+
}
106+
107+
private generateEcosystemFile(script: string): string {
87108
if (!this.config.pm2) return '';
88109

89110
const port = this.config.backend?.port ?? 3000;
@@ -94,7 +115,7 @@ export class BackendStrategy implements DeploymentStrategy {
94115
return `module.exports = {
95116
apps: [{
96117
name: '${name}',
97-
script: 'index',
118+
script: '${script}',
98119
instances: ${instances},
99120
exec_mode: 'cluster',
100121
max_memory_restart: '${maxMemory}',

src/services/health.service.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,15 @@ export class HealthCheckService {
4444
}
4545
}
4646

47-
// Fetch PM2 logs to help diagnose why the app didn't start
47+
// Read PM2 log files directly to avoid streaming behaviour of `pm2 logs`
4848
let diagnostics = '';
4949
if (this.config.pm2?.name) {
50-
const nodeVersion = this.config.nodeVersion === 'lts' ? '24' : this.config.nodeVersion;
51-
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
50+
const name = this.config.pm2.name;
5251
const logResult = await this.executor.exec(
53-
`${mise}; mise exec node@${nodeVersion} -- pm2 logs ${this.config.pm2.name} --lines 30 --nostream 2>&1 || true`,
52+
`{ tail -15 ~/.pm2/logs/${name}-error.log 2>/dev/null; tail -15 ~/.pm2/logs/${name}-out.log 2>/dev/null; } || true`,
5453
).catch(() => ({ stdout: '', stderr: '' }));
5554
const logs = logResult.stdout.trim();
56-
if (logs) diagnostics = `\n\nPM2 logs (last 30 lines):\n${logs}`;
55+
if (logs) diagnostics = `\n\nPM2 logs:\n${logs}`;
5756
}
5857

5958
throw new HealthCheckError(

0 commit comments

Comments
 (0)