@devalade/shipnode 2.0.0
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/cli/commands/backup.d.ts +14 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +144 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/ci.d.ts +5 -0
- package/dist/cli/commands/ci.d.ts.map +1 -0
- package/dist/cli/commands/ci.js +222 -0
- package/dist/cli/commands/ci.js.map +1 -0
- package/dist/cli/commands/cloudflare.d.ts +10 -0
- package/dist/cli/commands/cloudflare.d.ts.map +1 -0
- package/dist/cli/commands/cloudflare.js +166 -0
- package/dist/cli/commands/cloudflare.js.map +1 -0
- package/dist/cli/commands/config.d.ts +10 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +99 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +6 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +95 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +5 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +86 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/eject.d.ts +2 -0
- package/dist/cli/commands/eject.d.ts.map +1 -0
- package/dist/cli/commands/eject.js +74 -0
- package/dist/cli/commands/eject.js.map +1 -0
- package/dist/cli/commands/env.d.ts +4 -0
- package/dist/cli/commands/env.d.ts.map +1 -0
- package/dist/cli/commands/env.js +50 -0
- package/dist/cli/commands/env.js.map +1 -0
- package/dist/cli/commands/harden.d.ts +4 -0
- package/dist/cli/commands/harden.d.ts.map +1 -0
- package/dist/cli/commands/harden.js +110 -0
- package/dist/cli/commands/harden.js.map +1 -0
- package/dist/cli/commands/help.d.ts +2 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +99 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +246 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +5 -0
- package/dist/cli/commands/logs.d.ts.map +1 -0
- package/dist/cli/commands/logs.js +17 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/metrics.d.ts +4 -0
- package/dist/cli/commands/metrics.d.ts.map +1 -0
- package/dist/cli/commands/metrics.js +21 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +71 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/restart.d.ts +4 -0
- package/dist/cli/commands/restart.d.ts.map +1 -0
- package/dist/cli/commands/restart.js +14 -0
- package/dist/cli/commands/restart.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +5 -0
- package/dist/cli/commands/rollback.d.ts.map +1 -0
- package/dist/cli/commands/rollback.js +49 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +5 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +69 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +4 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +46 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +4 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +49 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +4 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +14 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/unlock.d.ts +4 -0
- package/dist/cli/commands/unlock.d.ts.map +1 -0
- package/dist/cli/commands/unlock.js +27 -0
- package/dist/cli/commands/unlock.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +2 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +63 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/commands/user.d.ts +17 -0
- package/dist/cli/commands/user.d.ts.map +1 -0
- package/dist/cli/commands/user.js +98 -0
- package/dist/cli/commands/user.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +218 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/prompt.d.ts +2 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +11 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/runner.d.ts +34 -0
- package/dist/cli/runner.d.ts.map +1 -0
- package/dist/cli/runner.js +44 -0
- package/dist/cli/runner.js.map +1 -0
- package/dist/cli/ui.d.ts +9 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +26 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/assembly.d.ts +14 -0
- package/dist/config/assembly.d.ts.map +1 -0
- package/dist/config/assembly.js +62 -0
- package/dist/config/assembly.js.map +1 -0
- package/dist/config/builder.d.ts +33 -0
- package/dist/config/builder.d.ts.map +1 -0
- package/dist/config/builder.js +119 -0
- package/dist/config/builder.js.map +1 -0
- package/dist/config/loader.d.ts +3 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +20 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +416 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +75 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/domain/deploy/backend-strategy.d.ts +15 -0
- package/dist/domain/deploy/backend-strategy.d.ts.map +1 -0
- package/dist/domain/deploy/backend-strategy.js +110 -0
- package/dist/domain/deploy/backend-strategy.js.map +1 -0
- package/dist/domain/deploy/frontend-strategy.d.ts +13 -0
- package/dist/domain/deploy/frontend-strategy.d.ts.map +1 -0
- package/dist/domain/deploy/frontend-strategy.js +64 -0
- package/dist/domain/deploy/frontend-strategy.js.map +1 -0
- package/dist/domain/deploy/orchestrator.d.ts +34 -0
- package/dist/domain/deploy/orchestrator.d.ts.map +1 -0
- package/dist/domain/deploy/orchestrator.js +149 -0
- package/dist/domain/deploy/orchestrator.js.map +1 -0
- package/dist/domain/deploy/strategy.d.ts +44 -0
- package/dist/domain/deploy/strategy.d.ts.map +1 -0
- package/dist/domain/deploy/strategy.js +2 -0
- package/dist/domain/deploy/strategy.js.map +1 -0
- package/dist/domain/framework/detector.d.ts +7 -0
- package/dist/domain/framework/detector.d.ts.map +1 -0
- package/dist/domain/framework/detector.js +109 -0
- package/dist/domain/framework/detector.js.map +1 -0
- package/dist/domain/release/manager.d.ts +22 -0
- package/dist/domain/release/manager.d.ts.map +1 -0
- package/dist/domain/release/manager.js +100 -0
- package/dist/domain/release/manager.js.map +1 -0
- package/dist/domain/remote/executor.d.ts +16 -0
- package/dist/domain/remote/executor.d.ts.map +1 -0
- package/dist/domain/remote/executor.js +2 -0
- package/dist/domain/remote/executor.js.map +1 -0
- package/dist/domain/validation/ip.d.ts +5 -0
- package/dist/domain/validation/ip.d.ts.map +1 -0
- package/dist/domain/validation/ip.js +38 -0
- package/dist/domain/validation/ip.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/ssh/connection.d.ts +19 -0
- package/dist/infrastructure/ssh/connection.d.ts.map +1 -0
- package/dist/infrastructure/ssh/connection.js +89 -0
- package/dist/infrastructure/ssh/connection.js.map +1 -0
- package/dist/services/caddy.service.d.ts +12 -0
- package/dist/services/caddy.service.d.ts.map +1 -0
- package/dist/services/caddy.service.js +56 -0
- package/dist/services/caddy.service.js.map +1 -0
- package/dist/services/deploy.service.d.ts +19 -0
- package/dist/services/deploy.service.d.ts.map +1 -0
- package/dist/services/deploy.service.js +53 -0
- package/dist/services/deploy.service.js.map +1 -0
- package/dist/services/health.service.d.ts +13 -0
- package/dist/services/health.service.d.ts.map +1 -0
- package/dist/services/health.service.js +38 -0
- package/dist/services/health.service.js.map +1 -0
- package/dist/shared/constants.d.ts +127 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +85 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/errors.d.ts +27 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +53 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/types.d.ts +116 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export function cmdHelp() {
|
|
3
|
+
console.log(`
|
|
4
|
+
${chalk.bold.blue('ShipNode')} v2.0.0 - Deploy Node.js apps to a single VPS
|
|
5
|
+
|
|
6
|
+
${chalk.bold('USAGE')}
|
|
7
|
+
shipnode <command> [options]
|
|
8
|
+
|
|
9
|
+
${chalk.bold('CORE')}
|
|
10
|
+
${chalk.green('init')} Initialize a new shipnode.config.ts
|
|
11
|
+
${chalk.green('setup')} Setup a new server with required dependencies
|
|
12
|
+
${chalk.green('deploy')} Deploy your application
|
|
13
|
+
${chalk.green('doctor')} Check local and remote configuration
|
|
14
|
+
${chalk.green('status')} Check application status
|
|
15
|
+
|
|
16
|
+
${chalk.bold('RELEASE MANAGEMENT')}
|
|
17
|
+
${chalk.green('rollback')} Roll back to a previous release
|
|
18
|
+
${chalk.green('migrate')} Migrate existing deploy to zero-downtime structure
|
|
19
|
+
|
|
20
|
+
${chalk.bold('ENVIRONMENT')}
|
|
21
|
+
${chalk.green('env')} Upload local .env file to the server
|
|
22
|
+
${chalk.green('run')} <cmd> Run a one-off command on the production server
|
|
23
|
+
|
|
24
|
+
${chalk.bold('PROCESS MANAGEMENT')}
|
|
25
|
+
${chalk.green('logs')} Show application logs
|
|
26
|
+
${chalk.green('restart')} Restart the application
|
|
27
|
+
${chalk.green('stop')} Stop the application
|
|
28
|
+
${chalk.green('metrics')} Open PM2 monitoring dashboard
|
|
29
|
+
|
|
30
|
+
${chalk.bold('SECURITY & MAINTENANCE')}
|
|
31
|
+
${chalk.green('harden')} Apply server security hardening
|
|
32
|
+
${chalk.green('unlock')} Clear a stuck deployment lock
|
|
33
|
+
|
|
34
|
+
${chalk.bold('USERS')}
|
|
35
|
+
${chalk.green('user sync')} Sync .shipnode/users.yml to server
|
|
36
|
+
${chalk.green('user list')} List non-system users on server
|
|
37
|
+
${chalk.green('user remove')} <u> Remove a user from the server
|
|
38
|
+
|
|
39
|
+
${chalk.bold('BACKUP')}
|
|
40
|
+
${chalk.green('backup setup')} Install backup script and systemd timer
|
|
41
|
+
${chalk.green('backup run')} Run a backup immediately
|
|
42
|
+
${chalk.green('backup status')} Show backup timer and last run
|
|
43
|
+
${chalk.green('backup list')} List recent backups in S3
|
|
44
|
+
|
|
45
|
+
${chalk.bold('CLOUDFLARE')}
|
|
46
|
+
${chalk.green('cloudflare init')} Install cloudflared, configure tunnel/DNS
|
|
47
|
+
${chalk.green('cloudflare audit')} Verify DNS and tunnel configuration
|
|
48
|
+
${chalk.green('cloudflare status')} Show cloudflared service status
|
|
49
|
+
|
|
50
|
+
${chalk.bold('CI/CD')}
|
|
51
|
+
${chalk.green('ci github')} Generate GitHub Actions deploy workflow
|
|
52
|
+
${chalk.green('ci env-sync')} Sync .env and config to GitHub secrets
|
|
53
|
+
|
|
54
|
+
${chalk.bold('CONFIGURATION')}
|
|
55
|
+
${chalk.green('config show')} Show resolved configuration
|
|
56
|
+
${chalk.green('config validate')} Validate configuration file
|
|
57
|
+
${chalk.green('config path')} Print path to config file
|
|
58
|
+
|
|
59
|
+
${chalk.bold('CUSTOMIZATION')}
|
|
60
|
+
${chalk.green('eject')} [target] Eject PM2/Caddy templates (pm2, caddy, all)
|
|
61
|
+
${chalk.green('upgrade')} Upgrade shipnode to the latest version
|
|
62
|
+
|
|
63
|
+
${chalk.bold('OPTIONS')}
|
|
64
|
+
--dry-run Show what would be deployed (deploy only)
|
|
65
|
+
--skip-build Skip the build step (deploy only)
|
|
66
|
+
--steps <n> Releases to go back (rollback only)
|
|
67
|
+
--lines <n> Log lines to show (logs only, default: 100)
|
|
68
|
+
--tty Force interactive TTY (run only)
|
|
69
|
+
--security Run security audit (doctor only)
|
|
70
|
+
--all Skip confirmation (ci env-sync only)
|
|
71
|
+
--config <path> Use a specific config file
|
|
72
|
+
|
|
73
|
+
${chalk.bold('EXAMPLES')}
|
|
74
|
+
${chalk.dim('# First deploy')}
|
|
75
|
+
shipnode init && shipnode setup && shipnode deploy
|
|
76
|
+
|
|
77
|
+
${chalk.dim('# Roll back one release')}
|
|
78
|
+
shipnode rollback
|
|
79
|
+
|
|
80
|
+
${chalk.dim('# Run a database migration')}
|
|
81
|
+
shipnode run "npx prisma migrate deploy"
|
|
82
|
+
|
|
83
|
+
${chalk.dim('# Open interactive shell on server')}
|
|
84
|
+
shipnode run bash
|
|
85
|
+
|
|
86
|
+
${chalk.dim('# Push .env then restart')}
|
|
87
|
+
shipnode env && shipnode restart
|
|
88
|
+
|
|
89
|
+
${chalk.dim('# Set up GitHub Actions CI')}
|
|
90
|
+
shipnode ci github && shipnode ci env-sync
|
|
91
|
+
|
|
92
|
+
${chalk.dim('# Harden server security')}
|
|
93
|
+
shipnode harden
|
|
94
|
+
|
|
95
|
+
${chalk.bold('DOCUMENTATION')}
|
|
96
|
+
https://github.com/devalade/shipnode
|
|
97
|
+
`);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GhH"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { writeFile, mkdir, pathExists } from 'fs-extra';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
import { detectFramework, detectPkgManager } from '../../domain/framework/detector.js';
|
|
5
|
+
import { isValidIpOrHostname, isValidPort } from '../../domain/validation/ip.js';
|
|
6
|
+
import { ORM_PATTERNS } from '../../shared/constants.js';
|
|
7
|
+
import { ui } from '../ui.js';
|
|
8
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
9
|
+
function ask(question, defaultValue) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const prompt = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;
|
|
12
|
+
rl.question(prompt, (answer) => {
|
|
13
|
+
resolve(answer.trim() || defaultValue || '');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export async function cmdInit(cwd, options) {
|
|
18
|
+
ui.info('Initializing ShipNode configuration...');
|
|
19
|
+
const detection = await detectFramework(cwd);
|
|
20
|
+
const pkgManager = await detectPkgManager(cwd);
|
|
21
|
+
const isBackend = detection.appType === 'backend';
|
|
22
|
+
const appName = await getAppName(cwd);
|
|
23
|
+
const defaultPort = detection.port ?? 3000;
|
|
24
|
+
if (options.nonInteractive || options.print) {
|
|
25
|
+
const config = generateConfig({
|
|
26
|
+
app: isBackend ? 'backend' : 'frontend',
|
|
27
|
+
appName,
|
|
28
|
+
backendPort: defaultPort,
|
|
29
|
+
pkgManager: pkgManager ?? undefined,
|
|
30
|
+
});
|
|
31
|
+
if (options.print) {
|
|
32
|
+
console.log(config);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const configPath = resolve(cwd, 'shipnode.config.ts');
|
|
36
|
+
const exists = await pathExists(configPath);
|
|
37
|
+
if (exists) {
|
|
38
|
+
ui.warn('shipnode.config.ts already exists. Use --force to overwrite.');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
await writeFile(configPath, config, 'utf-8');
|
|
42
|
+
ui.success('Created shipnode.config.ts');
|
|
43
|
+
await generateShipnodeDir(cwd, detection.orm);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
ui.info(`Detected: ${detection.name} (${detection.appType})`);
|
|
47
|
+
if (detection.orm) {
|
|
48
|
+
ui.info(`ORM: ${detection.orm}`);
|
|
49
|
+
}
|
|
50
|
+
const appType = await ask('App type', isBackend ? 'backend' : 'frontend');
|
|
51
|
+
const sshHost = await ask('SSH host');
|
|
52
|
+
if (!isValidIpOrHostname(sshHost)) {
|
|
53
|
+
ui.error('Invalid host. Must be an IP address or hostname.');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
const sshUser = await ask('SSH user', 'deploy');
|
|
57
|
+
const sshPortStr = await ask('SSH port', '22');
|
|
58
|
+
const sshPort = parseInt(sshPortStr, 10);
|
|
59
|
+
if (!isValidPort(sshPort)) {
|
|
60
|
+
ui.error('Invalid port number.');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const remotePath = await ask('Remote deploy path', `/var/www/${appName}`);
|
|
64
|
+
let pm2Name = '';
|
|
65
|
+
let backendPort = defaultPort;
|
|
66
|
+
let domain = '';
|
|
67
|
+
let zeroDowntime = true;
|
|
68
|
+
let healthCheckPath = '/health';
|
|
69
|
+
if (appType === 'backend') {
|
|
70
|
+
pm2Name = await ask('PM2 app name', appName);
|
|
71
|
+
backendPort = parseInt(await ask('Backend port', String(defaultPort)), 10);
|
|
72
|
+
domain = await ask('Domain (optional)', '');
|
|
73
|
+
const zd = await ask('Enable zero-downtime deployments?', 'yes');
|
|
74
|
+
zeroDowntime = zd.toLowerCase().startsWith('y');
|
|
75
|
+
if (zeroDowntime) {
|
|
76
|
+
healthCheckPath = await ask('Health check path', '/health');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
domain = await ask('Domain (optional)', '');
|
|
81
|
+
}
|
|
82
|
+
rl.close();
|
|
83
|
+
const config = generateConfig({
|
|
84
|
+
app: appType,
|
|
85
|
+
appName,
|
|
86
|
+
sshHost,
|
|
87
|
+
sshUser,
|
|
88
|
+
sshPort,
|
|
89
|
+
remotePath,
|
|
90
|
+
pm2Name,
|
|
91
|
+
backendPort,
|
|
92
|
+
domain: domain || undefined,
|
|
93
|
+
zeroDowntime,
|
|
94
|
+
healthCheckPath,
|
|
95
|
+
pkgManager: pkgManager ?? undefined,
|
|
96
|
+
});
|
|
97
|
+
const configPath = resolve(cwd, 'shipnode.config.ts');
|
|
98
|
+
const exists = await pathExists(configPath);
|
|
99
|
+
if (exists) {
|
|
100
|
+
ui.warn('shipnode.config.ts already exists. Use --force to overwrite.');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await writeFile(configPath, config, 'utf-8');
|
|
104
|
+
ui.success('Created shipnode.config.ts');
|
|
105
|
+
await generateShipnodeDir(cwd, detection.orm);
|
|
106
|
+
}
|
|
107
|
+
async function getAppName(cwd) {
|
|
108
|
+
try {
|
|
109
|
+
const { readFile } = await import('fs/promises');
|
|
110
|
+
const pkgPath = resolve(cwd, 'package.json');
|
|
111
|
+
const content = await readFile(pkgPath, 'utf-8');
|
|
112
|
+
const pkg = JSON.parse(content);
|
|
113
|
+
if (pkg.name) {
|
|
114
|
+
return pkg.name.replace(/^@[^/]+\//, '').replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// ignore
|
|
119
|
+
}
|
|
120
|
+
return cwd.split('/').pop() ?? 'myapp';
|
|
121
|
+
}
|
|
122
|
+
async function generateShipnodeDir(cwd, detectedOrm) {
|
|
123
|
+
const dir = resolve(cwd, '.shipnode');
|
|
124
|
+
await mkdir(dir, { recursive: true });
|
|
125
|
+
const preDeployPath = resolve(dir, 'pre-deploy.sh');
|
|
126
|
+
const postDeployPath = resolve(dir, 'post-deploy.sh');
|
|
127
|
+
const ignorePath = resolve(cwd, '.shipnodeignore');
|
|
128
|
+
if (!(await pathExists(preDeployPath))) {
|
|
129
|
+
await writeFile(preDeployPath, generatePreDeployHook(detectedOrm), 'utf-8');
|
|
130
|
+
await import('fs/promises').then((fs) => fs.chmod(preDeployPath, 0o755));
|
|
131
|
+
}
|
|
132
|
+
if (!(await pathExists(postDeployPath))) {
|
|
133
|
+
await writeFile(postDeployPath, generatePostDeployHook(), 'utf-8');
|
|
134
|
+
await import('fs/promises').then((fs) => fs.chmod(postDeployPath, 0o755));
|
|
135
|
+
}
|
|
136
|
+
if (!(await pathExists(ignorePath))) {
|
|
137
|
+
await writeFile(ignorePath, generateShipnodeIgnore(), 'utf-8');
|
|
138
|
+
}
|
|
139
|
+
const ormMsg = detectedOrm ? ` with ${detectedOrm} commands` : '';
|
|
140
|
+
ui.success(`Generated .shipnode/ hooks${ormMsg} and .shipnodeignore`);
|
|
141
|
+
}
|
|
142
|
+
function generatePreDeployHook(detectedOrm) {
|
|
143
|
+
const ormCommands = Object.entries(ORM_PATTERNS)
|
|
144
|
+
.filter(([, p]) => p.migrateCmd)
|
|
145
|
+
.map(([name, p]) => {
|
|
146
|
+
const active = name === detectedOrm;
|
|
147
|
+
const prefix = active ? '' : '# ';
|
|
148
|
+
const lines = [`${prefix}# ${name}${active ? ' (detected)' : ''}`];
|
|
149
|
+
if (p.generateCmd)
|
|
150
|
+
lines.push(`${prefix}${p.generateCmd}`);
|
|
151
|
+
lines.push(`${prefix}${p.migrateCmd}`);
|
|
152
|
+
return lines.join('\n');
|
|
153
|
+
})
|
|
154
|
+
.join('\n\n');
|
|
155
|
+
return `#!/bin/bash
|
|
156
|
+
# ShipNode Pre-Deploy Hook
|
|
157
|
+
# Runs BEFORE the new release is activated. Exit non-zero to abort.
|
|
158
|
+
#
|
|
159
|
+
# Env vars: RELEASE_PATH REMOTE_PATH PM2_APP_NAME BACKEND_PORT SHARED_ENV_PATH
|
|
160
|
+
set -e
|
|
161
|
+
|
|
162
|
+
if [ -f "$SHARED_ENV_PATH" ]; then
|
|
163
|
+
set -a; source "$SHARED_ENV_PATH"; set +a
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
echo "Pre-deploy: \${RELEASE_PATH}"
|
|
167
|
+
|
|
168
|
+
# ── Database migrations ──────────────────────────────────────────
|
|
169
|
+
${ormCommands}
|
|
170
|
+
# ────────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
echo "Pre-deploy hook complete"
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
function generatePostDeployHook() {
|
|
176
|
+
return `#!/bin/bash
|
|
177
|
+
# ShipNode Post-Deploy Hook
|
|
178
|
+
# Runs AFTER deployment. Failure is logged but does NOT trigger rollback.
|
|
179
|
+
#
|
|
180
|
+
# Env vars: RELEASE_PATH RELEASE_TIMESTAMP REMOTE_PATH PM2_APP_NAME BACKEND_PORT
|
|
181
|
+
set -e
|
|
182
|
+
|
|
183
|
+
echo "Post-deploy: \${RELEASE_PATH}"
|
|
184
|
+
|
|
185
|
+
# Examples:
|
|
186
|
+
# curl -s http://localhost:\${BACKEND_PORT}/api/warmup
|
|
187
|
+
# npm run cache:clear
|
|
188
|
+
|
|
189
|
+
echo "Post-deploy hook complete"
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
function generateShipnodeIgnore() {
|
|
193
|
+
return `# .shipnodeignore — files excluded from rsync (same syntax as .gitignore)
|
|
194
|
+
node_modules/
|
|
195
|
+
.env
|
|
196
|
+
.env.*
|
|
197
|
+
.git/
|
|
198
|
+
*.log
|
|
199
|
+
dist/
|
|
200
|
+
build/
|
|
201
|
+
coverage/
|
|
202
|
+
.DS_Store
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
205
|
+
function generateConfig(opts) {
|
|
206
|
+
const lines = [
|
|
207
|
+
"import { shipnode } from '@devalade/shipnode';",
|
|
208
|
+
'',
|
|
209
|
+
'export default shipnode',
|
|
210
|
+
` .${opts.app}()`,
|
|
211
|
+
];
|
|
212
|
+
const sshOpts = [];
|
|
213
|
+
if (opts.sshHost)
|
|
214
|
+
sshOpts.push(`host: '${opts.sshHost}'`);
|
|
215
|
+
if (opts.sshUser)
|
|
216
|
+
sshOpts.push(`user: '${opts.sshUser}'`);
|
|
217
|
+
if (opts.sshPort && opts.sshPort !== 22)
|
|
218
|
+
sshOpts.push(`port: ${opts.sshPort}`);
|
|
219
|
+
if (sshOpts.length > 0) {
|
|
220
|
+
lines.push(` .ssh({ ${sshOpts.join(', ')} })`);
|
|
221
|
+
}
|
|
222
|
+
if (opts.remotePath) {
|
|
223
|
+
lines.push(` .deployTo('${opts.remotePath}')`);
|
|
224
|
+
}
|
|
225
|
+
if (opts.pm2Name) {
|
|
226
|
+
lines.push(` .pm2('${opts.pm2Name}')`);
|
|
227
|
+
}
|
|
228
|
+
if (opts.backendPort && opts.backendPort !== 3000) {
|
|
229
|
+
lines.push(` .port(${opts.backendPort})`);
|
|
230
|
+
}
|
|
231
|
+
if (opts.domain) {
|
|
232
|
+
lines.push(` .domain('${opts.domain}')`);
|
|
233
|
+
}
|
|
234
|
+
if (opts.zeroDowntime !== false) {
|
|
235
|
+
lines.push(' .zeroDowntime()');
|
|
236
|
+
}
|
|
237
|
+
if (opts.healthCheckPath && opts.healthCheckPath !== '/health') {
|
|
238
|
+
lines.push(` .healthCheck('${opts.healthCheckPath}')`);
|
|
239
|
+
}
|
|
240
|
+
else if (opts.healthCheckPath) {
|
|
241
|
+
lines.push(` .healthCheck('${opts.healthCheckPath}')`);
|
|
242
|
+
}
|
|
243
|
+
lines.push('');
|
|
244
|
+
return lines.join('\n');
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAEA,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { runRemoteCommand } from '../runner.js';
|
|
2
|
+
export async function cmdLogs(cwd, options) {
|
|
3
|
+
await runRemoteCommand(cwd, async ({ config, executor }) => {
|
|
4
|
+
if (config.app !== 'backend' || !config.pm2?.name) {
|
|
5
|
+
throw new Error('Logs only available for backend apps with PM2');
|
|
6
|
+
}
|
|
7
|
+
const lines = options.lines ?? 100;
|
|
8
|
+
const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
|
|
9
|
+
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
|
|
10
|
+
const result = await executor.exec(`${mise}; mise exec "node@${nodeVersion}" -- pm2 logs ${config.pm2.name} --lines ${lines} --nostream`);
|
|
11
|
+
if (result.stdout)
|
|
12
|
+
process.stdout.write(result.stdout + '\n');
|
|
13
|
+
if (result.stderr)
|
|
14
|
+
process.stderr.write(result.stderr + '\n');
|
|
15
|
+
}, { configPath: options.config });
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,OAA4C;IACrF,MAAM,gBAAgB,CACpB,GAAG,EACH,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7B,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC;QACnC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;QAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;QAClF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,GAAG,IAAI,qBAAqB,WAAW,iBAAiB,MAAM,CAAC,GAAG,CAAC,IAAI,YAAY,KAAK,aAAa,CACtG,CAAC;QACF,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChE,CAAC,EACD,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import { loadConfig } from '../../config/loader.js';
|
|
3
|
+
export async function cmdMetrics(cwd, options) {
|
|
4
|
+
const config = await loadConfig(cwd, options.config);
|
|
5
|
+
if (config.app !== 'backend' || !config.pm2?.name) {
|
|
6
|
+
throw new Error('Metrics only available for backend apps with PM2');
|
|
7
|
+
}
|
|
8
|
+
const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
|
|
9
|
+
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
|
|
10
|
+
const remoteCmd = `${mise}; mise exec "node@${nodeVersion}" -- pm2 monit`;
|
|
11
|
+
const sshArgs = [
|
|
12
|
+
'-t',
|
|
13
|
+
'-p', String(config.ssh.port),
|
|
14
|
+
...(config.ssh.identityFile ? ['-i', config.ssh.identityFile] : []),
|
|
15
|
+
`${config.ssh.user}@${config.ssh.host}`,
|
|
16
|
+
remoteCmd,
|
|
17
|
+
];
|
|
18
|
+
const result = await execa('ssh', sshArgs, { stdio: 'inherit', reject: false });
|
|
19
|
+
process.exit(result.exitCode ?? 0);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAA4B;IACxE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;IAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;IAClF,MAAM,SAAS,GAAG,GAAG,IAAI,qBAAqB,WAAW,gBAAgB,CAAC;IAE1E,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;QACvC,SAAS;KACV,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGzF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { confirm } from '../prompt.js';
|
|
2
|
+
import { runRemoteCommand } from '../runner.js';
|
|
3
|
+
import { ReleaseManager } from '../../domain/release/manager.js';
|
|
4
|
+
import { ui } from '../ui.js';
|
|
5
|
+
export async function cmdMigrate(cwd, options) {
|
|
6
|
+
await runRemoteCommand(cwd, async ({ config, executor }) => {
|
|
7
|
+
if (!config.zeroDowntime) {
|
|
8
|
+
throw new Error('Migration requires zeroDowntime: true in your shipnode.config.ts. ' +
|
|
9
|
+
'Enable it and re-run to migrate to the zero-downtime release structure.');
|
|
10
|
+
}
|
|
11
|
+
const remotePath = config.remotePath;
|
|
12
|
+
ui.heading('Zero-Downtime Migration');
|
|
13
|
+
ui.info(`Remote path: ${remotePath}`);
|
|
14
|
+
ui.warn('This will reorganise your remote deployment directory into releases/shared/current structure.');
|
|
15
|
+
const ok = await confirm('Proceed with migration?');
|
|
16
|
+
if (!ok) {
|
|
17
|
+
ui.info('Migration cancelled.');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const timestamp = new Date()
|
|
21
|
+
.toISOString()
|
|
22
|
+
.replace(/[:.]/g, '-')
|
|
23
|
+
.replace('Z', '');
|
|
24
|
+
ui.info('Creating release structure directories...');
|
|
25
|
+
await executor.exec(`mkdir -p "${remotePath}/releases" "${remotePath}/shared" "${remotePath}/.shipnode"`);
|
|
26
|
+
await executor.exec(`echo '[]' > "${remotePath}/.shipnode/releases.json"`);
|
|
27
|
+
ui.success('Directory structure created');
|
|
28
|
+
ui.info(`Creating release snapshot: ${timestamp}...`);
|
|
29
|
+
await executor.exec(`mkdir -p "${remotePath}/releases/${timestamp}"`);
|
|
30
|
+
await executor.exec(`find "${remotePath}" -maxdepth 1 -mindepth 1 ` +
|
|
31
|
+
`! -name releases ! -name shared ! -name .shipnode ! -name current ` +
|
|
32
|
+
`-exec mv {} "${remotePath}/releases/${timestamp}/" \\;`);
|
|
33
|
+
ui.success('Existing files moved to release directory');
|
|
34
|
+
// Move .env to shared and symlink it back
|
|
35
|
+
const envCheckResult = await executor.exec(`[ -f "${remotePath}/releases/${timestamp}/.env" ] && echo "exists" || echo "missing"`);
|
|
36
|
+
if (envCheckResult.stdout.trim() === 'exists') {
|
|
37
|
+
ui.info('Moving .env to shared directory...');
|
|
38
|
+
await executor.exec(`mv "${remotePath}/releases/${timestamp}/.env" "${remotePath}/shared/.env"`);
|
|
39
|
+
await executor.exec(`ln -sf "${remotePath}/shared/.env" "${remotePath}/releases/${timestamp}/.env"`);
|
|
40
|
+
ui.success('Shared .env linked');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
ui.warn('No .env found in release — skipping shared env setup.');
|
|
44
|
+
}
|
|
45
|
+
ui.info('Creating current symlink...');
|
|
46
|
+
await executor.exec(`ln -sfn "${remotePath}/releases/${timestamp}" "${remotePath}/current"`);
|
|
47
|
+
ui.success('Symlink created: current → releases/' + timestamp);
|
|
48
|
+
// Reload PM2 if applicable
|
|
49
|
+
if (config.app === 'backend' && config.pm2?.name) {
|
|
50
|
+
const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
|
|
51
|
+
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
|
|
52
|
+
ui.info('Reloading PM2 from new path...');
|
|
53
|
+
await executor.exec(`${mise}; mise exec node@${nodeVersion} -- pm2 reload ${config.pm2.name} --update-env`);
|
|
54
|
+
ui.success('PM2 reloaded');
|
|
55
|
+
}
|
|
56
|
+
// Record the initial migrated release
|
|
57
|
+
const releases = new ReleaseManager(executor, remotePath, config.keepReleases);
|
|
58
|
+
await releases.recordRelease({
|
|
59
|
+
timestamp,
|
|
60
|
+
status: 'success',
|
|
61
|
+
duration: 0,
|
|
62
|
+
gitCommit: undefined,
|
|
63
|
+
});
|
|
64
|
+
ui.success('Release recorded in .shipnode/releases.json');
|
|
65
|
+
ui.heading('Migration Complete');
|
|
66
|
+
ui.success(`Active release: ${timestamp}`);
|
|
67
|
+
ui.info('Your app is now running under the zero-downtime release structure.');
|
|
68
|
+
ui.info('Future deployments will use releases/ and atomic symlink switches.');
|
|
69
|
+
}, { configPath: options.config });
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBzF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { runRemoteCommand } from '../runner.js';
|
|
2
|
+
import { ui } from '../ui.js';
|
|
3
|
+
export async function cmdRestart(cwd, options) {
|
|
4
|
+
await runRemoteCommand(cwd, async ({ config, executor }) => {
|
|
5
|
+
if (config.app !== 'backend' || !config.pm2?.name) {
|
|
6
|
+
throw new Error('Restart only available for backend apps with PM2');
|
|
7
|
+
}
|
|
8
|
+
const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
|
|
9
|
+
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
|
|
10
|
+
await executor.exec(`${mise}; mise exec "node@${nodeVersion}" -- pm2 reload ${config.pm2.name} --update-env`);
|
|
11
|
+
ui.success(`App '${config.pm2.name}' restarted successfully`);
|
|
12
|
+
}, { configPath: options.config });
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=restart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAA4B;IACxE,MAAM,gBAAgB,CACpB,GAAG,EACH,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7B,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;QAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;QAClF,MAAM,QAAQ,CAAC,IAAI,CACjB,GAAG,IAAI,qBAAqB,WAAW,mBAAmB,MAAM,CAAC,GAAG,CAAC,IAAI,eAAe,CACzF,CAAC;QACF,EAAE,CAAC,OAAO,CAAC,QAAQ,MAAM,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC,CAAC;IAChE,CAAC,EACD,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/rollback.ts"],"names":[],"mappings":"AAMA,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CA6Df"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { runRemoteCommand } from '../runner.js';
|
|
2
|
+
import { ReleaseManager } from '../../domain/release/manager.js';
|
|
3
|
+
import { HealthCheckService } from '../../services/health.service.js';
|
|
4
|
+
import { ui } from '../ui.js';
|
|
5
|
+
import { confirm } from '../prompt.js';
|
|
6
|
+
export async function cmdRollback(cwd, options) {
|
|
7
|
+
await runRemoteCommand(cwd, async ({ config, executor }) => {
|
|
8
|
+
if (!config.zeroDowntime) {
|
|
9
|
+
throw new Error('Rollback requires zero-downtime deployment. Enable zeroDowntime in config.');
|
|
10
|
+
}
|
|
11
|
+
const releases = new ReleaseManager(executor, config.remotePath, config.keepReleases);
|
|
12
|
+
const stepsBack = options.steps ?? 1;
|
|
13
|
+
ui.info('Fetching release history...');
|
|
14
|
+
const allReleases = await releases.listReleases();
|
|
15
|
+
if (allReleases.length < 2) {
|
|
16
|
+
throw new Error('No previous release to roll back to.');
|
|
17
|
+
}
|
|
18
|
+
const targetIdx = allReleases.length - 1 - stepsBack;
|
|
19
|
+
if (targetIdx < 0) {
|
|
20
|
+
throw new Error(`Cannot go back ${stepsBack} step(s) — only ${allReleases.length} release(s) recorded.`);
|
|
21
|
+
}
|
|
22
|
+
const current = allReleases[allReleases.length - 1];
|
|
23
|
+
const target = allReleases[targetIdx];
|
|
24
|
+
ui.warn(`Current release: ${current.timestamp}`);
|
|
25
|
+
ui.warn(`Target release: ${target.timestamp}`);
|
|
26
|
+
const ok = await confirm('Proceed with rollback?');
|
|
27
|
+
if (!ok) {
|
|
28
|
+
ui.info('Rollback cancelled.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const targetPath = `${config.remotePath}/releases/${target.timestamp}`;
|
|
32
|
+
await releases.switchSymlink(targetPath);
|
|
33
|
+
ui.success('Symlink switched');
|
|
34
|
+
if (config.app === 'backend' && config.pm2?.name) {
|
|
35
|
+
const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
|
|
36
|
+
const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
|
|
37
|
+
await executor.exec(`${mise}; mise exec node@${nodeVersion} -- pm2 reload ${config.pm2.name} --update-env`);
|
|
38
|
+
ui.success('PM2 reloaded');
|
|
39
|
+
}
|
|
40
|
+
if (config.app === 'backend' && config.healthCheck.enabled) {
|
|
41
|
+
ui.info('Running health check...');
|
|
42
|
+
const health = new HealthCheckService(executor, config);
|
|
43
|
+
await health.perform();
|
|
44
|
+
ui.success('Health check passed');
|
|
45
|
+
}
|
|
46
|
+
ui.success(`Rolled back to ${target.timestamp}`);
|
|
47
|
+
}, { configPath: options.config });
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=rollback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../../src/cli/commands/rollback.ts"],"names":[],"mappings":"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"}
|