git-push-deploy-cli 0.1.1 → 0.2.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/README.md +72 -38
- package/dist/commands/deploy.d.ts +9 -2
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +26 -21
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/init.d.ts +4 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +116 -13
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +21 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +174 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +5 -3
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/release.d.ts +2 -0
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +7 -5
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/stage.d.ts +5 -0
- package/dist/commands/stage.d.ts.map +1 -1
- package/dist/commands/stage.js +58 -22
- package/dist/commands/stage.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +5 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/config/loader.d.ts +14 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +18 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/types.d.ts +47 -9
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +24 -1
- package/dist/config/types.js.map +1 -1
- package/dist/index.js +16 -9
- package/dist/index.js.map +1 -1
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +4 -3
- package/dist/utils/shell.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,10 +4,10 @@ Git Push Deploy - A CLI for git-based deployments with PM2 support. Push to depl
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Git-based deployment**: Push to bare repo,
|
|
8
|
-
- **PM2 integration**: Automatic process restarts
|
|
9
|
-
- **
|
|
10
|
-
- **SSH orchestration**:
|
|
7
|
+
- **Git-based deployment**: Push to bare repo, server hook handles install
|
|
8
|
+
- **PM2 integration**: Automatic process restarts with user isolation
|
|
9
|
+
- **Lazy initialization**: Deploy repo created on first `gpd stage`
|
|
10
|
+
- **SSH orchestration**: Server setup from your dev machine
|
|
11
11
|
- **Config-driven**: Define services in `.git-deploy.json`
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
@@ -23,17 +23,25 @@ npm install -g git-push-deploy-cli
|
|
|
23
23
|
```json
|
|
24
24
|
{
|
|
25
25
|
"services": {
|
|
26
|
-
"my-api": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
26
|
+
"my-api-staging": {
|
|
27
|
+
"sourceDir": "my-api",
|
|
28
|
+
"deployRepo": "deploy/staging",
|
|
29
|
+
"artifacts": ["dist/index.js", "package.json", "ecosystem.config.cjs"],
|
|
30
|
+
"processManager": "pm2",
|
|
31
|
+
"processName": "my-api-staging",
|
|
31
32
|
"pm2Home": "/opt/myapp/.pm2",
|
|
32
|
-
"
|
|
33
|
+
"pm2User": "myapp",
|
|
34
|
+
"environment": "staging",
|
|
35
|
+
"env": {
|
|
36
|
+
"PORT": 5000,
|
|
37
|
+
"NODE_ENV": "staging"
|
|
38
|
+
},
|
|
33
39
|
"server": {
|
|
34
40
|
"host": "user@myserver",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
41
|
+
"sshOptions": "-p 22",
|
|
42
|
+
"targetDir": "/opt/myapp/staging/my-api",
|
|
43
|
+
"bareRepo": "/git/deploy-myapp/staging/my-api",
|
|
44
|
+
"group": "deploy-myapp"
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
47
|
}
|
|
@@ -43,23 +51,25 @@ npm install -g git-push-deploy-cli
|
|
|
43
51
|
### 2. Initialize server (once per service)
|
|
44
52
|
|
|
45
53
|
```bash
|
|
46
|
-
gpd init my-api
|
|
54
|
+
gpd init my-api-staging
|
|
47
55
|
```
|
|
48
56
|
|
|
49
57
|
This creates via SSH:
|
|
50
|
-
- Bare git repository at `/git/deploy-my-api`
|
|
51
|
-
-
|
|
58
|
+
- Bare git repository at `/git/deploy-myapp/staging/my-api`
|
|
59
|
+
- Target directory at `/opt/myapp/staging/my-api`
|
|
60
|
+
- Post-receive hook that calls `gpd install`
|
|
52
61
|
|
|
53
62
|
### 3. Deploy
|
|
54
63
|
|
|
55
64
|
```bash
|
|
56
|
-
gpd deploy my-api
|
|
65
|
+
gpd deploy my-api-staging
|
|
57
66
|
```
|
|
58
67
|
|
|
59
68
|
This:
|
|
60
|
-
1.
|
|
61
|
-
2.
|
|
62
|
-
3.
|
|
69
|
+
1. Creates deploy repo (if needed) at `my-api/deploy/staging/`
|
|
70
|
+
2. Copies build artifacts to deploy repo
|
|
71
|
+
3. Commits and pushes to bare repo on server
|
|
72
|
+
4. Server hook: `git checkout && npm install && pm2 restart`
|
|
63
73
|
|
|
64
74
|
## Commands
|
|
65
75
|
|
|
@@ -68,15 +78,16 @@ This:
|
|
|
68
78
|
| `gpd status` | Show all configured services |
|
|
69
79
|
| `gpd stage <service>` | Copy build artifacts to deploy repo |
|
|
70
80
|
| `gpd release <service>` | Commit and push deploy repo |
|
|
71
|
-
| `gpd deploy <service>` | Stage + release
|
|
72
|
-
| `gpd init <service>` | Initialize bare repo
|
|
81
|
+
| `gpd deploy <service>` | Stage + release (hook handles install) |
|
|
82
|
+
| `gpd init <service>` | Initialize server (bare repo, target dir, hook) |
|
|
83
|
+
| `gpd install <service>` | Server-side install (called by hook) |
|
|
73
84
|
| `gpd logs <service>` | Show PM2 logs from server via SSH |
|
|
74
85
|
|
|
75
86
|
## Options
|
|
76
87
|
|
|
77
88
|
```bash
|
|
78
89
|
gpd deploy my-api -m "custom commit message"
|
|
79
|
-
gpd deploy my-api --skip-
|
|
90
|
+
gpd deploy my-api --skip-push # Only stage, do not push
|
|
80
91
|
gpd logs my-api -f # Follow logs
|
|
81
92
|
gpd logs my-api -n 100 # Show last 100 lines
|
|
82
93
|
```
|
|
@@ -85,48 +96,71 @@ gpd logs my-api -n 100 # Show last 100 lines
|
|
|
85
96
|
|
|
86
97
|
```typescript
|
|
87
98
|
interface ServiceConfig {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
sourceDir: string; // Project directory (e.g., "my-api")
|
|
100
|
+
deployRepo: string; // Deploy repo path, relative to sourceDir
|
|
101
|
+
artifacts: string[]; // Files/dirs to copy
|
|
102
|
+
processManager: 'pm2'; // Process manager type
|
|
91
103
|
processName: string; // PM2 process name
|
|
92
104
|
pm2Home?: string; // PM2_HOME on server
|
|
93
|
-
|
|
105
|
+
pm2User?: string; // User to run PM2 as (sudo -u)
|
|
106
|
+
environment?: string; // staging | production
|
|
107
|
+
env?: Record<string, any>; // Environment variables for .env file
|
|
94
108
|
server: {
|
|
95
109
|
host: string; // SSH host (user@hostname)
|
|
96
|
-
|
|
110
|
+
sshOptions?: string; // SSH options (e.g., "-p 6771 -4")
|
|
111
|
+
targetDir: string; // Target directory on server
|
|
97
112
|
bareRepo: string; // Bare repo path on server
|
|
113
|
+
group?: string; // Unix group for permissions
|
|
98
114
|
};
|
|
99
115
|
}
|
|
100
116
|
```
|
|
101
117
|
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
Workspace Server
|
|
122
|
+
───────── ──────
|
|
123
|
+
my-api/
|
|
124
|
+
├── src/ /git/deploy-myapp/staging/my-api/
|
|
125
|
+
├── dist/ └── hooks/post-receive
|
|
126
|
+
└── deploy/ ↓
|
|
127
|
+
└── staging/ /opt/myapp/staging/my-api/
|
|
128
|
+
├── .git → ssh://... ├── dist/index.js
|
|
129
|
+
├── dist/ ├── package.json
|
|
130
|
+
└── package.json ├── node_modules/
|
|
131
|
+
└── .env (generated)
|
|
132
|
+
```
|
|
133
|
+
|
|
102
134
|
## Workflow
|
|
103
135
|
|
|
104
136
|
```
|
|
105
137
|
Dev Machine Server
|
|
106
138
|
─────────── ──────
|
|
107
|
-
gpd deploy my-api
|
|
139
|
+
gpd deploy my-api-staging
|
|
108
140
|
│
|
|
109
141
|
├─ gpd stage
|
|
110
|
-
│ └─ Copy artifacts →
|
|
111
|
-
│
|
|
112
|
-
├─ gpd release
|
|
113
|
-
│ └─ git push ──────────────────→ /git/deploy-my-api (bare)
|
|
142
|
+
│ └─ Copy artifacts → my-api/deploy/staging/
|
|
114
143
|
│
|
|
115
|
-
└─
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
144
|
+
└─ gpd release
|
|
145
|
+
└─ git push ───────────────→ /git/deploy-myapp/staging/my-api
|
|
146
|
+
│
|
|
147
|
+
└─ post-receive hook:
|
|
148
|
+
gpd install my-api-staging
|
|
149
|
+
│
|
|
150
|
+
├─ git checkout -f
|
|
151
|
+
├─ .env generation
|
|
152
|
+
├─ npm install --omit=dev
|
|
153
|
+
└─ pm2 restart
|
|
119
154
|
```
|
|
120
155
|
|
|
121
156
|
## Server Prerequisites
|
|
122
157
|
|
|
123
158
|
- Node.js + npm
|
|
124
159
|
- PM2 (`npm install -g pm2`)
|
|
160
|
+
- gpd CLI (`npm install -g git-push-deploy-cli`)
|
|
125
161
|
- SSH access from dev machine
|
|
126
162
|
- Git
|
|
127
163
|
|
|
128
|
-
No gpd installation needed on the server!
|
|
129
|
-
|
|
130
164
|
## License
|
|
131
165
|
|
|
132
166
|
MIT
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
interface DeployOptions {
|
|
2
2
|
message?: string;
|
|
3
|
-
|
|
3
|
+
skipPush?: boolean;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
|
-
* Deploy command - stage
|
|
6
|
+
* Deploy command - stage artifacts and push to server
|
|
7
|
+
*
|
|
8
|
+
* New architecture:
|
|
9
|
+
* 1. Stage: Copy build artifacts to deploy repo (with lazy init)
|
|
10
|
+
* 2. Release: Commit and push to bare repo on server
|
|
11
|
+
* 3. Server hook handles: git checkout, npm install, pm2 restart
|
|
12
|
+
*
|
|
13
|
+
* No more SSH install from client - the post-receive hook does everything!
|
|
7
14
|
*/
|
|
8
15
|
export declare function deployCommand(serviceName: string, options?: DeployOptions): Promise<void>;
|
|
9
16
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -2,31 +2,36 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { stageCommand } from './stage.js';
|
|
3
3
|
import { releaseCommand } from './release.js';
|
|
4
4
|
import { getServiceConfig } from '../config/loader.js';
|
|
5
|
-
import { sshExec } from '../utils/shell.js';
|
|
6
5
|
/**
|
|
7
|
-
* Deploy command - stage
|
|
6
|
+
* Deploy command - stage artifacts and push to server
|
|
7
|
+
*
|
|
8
|
+
* New architecture:
|
|
9
|
+
* 1. Stage: Copy build artifacts to deploy repo (with lazy init)
|
|
10
|
+
* 2. Release: Commit and push to bare repo on server
|
|
11
|
+
* 3. Server hook handles: git checkout, npm install, pm2 restart
|
|
12
|
+
*
|
|
13
|
+
* No more SSH install from client - the post-receive hook does everything!
|
|
8
14
|
*/
|
|
9
15
|
export async function deployCommand(serviceName, options = {}) {
|
|
10
|
-
|
|
16
|
+
const config = getServiceConfig(serviceName);
|
|
17
|
+
console.log(chalk.blue.bold(`Deploying ${serviceName}...`));
|
|
18
|
+
console.log(chalk.gray(` Environment: ${config.environment || 'production'}`));
|
|
19
|
+
console.log(chalk.gray(` Server: ${config.server.host}`));
|
|
20
|
+
console.log('');
|
|
21
|
+
// 1. Stage artifacts to deploy repo
|
|
11
22
|
await stageCommand(serviceName);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
console.log(chalk.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`cd ${mainPackage}`,
|
|
25
|
-
'npm install --omit=dev',
|
|
26
|
-
`${pm2Env}pm2 restart ecosystem.config.cjs`
|
|
27
|
-
].join(' && ');
|
|
28
|
-
sshExec(host, remoteCmd);
|
|
29
|
-
console.log(chalk.green(`✓ Deployed ${serviceName} to ${host}`));
|
|
23
|
+
console.log('');
|
|
24
|
+
// 2. Commit and push (triggers server-side hook)
|
|
25
|
+
if (!options.skipPush) {
|
|
26
|
+
await releaseCommand(serviceName, options);
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log(chalk.green.bold(`✓ Deployed ${serviceName}`));
|
|
29
|
+
console.log(chalk.gray(' The server hook will handle: git checkout, npm install, pm2 restart'));
|
|
30
|
+
console.log(chalk.gray(` Check logs: gpd logs ${serviceName}`));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(chalk.yellow('Skipped push (--skip-push). Run manually:'));
|
|
34
|
+
console.log(chalk.white(` gpd release ${serviceName}`));
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
//# sourceMappingURL=deploy.js.map
|
|
@@ -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;
|
|
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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
interface InitOptions {
|
|
2
2
|
}
|
|
3
3
|
/**
|
|
4
|
-
* Init command - initialize bare repo and
|
|
4
|
+
* Init command - initialize bare repo and target directory on remote server via SSH
|
|
5
5
|
*
|
|
6
6
|
* Creates:
|
|
7
|
-
* 1. Bare repo at server.bareRepo (e.g., /git/sym/deploy-kairox-api)
|
|
8
|
-
* 2.
|
|
7
|
+
* 1. Bare repo at server.bareRepo (e.g., /git/sym/deploy-kairox/staging/kairox-api)
|
|
8
|
+
* 2. Target directory at server.targetDir (e.g., /opt/kairox/staging/kairox-api)
|
|
9
|
+
* 3. Post-receive hook that calls `gpd install <service>`
|
|
9
10
|
*/
|
|
10
11
|
export declare function initCommand(serviceName: string, _options?: InitOptions): Promise<void>;
|
|
11
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;CAEpB;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;CAEpB;AA8DD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhG"}
|
package/dist/commands/init.js
CHANGED
|
@@ -2,29 +2,132 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { getServiceConfig } from '../config/loader.js';
|
|
3
3
|
import { sshExec } from '../utils/shell.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Generate post-receive hook content
|
|
6
|
+
* The hook simply calls `gpd install <service>` which handles all the logic
|
|
7
|
+
*/
|
|
8
|
+
function generatePostReceiveHook(serviceName, config) {
|
|
9
|
+
const { targetDir, bareRepo, pm2User, pm2Home } = config;
|
|
10
|
+
// Build the install command with sudo if pm2User is specified
|
|
11
|
+
let installCmd = 'gpd install ' + serviceName;
|
|
12
|
+
if (pm2User) {
|
|
13
|
+
// Run gpd as the pm2User
|
|
14
|
+
installCmd = `sudo -u ${pm2User} ${installCmd}`;
|
|
15
|
+
}
|
|
16
|
+
return `#!/bin/bash
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
# GPD post-receive hook for ${serviceName}
|
|
20
|
+
# Generated by: gpd init ${serviceName}
|
|
21
|
+
|
|
22
|
+
SERVICE="${serviceName}"
|
|
23
|
+
TARGET_DIR="${targetDir}"
|
|
24
|
+
GIT_DIR="${bareRepo}"
|
|
25
|
+
LOG_FILE="/var/log/gpd-${serviceName}.log"
|
|
26
|
+
|
|
27
|
+
log() {
|
|
28
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
log "=== Deployment started for $SERVICE ==="
|
|
32
|
+
|
|
33
|
+
while read oldrev newrev refname; do
|
|
34
|
+
BRANCH=$(echo "$refname" | sed 's|refs/heads/||')
|
|
35
|
+
log "Received push to branch: $BRANCH"
|
|
36
|
+
|
|
37
|
+
if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "master" ]; then
|
|
38
|
+
log "Ignoring branch $BRANCH (only main/master triggers deploy)"
|
|
39
|
+
continue
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Export variables for gpd install
|
|
43
|
+
export GPD_TARGET_DIR="$TARGET_DIR"
|
|
44
|
+
export GPD_GIT_DIR="$GIT_DIR"
|
|
45
|
+
export GPD_SERVICE="$SERVICE"
|
|
46
|
+
${pm2Home ? `export PM2_HOME="${pm2Home}"` : ''}
|
|
47
|
+
|
|
48
|
+
# Run gpd install (handles checkout, npm install, pm2 restart)
|
|
49
|
+
log "Running: ${installCmd}"
|
|
50
|
+
${installCmd} 2>&1 | tee -a "$LOG_FILE"
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
log "=== Deployment completed ==="
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Init command - initialize bare repo and target directory on remote server via SSH
|
|
6
58
|
*
|
|
7
59
|
* Creates:
|
|
8
|
-
* 1. Bare repo at server.bareRepo (e.g., /git/sym/deploy-kairox-api)
|
|
9
|
-
* 2.
|
|
60
|
+
* 1. Bare repo at server.bareRepo (e.g., /git/sym/deploy-kairox/staging/kairox-api)
|
|
61
|
+
* 2. Target directory at server.targetDir (e.g., /opt/kairox/staging/kairox-api)
|
|
62
|
+
* 3. Post-receive hook that calls `gpd install <service>`
|
|
10
63
|
*/
|
|
11
64
|
export async function initCommand(serviceName, _options = {}) {
|
|
12
65
|
console.log(chalk.blue(`Initializing ${serviceName}...`));
|
|
13
66
|
const config = getServiceConfig(serviceName);
|
|
14
|
-
const { host, bareRepo, targetDir } = config.server;
|
|
67
|
+
const { host, bareRepo, targetDir, sshOptions, group } = config.server;
|
|
68
|
+
const { pm2User, pm2Home } = config;
|
|
15
69
|
console.log(chalk.gray(` Host: ${host}`));
|
|
16
70
|
console.log(chalk.gray(` Bare repo: ${bareRepo}`));
|
|
17
71
|
console.log(chalk.gray(` Target dir: ${targetDir}`));
|
|
18
|
-
|
|
72
|
+
if (group)
|
|
73
|
+
console.log(chalk.gray(` Group: ${group}`));
|
|
74
|
+
if (pm2User)
|
|
75
|
+
console.log(chalk.gray(` PM2 user: ${pm2User}`));
|
|
76
|
+
// 1. Create group if specified
|
|
77
|
+
if (group) {
|
|
78
|
+
console.log(chalk.gray(` Creating group ${group}...`));
|
|
79
|
+
const createGroupCmd = `sudo groupadd -f ${group} && sudo usermod -aG ${group} $(whoami)`;
|
|
80
|
+
sshExec(host, createGroupCmd, { sshOptions });
|
|
81
|
+
}
|
|
82
|
+
// 2. Create bare repo with shared group access
|
|
19
83
|
console.log(chalk.gray(` Creating bare repo...`));
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
84
|
+
const bareRepoParent = bareRepo.split('/').slice(0, -1).join('/');
|
|
85
|
+
let createBareCmd = `sudo mkdir -p ${bareRepoParent}`;
|
|
86
|
+
if (group) {
|
|
87
|
+
createBareCmd += ` && sudo chgrp ${group} ${bareRepoParent} && sudo chmod g+rwxs ${bareRepoParent}`;
|
|
88
|
+
}
|
|
89
|
+
createBareCmd += ` && cd ${bareRepoParent} && git init --bare --shared=group ${bareRepo.split('/').pop()}`;
|
|
90
|
+
if (group) {
|
|
91
|
+
createBareCmd += ` && sudo chgrp -R ${group} ${bareRepo}`;
|
|
92
|
+
}
|
|
93
|
+
sshExec(host, createBareCmd, { sshOptions });
|
|
94
|
+
// 3. Create target directory
|
|
95
|
+
console.log(chalk.gray(` Creating target directory...`));
|
|
96
|
+
const targetParent = targetDir.split('/').slice(0, -1).join('/');
|
|
97
|
+
let createTargetCmd = `sudo mkdir -p ${targetDir}`;
|
|
98
|
+
if (pm2User) {
|
|
99
|
+
createTargetCmd += ` && sudo chown ${pm2User}:${group || pm2User} ${targetDir}`;
|
|
100
|
+
}
|
|
101
|
+
if (group) {
|
|
102
|
+
createTargetCmd += ` && sudo chgrp -R ${group} ${targetParent} && sudo chmod g+rwxs ${targetParent}`;
|
|
103
|
+
}
|
|
104
|
+
sshExec(host, createTargetCmd, { sshOptions });
|
|
105
|
+
// 4. Create post-receive hook
|
|
106
|
+
console.log(chalk.gray(` Creating post-receive hook...`));
|
|
107
|
+
const hookContent = generatePostReceiveHook(serviceName, {
|
|
108
|
+
targetDir,
|
|
109
|
+
bareRepo,
|
|
110
|
+
pm2User,
|
|
111
|
+
pm2Home
|
|
112
|
+
});
|
|
113
|
+
// Escape for shell (use base64 to avoid quote issues)
|
|
114
|
+
const hookBase64 = Buffer.from(hookContent).toString('base64');
|
|
115
|
+
const hookPath = `${bareRepo}/hooks/post-receive`;
|
|
116
|
+
const createHookCmd = `echo '${hookBase64}' | base64 -d | sudo tee ${hookPath} > /dev/null && sudo chmod +x ${hookPath}`;
|
|
117
|
+
if (group) {
|
|
118
|
+
sshExec(host, `${createHookCmd} && sudo chgrp ${group} ${hookPath}`, { sshOptions });
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
sshExec(host, createHookCmd, { sshOptions });
|
|
122
|
+
}
|
|
123
|
+
// 5. Create log file
|
|
124
|
+
console.log(chalk.gray(` Creating log file...`));
|
|
125
|
+
const logFile = `/var/log/gpd-${serviceName}.log`;
|
|
126
|
+
let createLogCmd = `sudo touch ${logFile} && sudo chmod 666 ${logFile}`;
|
|
127
|
+
if (group) {
|
|
128
|
+
createLogCmd += ` && sudo chgrp ${group} ${logFile}`;
|
|
129
|
+
}
|
|
130
|
+
sshExec(host, createLogCmd, { sshOptions });
|
|
28
131
|
console.log(chalk.green(`✓ Initialized ${serviceName}`));
|
|
29
132
|
console.log('');
|
|
30
133
|
console.log(chalk.gray('Server setup complete. Now you can deploy:'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAM5C
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface InstallOptions {
|
|
2
|
+
configPath?: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Install command - runs on server after git push (called by post-receive hook)
|
|
6
|
+
*
|
|
7
|
+
* Environment variables from hook:
|
|
8
|
+
* - GPD_TARGET_DIR: Where to install (e.g., /opt/kairox/staging/kairox-api)
|
|
9
|
+
* - GPD_GIT_DIR: Bare repo path (e.g., /git/sym/deploy-kairox/staging/kairox-api)
|
|
10
|
+
* - GPD_SERVICE: Service name (e.g., kairox-api-staging)
|
|
11
|
+
* - PM2_HOME: PM2 home directory (optional)
|
|
12
|
+
*
|
|
13
|
+
* Steps:
|
|
14
|
+
* 1. git checkout from bare repo to target dir
|
|
15
|
+
* 2. Generate .env file from config
|
|
16
|
+
* 3. npm install --omit=dev
|
|
17
|
+
* 4. PM2 restart
|
|
18
|
+
*/
|
|
19
|
+
export declare function installCommand(serviceName: string, options?: InstallOptions): Promise<void>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoDD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiHrG"}
|