git-push-deploy-cli 0.2.2 → 0.6.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.
Files changed (61) hide show
  1. package/README.md +466 -108
  2. package/dist/commands/config.d.ts +10 -0
  3. package/dist/commands/config.d.ts.map +1 -0
  4. package/dist/commands/config.js +295 -0
  5. package/dist/commands/config.js.map +1 -0
  6. package/dist/commands/daemon.d.ts +10 -0
  7. package/dist/commands/daemon.d.ts.map +1 -0
  8. package/dist/commands/daemon.js +67 -0
  9. package/dist/commands/daemon.js.map +1 -0
  10. package/dist/commands/deploy.d.ts +2 -1
  11. package/dist/commands/deploy.d.ts.map +1 -1
  12. package/dist/commands/deploy.js +23 -5
  13. package/dist/commands/deploy.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +36 -19
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/install.d.ts.map +1 -1
  18. package/dist/commands/install.js +98 -3
  19. package/dist/commands/install.js.map +1 -1
  20. package/dist/commands/logs.d.ts +1 -0
  21. package/dist/commands/logs.d.ts.map +1 -1
  22. package/dist/commands/logs.js +4 -1
  23. package/dist/commands/logs.js.map +1 -1
  24. package/dist/commands/release.d.ts +5 -1
  25. package/dist/commands/release.d.ts.map +1 -1
  26. package/dist/commands/release.js +204 -6
  27. package/dist/commands/release.js.map +1 -1
  28. package/dist/commands/rollback.d.ts +17 -0
  29. package/dist/commands/rollback.d.ts.map +1 -0
  30. package/dist/commands/rollback.js +169 -0
  31. package/dist/commands/rollback.js.map +1 -0
  32. package/dist/commands/stage.d.ts +4 -0
  33. package/dist/commands/stage.d.ts.map +1 -1
  34. package/dist/commands/stage.js +52 -4
  35. package/dist/commands/stage.js.map +1 -1
  36. package/dist/commands/status.d.ts.map +1 -1
  37. package/dist/commands/status.js +15 -2
  38. package/dist/commands/status.js.map +1 -1
  39. package/dist/config/loader.d.ts +1 -0
  40. package/dist/config/loader.d.ts.map +1 -1
  41. package/dist/config/loader.js +1 -1
  42. package/dist/config/loader.js.map +1 -1
  43. package/dist/config/types.d.ts +112 -14
  44. package/dist/config/types.d.ts.map +1 -1
  45. package/dist/config/types.js +20 -0
  46. package/dist/config/types.js.map +1 -1
  47. package/dist/index.js +31 -2
  48. package/dist/index.js.map +1 -1
  49. package/dist/utils/git.d.ts +43 -0
  50. package/dist/utils/git.d.ts.map +1 -1
  51. package/dist/utils/git.js +98 -0
  52. package/dist/utils/git.js.map +1 -1
  53. package/dist/utils/notifications.d.ts +6 -0
  54. package/dist/utils/notifications.d.ts.map +1 -0
  55. package/dist/utils/notifications.js +188 -0
  56. package/dist/utils/notifications.js.map +1 -0
  57. package/dist/utils/shell.d.ts +4 -0
  58. package/dist/utils/shell.d.ts.map +1 -1
  59. package/dist/utils/shell.js +18 -0
  60. package/dist/utils/shell.js.map +1 -1
  61. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ interface ConfigOptions {
2
+ edit?: string;
3
+ list?: boolean;
4
+ }
5
+ /**
6
+ * Config command - create or edit .git-deploy.json
7
+ */
8
+ export declare function configCommand(options?: ConfigOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAqOA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8E9E"}
@@ -0,0 +1,295 @@
1
+ import chalk from 'chalk';
2
+ import * as readline from 'readline';
3
+ import { existsSync, writeFileSync, readFileSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { getServers } from '../config/types.js';
6
+ const CONFIG_FILENAME = '.git-deploy.json';
7
+ /**
8
+ * Get the primary server from config (handles both server and servers)
9
+ */
10
+ function getExistingServer(config) {
11
+ if (!config)
12
+ return undefined;
13
+ if (config.servers && config.servers.length > 0)
14
+ return config.servers[0];
15
+ return config.server;
16
+ }
17
+ /**
18
+ * Create readline interface
19
+ */
20
+ function createPrompt() {
21
+ return readline.createInterface({
22
+ input: process.stdin,
23
+ output: process.stdout
24
+ });
25
+ }
26
+ /**
27
+ * Prompt for input with default value
28
+ */
29
+ async function prompt(rl, question, defaultValue) {
30
+ const defaultText = defaultValue ? chalk.gray(` [${defaultValue}]`) : '';
31
+ return new Promise((resolve) => {
32
+ rl.question(`${question}${defaultText}: `, (answer) => {
33
+ resolve(answer.trim() || defaultValue || '');
34
+ });
35
+ });
36
+ }
37
+ /**
38
+ * Prompt for yes/no
39
+ */
40
+ async function promptYesNo(rl, question, defaultYes = true) {
41
+ const hint = defaultYes ? '[Y/n]' : '[y/N]';
42
+ return new Promise((resolve) => {
43
+ rl.question(`${question} ${hint}: `, (answer) => {
44
+ if (!answer.trim()) {
45
+ resolve(defaultYes);
46
+ }
47
+ else {
48
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
49
+ }
50
+ });
51
+ });
52
+ }
53
+ /**
54
+ * Prompt for selection from list
55
+ */
56
+ async function promptSelect(rl, question, options, defaultIndex = 0) {
57
+ console.log(question);
58
+ options.forEach((opt, i) => {
59
+ const marker = i === defaultIndex ? chalk.green('→') : ' ';
60
+ console.log(` ${marker} ${i + 1}) ${opt}`);
61
+ });
62
+ return new Promise((resolve) => {
63
+ rl.question(`Select (1-${options.length}) [${defaultIndex + 1}]: `, (answer) => {
64
+ if (!answer.trim()) {
65
+ resolve(options[defaultIndex]);
66
+ }
67
+ else {
68
+ const num = parseInt(answer, 10);
69
+ if (num >= 1 && num <= options.length) {
70
+ resolve(options[num - 1]);
71
+ }
72
+ else {
73
+ resolve(options[defaultIndex]);
74
+ }
75
+ }
76
+ });
77
+ });
78
+ }
79
+ /**
80
+ * Load existing config or create empty one
81
+ */
82
+ function loadOrCreateConfig(configPath) {
83
+ if (existsSync(configPath)) {
84
+ try {
85
+ const content = readFileSync(configPath, 'utf-8');
86
+ return JSON.parse(content);
87
+ }
88
+ catch {
89
+ console.log(chalk.yellow('Warning: Could not parse existing config, starting fresh'));
90
+ }
91
+ }
92
+ return { services: {} };
93
+ }
94
+ /**
95
+ * Save config to file
96
+ */
97
+ function saveConfig(configPath, config) {
98
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
99
+ }
100
+ /**
101
+ * Interactive wizard to create/edit service configuration
102
+ */
103
+ async function createServiceConfig(rl, existingConfig) {
104
+ console.log('');
105
+ console.log(chalk.blue.bold('Service Configuration'));
106
+ console.log(chalk.gray('─'.repeat(40)));
107
+ // Source and deploy
108
+ const sourceDir = await prompt(rl, 'Source directory (relative to workspace)', existingConfig?.sourceDir || '.');
109
+ const deployRepo = await prompt(rl, 'Deploy repo path (relative to source)', existingConfig?.deployRepo || 'deploy');
110
+ // Artifacts
111
+ console.log('');
112
+ const defaultArtifacts = existingConfig?.artifacts?.join(', ') || 'dist, package.json, ecosystem.config.cjs';
113
+ const artifactsStr = await prompt(rl, 'Artifacts to deploy (comma-separated)', defaultArtifacts);
114
+ const artifacts = artifactsStr.split(',').map(a => a.trim()).filter(a => a);
115
+ // Process manager
116
+ console.log('');
117
+ const processManager = await promptSelect(rl, 'Process manager:', ['pm2', 'gpdd', 'systemd'], 0);
118
+ const processName = await prompt(rl, 'Process name', existingConfig?.processName || 'my-service');
119
+ // PM2 specific
120
+ let pm2Home;
121
+ let pm2User;
122
+ if (processManager === 'pm2') {
123
+ const usePm2User = await promptYesNo(rl, 'Run PM2 as different user (sudo -u)?', !!existingConfig?.pm2User);
124
+ if (usePm2User) {
125
+ pm2User = await prompt(rl, 'PM2 user', existingConfig?.pm2User || 'deploy');
126
+ pm2Home = await prompt(rl, 'PM2_HOME directory', existingConfig?.pm2Home || `/opt/${processName}/.pm2`);
127
+ }
128
+ }
129
+ // GPDD specific
130
+ let gpddWorkers;
131
+ let gpddEntryPoint;
132
+ if (processManager === 'gpdd') {
133
+ const workersStr = await prompt(rl, 'Number of workers (0 = CPU count)', String(existingConfig?.gpddWorkers || 0));
134
+ gpddWorkers = parseInt(workersStr, 10) || undefined;
135
+ gpddEntryPoint = await prompt(rl, 'Entry point', existingConfig?.gpddEntryPoint || 'dist/index.js');
136
+ // gpdd also supports running as different user
137
+ const useGpddUser = await promptYesNo(rl, 'Run GPDD as different user (sudo -u)?', !!existingConfig?.pm2User);
138
+ if (useGpddUser) {
139
+ pm2User = await prompt(rl, 'User', existingConfig?.pm2User || 'deploy');
140
+ }
141
+ }
142
+ // Environment
143
+ console.log('');
144
+ const environment = await promptSelect(rl, 'Environment:', ['production', 'staging', 'development'], 0);
145
+ // Server config
146
+ console.log('');
147
+ console.log(chalk.blue('Server Configuration'));
148
+ console.log(chalk.gray('─'.repeat(40)));
149
+ const host = await prompt(rl, 'SSH host (user@hostname)', getExistingServer(existingConfig)?.host || 'deploy@localhost');
150
+ const sshOptions = await prompt(rl, 'SSH options (e.g., -p 22)', getExistingServer(existingConfig)?.sshOptions || '');
151
+ const targetDir = await prompt(rl, 'Target directory on server', getExistingServer(existingConfig)?.targetDir || `/opt/${processName}`);
152
+ const bareRepo = await prompt(rl, 'Bare repo path on server', getExistingServer(existingConfig)?.bareRepo || `/git/deploy-${processName}`);
153
+ const useGroup = await promptYesNo(rl, 'Use shared Unix group?', !!getExistingServer(existingConfig)?.group);
154
+ const group = useGroup ? await prompt(rl, 'Group name', getExistingServer(existingConfig)?.group || 'deploy') : undefined;
155
+ // Environment variables
156
+ console.log('');
157
+ const addEnvVars = await promptYesNo(rl, 'Add environment variables?', !!existingConfig?.env);
158
+ let env;
159
+ if (addEnvVars) {
160
+ env = existingConfig?.env ? { ...existingConfig.env } : {};
161
+ console.log(chalk.gray('Enter variables as KEY=VALUE, empty line to finish'));
162
+ while (true) {
163
+ const varInput = await prompt(rl, 'ENV_VAR=value');
164
+ if (!varInput)
165
+ break;
166
+ const [key, ...valueParts] = varInput.split('=');
167
+ if (key && valueParts.length > 0) {
168
+ const value = valueParts.join('=');
169
+ // Try to parse as number or boolean
170
+ if (value === 'true') {
171
+ env[key] = true;
172
+ }
173
+ else if (value === 'false') {
174
+ env[key] = false;
175
+ }
176
+ else if (/^\d+$/.test(value)) {
177
+ env[key] = parseInt(value, 10);
178
+ }
179
+ else {
180
+ env[key] = value;
181
+ }
182
+ }
183
+ }
184
+ }
185
+ // Build server config
186
+ const serverConfig = {
187
+ host,
188
+ targetDir,
189
+ bareRepo,
190
+ };
191
+ if (sshOptions)
192
+ serverConfig.sshOptions = sshOptions;
193
+ if (group)
194
+ serverConfig.group = group;
195
+ const config = {
196
+ sourceDir,
197
+ deployRepo,
198
+ artifacts,
199
+ processManager,
200
+ processName,
201
+ environment,
202
+ server: serverConfig
203
+ };
204
+ if (pm2Home)
205
+ config.pm2Home = pm2Home;
206
+ if (pm2User)
207
+ config.pm2User = pm2User;
208
+ if (gpddWorkers)
209
+ config.gpddWorkers = gpddWorkers;
210
+ if (gpddEntryPoint && gpddEntryPoint !== 'dist/index.js')
211
+ config.gpddEntryPoint = gpddEntryPoint;
212
+ if (env && Object.keys(env).length > 0)
213
+ config.env = env;
214
+ return config;
215
+ }
216
+ /**
217
+ * Config command - create or edit .git-deploy.json
218
+ */
219
+ export async function configCommand(options = {}) {
220
+ const configPath = join(process.cwd(), CONFIG_FILENAME);
221
+ const config = loadOrCreateConfig(configPath);
222
+ // List mode
223
+ if (options.list) {
224
+ if (Object.keys(config.services).length === 0) {
225
+ console.log(chalk.yellow('No services configured'));
226
+ }
227
+ else {
228
+ console.log(chalk.blue('Configured services:'));
229
+ for (const [name, svc] of Object.entries(config.services)) {
230
+ const servers = getServers(svc);
231
+ console.log(` ${chalk.white(name)}`);
232
+ if (servers.length === 1) {
233
+ console.log(chalk.gray(` Host: ${servers[0].host}`));
234
+ console.log(chalk.gray(` Target: ${servers[0].targetDir}`));
235
+ }
236
+ else {
237
+ console.log(chalk.gray(` Servers: ${servers.length}`));
238
+ for (const server of servers) {
239
+ const label = server.name || server.host;
240
+ console.log(chalk.gray(` - ${label}: ${server.targetDir}`));
241
+ }
242
+ }
243
+ }
244
+ }
245
+ return;
246
+ }
247
+ const rl = createPrompt();
248
+ try {
249
+ console.log(chalk.blue.bold('GPD Configuration Wizard'));
250
+ console.log(chalk.gray(`Config file: ${configPath}`));
251
+ console.log('');
252
+ // Service name
253
+ let serviceName;
254
+ if (options.edit) {
255
+ serviceName = options.edit;
256
+ if (!config.services[serviceName]) {
257
+ console.log(chalk.yellow(`Service '${serviceName}' not found, creating new`));
258
+ }
259
+ }
260
+ else {
261
+ const existingServices = Object.keys(config.services);
262
+ if (existingServices.length > 0) {
263
+ console.log(chalk.gray('Existing services: ' + existingServices.join(', ')));
264
+ }
265
+ serviceName = await prompt(rl, 'Service name', existingServices[0] || 'my-service');
266
+ }
267
+ // Create/edit service config
268
+ const existingService = config.services[serviceName];
269
+ const serviceConfig = await createServiceConfig(rl, existingService);
270
+ // Preview
271
+ console.log('');
272
+ console.log(chalk.blue.bold('Configuration Preview'));
273
+ console.log(chalk.gray('─'.repeat(40)));
274
+ console.log(JSON.stringify({ [serviceName]: serviceConfig }, null, 2));
275
+ console.log('');
276
+ // Confirm save
277
+ const shouldSave = await promptYesNo(rl, 'Save configuration?', true);
278
+ if (shouldSave) {
279
+ config.services[serviceName] = serviceConfig;
280
+ saveConfig(configPath, config);
281
+ console.log(chalk.green(`✓ Saved to ${CONFIG_FILENAME}`));
282
+ console.log('');
283
+ console.log(chalk.gray('Next steps:'));
284
+ console.log(chalk.white(` gpd init ${serviceName} # Setup server`));
285
+ console.log(chalk.white(` gpd deploy ${serviceName} # Deploy`));
286
+ }
287
+ else {
288
+ console.log(chalk.yellow('Cancelled'));
289
+ }
290
+ }
291
+ finally {
292
+ rl.close();
293
+ }
294
+ }
295
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Daemon command - control gpdd on remote server via SSH
3
+ *
4
+ * gpd daemon <service> status Show gpdd status
5
+ * gpd daemon <service> reload Zero-downtime reload
6
+ * gpd daemon <service> stop Stop the daemon
7
+ * gpd daemon <service> start Start the daemon
8
+ */
9
+ export declare function daemonCommand(serviceName: string, action: string): Promise<void>;
10
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DtF"}
@@ -0,0 +1,67 @@
1
+ import chalk from 'chalk';
2
+ import { getServiceConfig } from '../config/loader.js';
3
+ import { getServers } from '../config/types.js';
4
+ import { runSshCommand } from '../utils/shell.js';
5
+ /**
6
+ * Daemon command - control gpdd on remote server via SSH
7
+ *
8
+ * gpd daemon <service> status Show gpdd status
9
+ * gpd daemon <service> reload Zero-downtime reload
10
+ * gpd daemon <service> stop Stop the daemon
11
+ * gpd daemon <service> start Start the daemon
12
+ */
13
+ export async function daemonCommand(serviceName, action) {
14
+ const config = getServiceConfig(serviceName);
15
+ const servers = getServers(config);
16
+ if (config.processManager !== 'gpdd') {
17
+ console.log(chalk.yellow(`Service ${serviceName} uses ${config.processManager || 'pm2'}, not gpdd`));
18
+ console.log(chalk.gray(`Use 'gpd logs ${serviceName}' for PM2 services`));
19
+ return;
20
+ }
21
+ // Run on all servers
22
+ for (const server of servers) {
23
+ const { host, sshOptions, targetDir } = server;
24
+ const serverLabel = server.name || host;
25
+ console.log(chalk.blue(`GPDD ${action} on ${serverLabel}...`));
26
+ console.log(chalk.gray(` Host: ${host}`));
27
+ console.log(chalk.gray(` Target: ${targetDir}`));
28
+ console.log('');
29
+ const runUser = config.pm2User;
30
+ let cmd;
31
+ switch (action) {
32
+ case 'status':
33
+ cmd = `cd "${targetDir}" && gpdd status`;
34
+ break;
35
+ case 'reload':
36
+ cmd = `cd "${targetDir}" && gpdd reload`;
37
+ break;
38
+ case 'stop':
39
+ cmd = `cd "${targetDir}" && gpdd stop`;
40
+ break;
41
+ case 'start':
42
+ const entryPoint = config.gpddEntryPoint || 'dist/index.js';
43
+ const workers = config.gpddWorkers ? `-w ${config.gpddWorkers}` : '';
44
+ cmd = `cd "${targetDir}" && gpdd start ${entryPoint} ${workers}`;
45
+ break;
46
+ default:
47
+ console.error(chalk.red(`Unknown action: ${action}`));
48
+ console.log('Available actions: status, reload, stop, start');
49
+ return;
50
+ }
51
+ // If running as different user, wrap in sudo
52
+ if (runUser) {
53
+ cmd = `sudo -u ${runUser} bash -c '${cmd.replace(/'/g, "'\\''")}'`;
54
+ }
55
+ try {
56
+ const output = await runSshCommand(host, cmd, sshOptions);
57
+ console.log(output);
58
+ console.log(chalk.green(`✓ ${action} completed on ${serverLabel}`));
59
+ }
60
+ catch (error) {
61
+ console.error(chalk.red(`Failed on ${serverLabel}: ${error.message}`));
62
+ }
63
+ if (servers.length > 1)
64
+ console.log('');
65
+ }
66
+ }
67
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,14 @@
1
1
  interface DeployOptions {
2
2
  message?: string;
3
3
  skipPush?: boolean;
4
+ dryRun?: boolean;
4
5
  }
5
6
  /**
6
7
  * Deploy command - stage artifacts and push to server
7
8
  *
8
9
  * New architecture:
9
10
  * 1. Stage: Copy build artifacts to deploy repo (with lazy init)
10
- * 2. Release: Commit and push to bare repo on server
11
+ * 2. Release: Commit and push to bare repo on server(s)
11
12
  * 3. Server hook handles: git checkout, npm install, pm2 restart
12
13
  *
13
14
  * No more SSH install from client - the post-receive hook does everything!
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAKA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBnG"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCnG"}
@@ -1,23 +1,41 @@
1
1
  import chalk from 'chalk';
2
- import { stageCommand } from './stage.js';
3
- import { releaseCommand } from './release.js';
2
+ import { stageCommand, stageCommandDryRun } from './stage.js';
3
+ import { releaseCommand, releaseCommandDryRun } from './release.js';
4
4
  import { getServiceConfig } from '../config/loader.js';
5
+ import { getServers } from '../config/types.js';
5
6
  /**
6
7
  * Deploy command - stage artifacts and push to server
7
8
  *
8
9
  * New architecture:
9
10
  * 1. Stage: Copy build artifacts to deploy repo (with lazy init)
10
- * 2. Release: Commit and push to bare repo on server
11
+ * 2. Release: Commit and push to bare repo on server(s)
11
12
  * 3. Server hook handles: git checkout, npm install, pm2 restart
12
13
  *
13
14
  * No more SSH install from client - the post-receive hook does everything!
14
15
  */
15
16
  export async function deployCommand(serviceName, options = {}) {
16
17
  const config = getServiceConfig(serviceName);
17
- console.log(chalk.blue.bold(`Deploying ${serviceName}...`));
18
+ const servers = getServers(config);
19
+ const serverList = servers.map(s => s.name || s.host).join(', ');
20
+ if (options.dryRun) {
21
+ console.log(chalk.blue.bold(`[DRY RUN] Deploy preview for ${serviceName}`));
22
+ }
23
+ else {
24
+ console.log(chalk.blue.bold(`Deploying ${serviceName}...`));
25
+ }
18
26
  console.log(chalk.gray(` Environment: ${config.environment || 'production'}`));
19
- console.log(chalk.gray(` Server: ${config.server.host}`));
27
+ console.log(chalk.gray(` Server${servers.length > 1 ? 's' : ''}: ${serverList}`));
20
28
  console.log('');
29
+ if (options.dryRun) {
30
+ // Dry run - just show what would happen
31
+ await stageCommandDryRun(serviceName);
32
+ console.log('');
33
+ await releaseCommandDryRun(serviceName);
34
+ console.log('');
35
+ console.log(chalk.yellow.bold('This was a dry run. No changes were made.'));
36
+ console.log(chalk.gray('Run without --dry-run to actually deploy.'));
37
+ return;
38
+ }
21
39
  // 1. Stage artifacts to deploy repo
22
40
  await stageCommand(serviceName);
23
41
  console.log('');
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAOvD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,UAAyB,EAAE;IAClF,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,WAAW,KAAK,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,WAAW,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,oCAAoC;IACpC,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,iDAAiD;IACjD,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,WAAW,EAAE,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA8ID;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwFhG"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA8ID;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBhG"}
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { getServiceConfig } from '../config/loader.js';
3
+ import { getServers } from '../config/types.js';
3
4
  import { sshExec, checkSshConnection, findSshPublicKey, copySshKey } from '../utils/shell.js';
4
5
  import * as readline from 'readline';
5
6
  /**
@@ -137,33 +138,52 @@ log "=== Deployment completed ==="
137
138
  export async function initCommand(serviceName, _options = {}) {
138
139
  console.log(chalk.blue(`Initializing ${serviceName}...`));
139
140
  const config = getServiceConfig(serviceName);
140
- const { host, bareRepo, targetDir, sshOptions, group } = config.server;
141
+ const servers = getServers(config);
141
142
  const { pm2User, pm2Home } = config;
142
- console.log(chalk.gray(` Host: ${host}`));
143
- console.log(chalk.gray(` Bare repo: ${bareRepo}`));
144
- console.log(chalk.gray(` Target dir: ${targetDir}`));
145
- if (group)
146
- console.log(chalk.gray(` Group: ${group}`));
143
+ console.log(chalk.gray(` Servers: ${servers.length}`));
147
144
  if (pm2User)
148
145
  console.log(chalk.gray(` PM2 user: ${pm2User}`));
149
146
  console.log('');
147
+ // Initialize each server
148
+ for (const server of servers) {
149
+ await initServer(serviceName, server, config, _options);
150
+ if (servers.length > 1)
151
+ console.log('');
152
+ }
153
+ console.log(chalk.green(`✓ Initialized ${serviceName} on ${servers.length} server(s)`));
154
+ console.log('');
155
+ console.log(chalk.gray('Server setup complete. Now you can deploy:'));
156
+ console.log(chalk.white(` gpd deploy ${serviceName}`));
157
+ }
158
+ /**
159
+ * Initialize a single server
160
+ */
161
+ async function initServer(serviceName, server, config, options) {
162
+ const { host, bareRepo, targetDir, sshOptions, group } = server;
163
+ const { pm2User, pm2Home } = config;
164
+ const serverLabel = server.name || host;
165
+ console.log(chalk.blue(` Setting up ${serverLabel}...`));
166
+ console.log(chalk.gray(` Host: ${host}`));
167
+ console.log(chalk.gray(` Bare repo: ${bareRepo}`));
168
+ console.log(chalk.gray(` Target dir: ${targetDir}`));
169
+ if (group)
170
+ console.log(chalk.gray(` Group: ${group}`));
150
171
  // 0. Check SSH connection first
151
- if (!_options.skipSshCheck) {
172
+ if (!options.skipSshCheck) {
152
173
  const sshReady = await ensureSshConnection(host, sshOptions);
153
174
  if (!sshReady) {
154
- console.log(chalk.red('Aborting. Fix SSH connection and try again.'));
155
- process.exit(1);
175
+ console.log(chalk.red(` Skipping ${serverLabel} - SSH connection failed`));
176
+ return;
156
177
  }
157
- console.log('');
158
178
  }
159
179
  // 1. Create group if specified
160
180
  if (group) {
161
- console.log(chalk.gray(` Creating group ${group}...`));
181
+ console.log(chalk.gray(` Creating group ${group}...`));
162
182
  const createGroupCmd = `sudo groupadd -f ${group} && sudo usermod -aG ${group} $(whoami)`;
163
183
  sshExec(host, createGroupCmd, { sshOptions });
164
184
  }
165
185
  // 2. Create bare repo with shared group access
166
- console.log(chalk.gray(` Creating bare repo...`));
186
+ console.log(chalk.gray(` Creating bare repo...`));
167
187
  const bareRepoParent = bareRepo.split('/').slice(0, -1).join('/');
168
188
  let createBareCmd = `sudo mkdir -p ${bareRepoParent}`;
169
189
  if (group) {
@@ -175,7 +195,7 @@ export async function initCommand(serviceName, _options = {}) {
175
195
  }
176
196
  sshExec(host, createBareCmd, { sshOptions });
177
197
  // 3. Create target directory
178
- console.log(chalk.gray(` Creating target directory...`));
198
+ console.log(chalk.gray(` Creating target directory...`));
179
199
  const targetParent = targetDir.split('/').slice(0, -1).join('/');
180
200
  let createTargetCmd = `sudo mkdir -p ${targetDir}`;
181
201
  if (pm2User) {
@@ -186,7 +206,7 @@ export async function initCommand(serviceName, _options = {}) {
186
206
  }
187
207
  sshExec(host, createTargetCmd, { sshOptions });
188
208
  // 4. Create post-receive hook
189
- console.log(chalk.gray(` Creating post-receive hook...`));
209
+ console.log(chalk.gray(` Creating post-receive hook...`));
190
210
  const hookContent = generatePostReceiveHook(serviceName, {
191
211
  targetDir,
192
212
  bareRepo,
@@ -204,16 +224,13 @@ export async function initCommand(serviceName, _options = {}) {
204
224
  sshExec(host, createHookCmd, { sshOptions });
205
225
  }
206
226
  // 5. Create log file
207
- console.log(chalk.gray(` Creating log file...`));
227
+ console.log(chalk.gray(` Creating log file...`));
208
228
  const logFile = `/var/log/gpd-${serviceName}.log`;
209
229
  let createLogCmd = `sudo touch ${logFile} && sudo chmod 666 ${logFile}`;
210
230
  if (group) {
211
231
  createLogCmd += ` && sudo chgrp ${group} ${logFile}`;
212
232
  }
213
233
  sshExec(host, createLogCmd, { sshOptions });
214
- console.log(chalk.green(`✓ Initialized ${serviceName}`));
215
- console.log('');
216
- console.log(chalk.gray('Server setup complete. Now you can deploy:'));
217
- console.log(chalk.white(` gpd deploy ${serviceName}`));
234
+ console.log(chalk.green(` ✓ Initialized on ${serverLabel}`));
218
235
  }
219
236
  //# sourceMappingURL=init.js.map