git-push-deploy-cli 0.1.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/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/commands/deploy.d.ts +9 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +10 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +212 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +10 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +67 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/logs.d.ts +10 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +42 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/release.d.ts +9 -0
- package/dist/commands/release.d.ts.map +1 -0
- package/dist/commands/release.js +32 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/commands/stage.d.ts +5 -0
- package/dist/commands/stage.d.ts.map +1 -0
- package/dist/commands/stage.js +37 -0
- package/dist/commands/stage.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +61 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/loader.d.ts +22 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +66 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +42 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +10 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/files.d.ts +25 -0
- package/dist/utils/files.d.ts.map +1 -0
- package/dist/utils/files.js +47 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/git.d.ts +33 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +63 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/pm2.d.ts +39 -0
- package/dist/utils/pm2.d.ts.map +1 -0
- package/dist/utils/pm2.js +83 -0
- package/dist/utils/pm2.js.map +1 -0
- package/dist/utils/process-manager.d.ts +37 -0
- package/dist/utils/process-manager.d.ts.map +1 -0
- package/dist/utils/process-manager.js +17 -0
- package/dist/utils/process-manager.js.map +1 -0
- package/dist/utils/shell.d.ts +24 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +51 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/systemd.d.ts +34 -0
- package/dist/utils/systemd.d.ts.map +1 -0
- package/dist/utils/systemd.js +79 -0
- package/dist/utils/systemd.js.map +1 -0
- package/package.json +60 -0
- package/templates/post-receive.sh +55 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { exec, execOutput } from './shell.js';
|
|
2
|
+
/**
|
|
3
|
+
* PM2 Process Manager implementation
|
|
4
|
+
*/
|
|
5
|
+
export class PM2ProcessManager {
|
|
6
|
+
name = 'pm2';
|
|
7
|
+
buildEnv(options) {
|
|
8
|
+
return options?.home ? `PM2_HOME=${options.home} ` : '';
|
|
9
|
+
}
|
|
10
|
+
restart(processName, options) {
|
|
11
|
+
const env = this.buildEnv(options);
|
|
12
|
+
exec(`${env}pm2 restart ${processName} --no-color`, { silent: options?.silent });
|
|
13
|
+
}
|
|
14
|
+
list(options) {
|
|
15
|
+
const env = this.buildEnv(options);
|
|
16
|
+
return execOutput(`${env}pm2 list --no-color`);
|
|
17
|
+
}
|
|
18
|
+
save(options) {
|
|
19
|
+
const env = this.buildEnv(options);
|
|
20
|
+
exec(`${env}pm2 save`, { silent: true });
|
|
21
|
+
}
|
|
22
|
+
show(processName, options) {
|
|
23
|
+
const env = this.buildEnv(options);
|
|
24
|
+
return execOutput(`${env}pm2 show ${processName} --no-color`);
|
|
25
|
+
}
|
|
26
|
+
exists(processName, options) {
|
|
27
|
+
try {
|
|
28
|
+
this.show(processName, options);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
asUser(user, command, options) {
|
|
36
|
+
const env = this.buildEnv(options);
|
|
37
|
+
exec(`sudo -u ${user} ${env}pm2 ${command} --no-color`, { silent: options?.silent });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Legacy function exports for backward compatibility
|
|
41
|
+
/**
|
|
42
|
+
* Restart PM2 process
|
|
43
|
+
*/
|
|
44
|
+
export function pm2Restart(processName, pm2Home) {
|
|
45
|
+
const pm2 = new PM2ProcessManager();
|
|
46
|
+
pm2.restart(processName, { home: pm2Home });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get PM2 process list
|
|
50
|
+
*/
|
|
51
|
+
export function pm2List(pm2Home) {
|
|
52
|
+
const pm2 = new PM2ProcessManager();
|
|
53
|
+
return pm2.list({ home: pm2Home });
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Save PM2 process list
|
|
57
|
+
*/
|
|
58
|
+
export function pm2Save(pm2Home) {
|
|
59
|
+
const pm2 = new PM2ProcessManager();
|
|
60
|
+
pm2.save({ home: pm2Home });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get PM2 process info
|
|
64
|
+
*/
|
|
65
|
+
export function pm2Show(processName, pm2Home) {
|
|
66
|
+
const pm2 = new PM2ProcessManager();
|
|
67
|
+
return pm2.show(processName, { home: pm2Home });
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if PM2 process exists
|
|
71
|
+
*/
|
|
72
|
+
export function pm2ProcessExists(processName, pm2Home) {
|
|
73
|
+
const pm2 = new PM2ProcessManager();
|
|
74
|
+
return pm2.exists(processName, { home: pm2Home });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Run PM2 command as specific user (for server-side)
|
|
78
|
+
*/
|
|
79
|
+
export function pm2AsUser(user, command, pm2Home) {
|
|
80
|
+
const pm2 = new PM2ProcessManager();
|
|
81
|
+
pm2.asUser(user, command, { home: pm2Home });
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=pm2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pm2.js","sourceRoot":"","sources":["../../src/utils/pm2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract interface for process managers (PM2, systemd, etc.)
|
|
3
|
+
*/
|
|
4
|
+
export interface ProcessManager {
|
|
5
|
+
/** Name of the process manager */
|
|
6
|
+
readonly name: string;
|
|
7
|
+
/** Restart a process by name */
|
|
8
|
+
restart(processName: string, options?: ProcessManagerOptions): void;
|
|
9
|
+
/** Get status/list of processes */
|
|
10
|
+
list(options?: ProcessManagerOptions): string;
|
|
11
|
+
/** Save current process state (for resurrection after reboot) */
|
|
12
|
+
save(options?: ProcessManagerOptions): void;
|
|
13
|
+
/** Get info about a specific process */
|
|
14
|
+
show(processName: string, options?: ProcessManagerOptions): string;
|
|
15
|
+
/** Check if a process exists */
|
|
16
|
+
exists(processName: string, options?: ProcessManagerOptions): boolean;
|
|
17
|
+
/** Run command as specific user (for server-side) */
|
|
18
|
+
asUser(user: string, command: string, options?: ProcessManagerOptions): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for process manager commands
|
|
22
|
+
*/
|
|
23
|
+
export interface ProcessManagerOptions {
|
|
24
|
+
/** Home directory for the process manager */
|
|
25
|
+
home?: string;
|
|
26
|
+
/** Run silently (no output) */
|
|
27
|
+
silent?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Process manager types
|
|
31
|
+
*/
|
|
32
|
+
export type ProcessManagerType = 'pm2' | 'systemd';
|
|
33
|
+
/**
|
|
34
|
+
* Factory function to create a process manager instance
|
|
35
|
+
*/
|
|
36
|
+
export declare function createProcessManager(type: ProcessManagerType): ProcessManager;
|
|
37
|
+
//# sourceMappingURL=process-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/utils/process-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,gCAAgC;IAChC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAEpE,mCAAmC;IACnC,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;IAE9C,iEAAiE;IACjE,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAE5C,wCAAwC;IACxC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC;IAEnE,gCAAgC;IAChC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAEtE,qDAAqD;IACrD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC9E;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,SAAS,CAAC;AAEnD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAY7E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory function to create a process manager instance
|
|
3
|
+
*/
|
|
4
|
+
export function createProcessManager(type) {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'pm2':
|
|
7
|
+
// Lazy import to avoid loading unused modules
|
|
8
|
+
const { PM2ProcessManager } = require('./pm2.js');
|
|
9
|
+
return new PM2ProcessManager();
|
|
10
|
+
case 'systemd':
|
|
11
|
+
const { SystemdProcessManager } = require('./systemd.js');
|
|
12
|
+
return new SystemdProcessManager();
|
|
13
|
+
default:
|
|
14
|
+
throw new Error(`Unknown process manager type: ${type}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=process-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../src/utils/process-manager.ts"],"names":[],"mappings":"AA0CA;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,8CAA8C;YAC9C,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;YAClD,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACjC,KAAK,SAAS;YACZ,MAAM,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1D,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACrC;YACE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute a shell command and return output
|
|
3
|
+
*/
|
|
4
|
+
export declare function exec(command: string, options?: {
|
|
5
|
+
cwd?: string;
|
|
6
|
+
silent?: boolean;
|
|
7
|
+
}): string;
|
|
8
|
+
/**
|
|
9
|
+
* Execute command and return output (always silent)
|
|
10
|
+
*/
|
|
11
|
+
export declare function execOutput(command: string, cwd?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a command exists
|
|
14
|
+
*/
|
|
15
|
+
export declare function commandExists(command: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Check if running as root
|
|
18
|
+
*/
|
|
19
|
+
export declare function isRoot(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get current username
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCurrentUser(): string;
|
|
24
|
+
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAc9F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Execute a shell command and return output
|
|
4
|
+
*/
|
|
5
|
+
export function exec(command, options = {}) {
|
|
6
|
+
try {
|
|
7
|
+
const result = execSync(command, {
|
|
8
|
+
cwd: options.cwd,
|
|
9
|
+
encoding: 'utf-8',
|
|
10
|
+
stdio: options.silent ? 'pipe' : 'inherit'
|
|
11
|
+
});
|
|
12
|
+
return result?.trim() || '';
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error instanceof Error && 'stdout' in error) {
|
|
16
|
+
return error.stdout?.trim() || '';
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Execute command and return output (always silent)
|
|
23
|
+
*/
|
|
24
|
+
export function execOutput(command, cwd) {
|
|
25
|
+
return exec(command, { cwd, silent: true });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if a command exists
|
|
29
|
+
*/
|
|
30
|
+
export function commandExists(command) {
|
|
31
|
+
try {
|
|
32
|
+
execSync(`which ${command}`, { stdio: 'pipe' });
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if running as root
|
|
41
|
+
*/
|
|
42
|
+
export function isRoot() {
|
|
43
|
+
return process.getuid?.() === 0;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get current username
|
|
47
|
+
*/
|
|
48
|
+
export function getCurrentUser() {
|
|
49
|
+
return process.env.USER || process.env.USERNAME || 'unknown';
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;GAEG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,UAA8C,EAAE;IACpF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,EAAE;YAC/B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC3C,CAAC,CAAC;QACH,OAAO,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAChD,OAAQ,KAA4B,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC5D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAY;IACtD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,CAAC;QACH,QAAQ,CAAC,SAAS,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ProcessManager, ProcessManagerOptions } from './process-manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* Systemd Process Manager implementation
|
|
4
|
+
*
|
|
5
|
+
* Uses systemctl to manage services. The processName is expected to be
|
|
6
|
+
* a systemd service name (e.g., "myapp.service" or just "myapp").
|
|
7
|
+
*/
|
|
8
|
+
export declare class SystemdProcessManager implements ProcessManager {
|
|
9
|
+
readonly name = "systemd";
|
|
10
|
+
private serviceName;
|
|
11
|
+
restart(processName: string, options?: ProcessManagerOptions): void;
|
|
12
|
+
list(options?: ProcessManagerOptions): string;
|
|
13
|
+
save(options?: ProcessManagerOptions): void;
|
|
14
|
+
show(processName: string, options?: ProcessManagerOptions): string;
|
|
15
|
+
exists(processName: string, options?: ProcessManagerOptions): boolean;
|
|
16
|
+
asUser(user: string, command: string, options?: ProcessManagerOptions): void;
|
|
17
|
+
/**
|
|
18
|
+
* Enable service to start on boot
|
|
19
|
+
*/
|
|
20
|
+
enable(processName: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Disable service from starting on boot
|
|
23
|
+
*/
|
|
24
|
+
disable(processName: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Reload systemd daemon (after changing unit files)
|
|
27
|
+
*/
|
|
28
|
+
daemonReload(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Check if service is active
|
|
31
|
+
*/
|
|
32
|
+
isActive(processName: string): boolean;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=systemd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.d.ts","sourceRoot":"","sources":["../../src/utils/systemd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlF;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,QAAQ,CAAC,IAAI,aAAa;IAE1B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI;IAKnE,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM;IAK7C,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI;IAM3C,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM;IAKlE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO;IAUrE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,IAAI;IAM5E;;OAEG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKjC;;OAEG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKlC;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;CASvC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { exec, execOutput } from './shell.js';
|
|
2
|
+
/**
|
|
3
|
+
* Systemd Process Manager implementation
|
|
4
|
+
*
|
|
5
|
+
* Uses systemctl to manage services. The processName is expected to be
|
|
6
|
+
* a systemd service name (e.g., "myapp.service" or just "myapp").
|
|
7
|
+
*/
|
|
8
|
+
export class SystemdProcessManager {
|
|
9
|
+
name = 'systemd';
|
|
10
|
+
serviceName(name) {
|
|
11
|
+
return name.endsWith('.service') ? name : `${name}.service`;
|
|
12
|
+
}
|
|
13
|
+
restart(processName, options) {
|
|
14
|
+
const service = this.serviceName(processName);
|
|
15
|
+
exec(`sudo systemctl restart ${service}`, { silent: options?.silent });
|
|
16
|
+
}
|
|
17
|
+
list(options) {
|
|
18
|
+
// List all running services
|
|
19
|
+
return execOutput('systemctl list-units --type=service --state=running --no-pager');
|
|
20
|
+
}
|
|
21
|
+
save(options) {
|
|
22
|
+
// systemd auto-saves, but we can enable the service for boot
|
|
23
|
+
// This is a no-op for systemd as it manages state automatically
|
|
24
|
+
console.log('Note: systemd manages service state automatically.');
|
|
25
|
+
}
|
|
26
|
+
show(processName, options) {
|
|
27
|
+
const service = this.serviceName(processName);
|
|
28
|
+
return execOutput(`systemctl status ${service} --no-pager`);
|
|
29
|
+
}
|
|
30
|
+
exists(processName, options) {
|
|
31
|
+
const service = this.serviceName(processName);
|
|
32
|
+
try {
|
|
33
|
+
execOutput(`systemctl cat ${service} 2>/dev/null`);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
asUser(user, command, options) {
|
|
41
|
+
// For systemd, we use systemctl directly (no user switching needed)
|
|
42
|
+
// The 'command' here should be a systemctl action like 'restart myapp'
|
|
43
|
+
exec(`sudo systemctl ${command}`, { silent: options?.silent });
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Enable service to start on boot
|
|
47
|
+
*/
|
|
48
|
+
enable(processName) {
|
|
49
|
+
const service = this.serviceName(processName);
|
|
50
|
+
exec(`sudo systemctl enable ${service}`, { silent: true });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Disable service from starting on boot
|
|
54
|
+
*/
|
|
55
|
+
disable(processName) {
|
|
56
|
+
const service = this.serviceName(processName);
|
|
57
|
+
exec(`sudo systemctl disable ${service}`, { silent: true });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Reload systemd daemon (after changing unit files)
|
|
61
|
+
*/
|
|
62
|
+
daemonReload() {
|
|
63
|
+
exec('sudo systemctl daemon-reload', { silent: true });
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if service is active
|
|
67
|
+
*/
|
|
68
|
+
isActive(processName) {
|
|
69
|
+
const service = this.serviceName(processName);
|
|
70
|
+
try {
|
|
71
|
+
const result = execOutput(`systemctl is-active ${service}`);
|
|
72
|
+
return result.trim() === 'active';
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=systemd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../src/utils/systemd.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,SAAS,CAAC;IAElB,WAAW,CAAC,IAAY;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,UAAU,CAAC;IAC9D,CAAC;IAED,OAAO,CAAC,WAAmB,EAAE,OAA+B;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,0BAA0B,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC,OAA+B;QAClC,4BAA4B;QAC5B,OAAO,UAAU,CAAC,gEAAgE,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,OAA+B;QAClC,6DAA6D;QAC7D,gEAAgE;QAChE,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,CAAC,WAAmB,EAAE,OAA+B;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,OAAO,UAAU,CAAC,oBAAoB,OAAO,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,OAA+B;QACzD,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,UAAU,CAAC,iBAAiB,OAAO,cAAc,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,OAAe,EAAE,OAA+B;QACnE,oEAAoE;QACpE,uEAAuE;QACvE,IAAI,CAAC,kBAAkB,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAmB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,yBAAyB,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,WAAmB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,0BAA0B,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,CAAC,8BAA8B,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,WAAmB;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,UAAU,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;YAC5D,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-push-deploy-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Git Push Deploy - CLI for git-based deployments. Push to bare repos, auto npm install, PM2/systemd restart. Monorepo-ready.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"git",
|
|
7
|
+
"push",
|
|
8
|
+
"deploy",
|
|
9
|
+
"deployment",
|
|
10
|
+
"pm2",
|
|
11
|
+
"systemd",
|
|
12
|
+
"bare-repo",
|
|
13
|
+
"post-receive",
|
|
14
|
+
"hook",
|
|
15
|
+
"monorepo",
|
|
16
|
+
"cli",
|
|
17
|
+
"gpd"
|
|
18
|
+
],
|
|
19
|
+
"author": "Andreas Schulz <aschulz@kairox.de>",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/aschulz-kairox/git-push-deploy-cli.git"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/aschulz-kairox/git-push-deploy-cli#readme",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/aschulz-kairox/git-push-deploy-cli/issues"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"bin": {
|
|
31
|
+
"git-push-deploy": "./dist/index.js",
|
|
32
|
+
"gpd": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"templates"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"dev": "tsc --watch",
|
|
43
|
+
"start": "node dist/index.js",
|
|
44
|
+
"lint": "eslint src",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"prepublishOnly": "npm run build"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"commander": "^13.0.0",
|
|
50
|
+
"chalk": "^5.4.1"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22.10.1",
|
|
54
|
+
"typescript": "^5.7.2",
|
|
55
|
+
"vitest": "^2.1.8"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post-receive hook template
|
|
3
|
+
# Copy this to your bare repo: hooks/post-receive
|
|
4
|
+
# Or use: git-deploy init <service>
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Configuration - adjust these values
|
|
9
|
+
SERVICE="my-service"
|
|
10
|
+
TARGET_DIR="/opt/myapp/my-service"
|
|
11
|
+
LOG_FILE="/var/log/deploy-my-service.log"
|
|
12
|
+
PM2_NAME="my-service"
|
|
13
|
+
PM2_HOME="/opt/myapp/.pm2"
|
|
14
|
+
PACKAGES=("my-service")
|
|
15
|
+
MAIN_PKG="my-service"
|
|
16
|
+
USER="myapp"
|
|
17
|
+
|
|
18
|
+
log() {
|
|
19
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | sudo tee -a "$LOG_FILE"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
log "=== Deployment started ==="
|
|
23
|
+
|
|
24
|
+
while read oldrev newrev refname; do
|
|
25
|
+
BRANCH=$(echo "$refname" | sed 's|refs/heads/||')
|
|
26
|
+
log "Received push to branch: $BRANCH"
|
|
27
|
+
|
|
28
|
+
if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "master" ]; then
|
|
29
|
+
log "Ignoring non-main branch"
|
|
30
|
+
continue
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Extract packages using git archive
|
|
34
|
+
for pkg in "${PACKAGES[@]}"; do
|
|
35
|
+
log "Extracting $pkg..."
|
|
36
|
+
git archive "$BRANCH" "$pkg/" 2>/dev/null | sudo tar -x -C "$TARGET_DIR/" || true
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# Set ownership
|
|
40
|
+
sudo chown -R $USER:$USER "$TARGET_DIR"
|
|
41
|
+
|
|
42
|
+
# Install dependencies
|
|
43
|
+
log "Installing dependencies..."
|
|
44
|
+
cd "$TARGET_DIR/$MAIN_PKG"
|
|
45
|
+
sudo -u $USER npm install --omit=dev 2>&1 | sudo tee -a "$LOG_FILE"
|
|
46
|
+
|
|
47
|
+
# Restart PM2
|
|
48
|
+
log "Restarting $PM2_NAME..."
|
|
49
|
+
sudo -u $USER PM2_HOME=$PM2_HOME pm2 restart "$PM2_NAME" --no-color 2>&1 | sudo tee -a "$LOG_FILE"
|
|
50
|
+
|
|
51
|
+
log "Current status:"
|
|
52
|
+
sudo -u $USER PM2_HOME=$PM2_HOME pm2 list --no-color 2>&1 | sudo tee -a "$LOG_FILE"
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
log "=== Deployment completed ==="
|