Skip to content

Commit b56c4e5

Browse files
committed
fix(cli): render every app in deploy --dry-run
The dry-run block called `getActiveApp(config)` and printed a single plan, hiding every additional app in a workspace. Split the output into a workspace header (host, remote path, node, app list) followed by one plan block per app in `config.apps`, using the per-app namespace-prefixed PM2 names so the preview matches what actually ships.
1 parent 7ccf7c3 commit b56c4e5

1 file changed

Lines changed: 45 additions & 26 deletions

File tree

src/cli/commands/deploy.ts

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { DeployService } from '../../services/deploy.service.js';
44
import { LoggingExecutor } from '../../infrastructure/ssh/logging-executor.js';
55
import { runRemoteCommand } from '../runner.js';
66
import { ui } from '../ui.js';
7-
import type { ShipnodeConfig } from '../../shared/types.js';
7+
import type { ShipnodeConfig, ShipnodeApp } from '../../shared/types.js';
88
import { getActiveApp } from '../../domain/workspace.js';
9-
import { getDeploymentName, getWebApp } from '../../domain/pm2/apps.js';
9+
import { getPm2Name } from '../../domain/pm2/apps.js';
1010

1111
export async function cmdDeploy(cwd: string, options: { dryRun?: boolean; skipBuild?: boolean; app?: string; config?: string }): Promise<void> {
1212
const config = await loadConfig(cwd, options.config);
@@ -45,25 +45,31 @@ export async function cmdDeploy(cwd: string, options: { dryRun?: boolean; skipBu
4545
);
4646
}
4747

48-
function printDryRun(config: ShipnodeConfig, skipBuild: boolean): void {
49-
ui.banner();
50-
51-
const app = getActiveApp(config);
48+
function renderAppPlan(app: ShipnodeApp, skipBuild: boolean): string {
49+
const namespace = app.pm2?.apps[0]?.name;
50+
const web = app.pm2?.apps.find((a) => a.port !== undefined);
5251

5352
const serverRows: [string, string][] = [
5453
['App type', app.appType],
55-
['Host', `${config.ssh.user}@${config.ssh.host}:${config.ssh.port}`],
56-
['Remote path', config.remotePath],
54+
['App root', app.appRoot ?? '(repo root)'],
5755
['Keep releases', String(app.keepReleases)],
5856
];
5957

6058
if (app.appType === 'backend') {
61-
const apps = app.pm2?.apps ?? [];
62-
if (apps.length) {
63-
serverRows.push(['PM2 deployment', getDeploymentName(config) ?? '']);
64-
serverRows.push(['PM2 apps', apps.map((a) => a.port !== undefined ? `${a.name}(web:${a.port})` : a.name).join(', ')]);
59+
const pm2Apps = app.pm2?.apps ?? [];
60+
if (pm2Apps.length && namespace) {
61+
serverRows.push(['PM2 deployment', namespace]);
62+
serverRows.push([
63+
'PM2 apps',
64+
pm2Apps
65+
.map((a) =>
66+
a.port !== undefined
67+
? `${getPm2Name(namespace, a.name)}(web:${a.port})`
68+
: getPm2Name(namespace, a.name),
69+
)
70+
.join(', '),
71+
]);
6572
}
66-
const web = getWebApp(config);
6773
if (web) serverRows.push(['Port', String(web.port)]);
6874
}
6975

@@ -96,17 +102,30 @@ function printDryRun(config: ShipnodeConfig, skipBuild: boolean): void {
96102

97103
const flowRows: [string, string][] = steps.map((s, i) => [`${i + 1}.`, s as string]);
98104

99-
ui.note(
100-
[
101-
chalk.bold('Server'),
102-
...serverRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(12))} ${v}`),
103-
'',
104-
chalk.bold('Build'),
105-
...buildRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(12))} ${v}`),
106-
'',
107-
chalk.bold('Deploy flow'),
108-
...flowRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(4))} ${v}`),
109-
].join('\n'),
110-
'Dry run — no changes will be made',
111-
);
105+
return [
106+
chalk.bold(`App: ${app.name}`),
107+
...serverRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(14))} ${v}`),
108+
'',
109+
chalk.bold(' Build'),
110+
...buildRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(14))} ${v}`),
111+
'',
112+
chalk.bold(' Deploy flow'),
113+
...flowRows.map(([k, v]) => ` ${chalk.dim(k.padEnd(4))} ${v}`),
114+
].join('\n');
115+
}
116+
117+
function printDryRun(config: ShipnodeConfig, skipBuild: boolean): void {
118+
ui.banner();
119+
120+
const header = [
121+
chalk.bold('Workspace'),
122+
` ${chalk.dim('Host'.padEnd(14))} ${config.ssh.user}@${config.ssh.host}:${config.ssh.port}`,
123+
` ${chalk.dim('Remote path'.padEnd(14))} ${config.remotePath}`,
124+
` ${chalk.dim('Node'.padEnd(14))} ${config.nodeVersion}`,
125+
` ${chalk.dim('Apps'.padEnd(14))} ${config.apps.map((a) => a.name).join(', ')}`,
126+
].join('\n');
127+
128+
const perApp = config.apps.map((app) => renderAppPlan(app, skipBuild)).join('\n\n');
129+
130+
ui.note([header, '', perApp].join('\n'), 'Dry run — no changes will be made');
112131
}

0 commit comments

Comments
 (0)