@wxuns/zp-cli 0.0.1
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/.github/workflows/publish.yml +51 -0
- package/DEBUG.md +129 -0
- package/README.md +289 -0
- package/bin/zp-cli.js +84 -0
- package/lib/commands/init.js +93 -0
- package/lib/commands/upload.js +231 -0
- package/lib/core/configManager.js +166 -0
- package/lib/core/gitHelper.js +167 -0
- package/lib/core/sshDeployer.js +384 -0
- package/lib/utils/logger.js +64 -0
- package/package.json +27 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# 推送版本标签时触发 (例如 v1.0.0, v1.1.0)
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*'
|
|
8
|
+
|
|
9
|
+
# 也可以手动触发
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
# 1. 检出代码
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
# 2. 设置 Node.js 环境
|
|
22
|
+
- name: Setup Node.js
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: '18'
|
|
26
|
+
registry-url: 'https://registry.npmjs.org'
|
|
27
|
+
|
|
28
|
+
# 3. 安装依赖
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: npm install
|
|
31
|
+
|
|
32
|
+
# 4. 运行测试 (如果有)
|
|
33
|
+
# - name: Run tests
|
|
34
|
+
# run: npm test
|
|
35
|
+
|
|
36
|
+
# 5. 发布到 npm
|
|
37
|
+
- name: Publish to npm
|
|
38
|
+
run: npm publish --access public
|
|
39
|
+
env:
|
|
40
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
41
|
+
|
|
42
|
+
# 6. 创建 GitHub Release (可选)
|
|
43
|
+
- name: Create GitHub Release
|
|
44
|
+
uses: actions/create-release@v1
|
|
45
|
+
env:
|
|
46
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
47
|
+
with:
|
|
48
|
+
tag_name: ${{ github.ref }}
|
|
49
|
+
release_name: Release ${{ github.ref }}
|
|
50
|
+
draft: false
|
|
51
|
+
prerelease: false
|
package/DEBUG.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# zp-cli 本地调试指南
|
|
2
|
+
|
|
3
|
+
## npm link 全局链接
|
|
4
|
+
|
|
5
|
+
将本地项目链接到全局,使 `zp-cli` 命令直接指向本地代码,修改代码后立即生效。
|
|
6
|
+
|
|
7
|
+
### 链接
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd D:/epg/codes/zp-cli
|
|
11
|
+
npm link
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
执行后 `zp-cli` 命令将指向当前目录,可以直接使用:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
zp-cli --help
|
|
18
|
+
zp-cli init
|
|
19
|
+
zp-cli upload ./some-file --server <服务器别名> --remote-path /tmp/test
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 取消链接
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd D:/epg/codes/zp-cli
|
|
26
|
+
npm unlink -g zp-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
或直接全局卸载:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm uninstall -g zp-cli
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 验证链接状态
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 查看 zp-cli 命令指向的路径
|
|
39
|
+
which zp-cli
|
|
40
|
+
|
|
41
|
+
# 应输出类似:
|
|
42
|
+
# /c/Users/<用户名>/AppData/Roaming/npm/zp-cli -> /d/epg/codes/zp-cli/bin/zp-cli.js
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 调试流程
|
|
48
|
+
|
|
49
|
+
### 1. 基础命令测试
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# 帮助信息
|
|
53
|
+
zp-cli --help
|
|
54
|
+
zp-cli upload --help
|
|
55
|
+
zp-cli init --help
|
|
56
|
+
|
|
57
|
+
# 版本
|
|
58
|
+
zp-cli -v
|
|
59
|
+
|
|
60
|
+
# 配置路径
|
|
61
|
+
zp-cli config path
|
|
62
|
+
|
|
63
|
+
# 查看配置
|
|
64
|
+
zp-cli config show
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. 初始化配置
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# 生成 demo 配置
|
|
71
|
+
zp-cli init
|
|
72
|
+
|
|
73
|
+
# 编辑配置文件,填入真实的服务器信息
|
|
74
|
+
notepad %USERPROFILE%\.zp-cli.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. 上传测试
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 指定服务器和远程路径(跳过 Git 匹配)
|
|
81
|
+
zp-cli upload ./test.txt --server <服务器别名> --remote-path /tmp/test.txt
|
|
82
|
+
|
|
83
|
+
# 上传目录
|
|
84
|
+
zp-cli upload ./dist --server <服务器别名> --remote-path /tmp/dist
|
|
85
|
+
|
|
86
|
+
# 在 Git 仓库内,自动匹配(需要先配好 mappings)
|
|
87
|
+
zp-cli upload ./vue_zte3.0/dist
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. 查看部署结果
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 登录服务器验证(根据实际配置替换信息)
|
|
94
|
+
ssh <用户名>@<服务器地址> "ls -la /tmp/"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 常见问题
|
|
100
|
+
|
|
101
|
+
### 命令找不到
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# 检查 npm 全局 bin 目录是否在 PATH 中
|
|
105
|
+
npm config get prefix
|
|
106
|
+
|
|
107
|
+
# Windows 下通常在:
|
|
108
|
+
# C:\Users\<用户名>\AppData\Roaming\npm
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 修改代码后不生效
|
|
112
|
+
|
|
113
|
+
npm link 后修改代码会立即生效,无需重新 link。如果出现缓存问题:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# 重新 link
|
|
117
|
+
npm unlink -g zp-cli
|
|
118
|
+
npm link
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 权限问题(Linux/Mac)
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
sudo npm link
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Windows 上 tar 命令报错
|
|
128
|
+
|
|
129
|
+
确保使用 Git Bash 终端运行,Git Bash 自带 tar 命令。或安装 WSL。
|
package/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# zp-cli
|
|
2
|
+
|
|
3
|
+
将本地代码通过 SSH 部署到远程服务器的命令行工具。支持单文件/目录上传,支持同一仓库不同子目录部署到不同服务器。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @wxuns/zp-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 快速开始
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 1. 生成配置文件模板
|
|
15
|
+
zp-cli init
|
|
16
|
+
|
|
17
|
+
# 2. 编辑配置文件,填入你的服务器信息
|
|
18
|
+
# Windows: notepad %USERPROFILE%\.zp-cli.json
|
|
19
|
+
# Linux/Mac: vim ~/.zp-cli.json
|
|
20
|
+
|
|
21
|
+
# 3. 上传文件
|
|
22
|
+
zp-cli upload ./dist/index.html
|
|
23
|
+
zp-cli upload ./dist
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 命令一览
|
|
29
|
+
|
|
30
|
+
| 命令 | 说明 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| `zp-cli init` | 生成 demo 配置文件 `~/.zp-cli.json` |
|
|
33
|
+
| `zp-cli upload <路径>` | 上传文件或目录到远程服务器 |
|
|
34
|
+
| `zp-cli config show` | 查看当前配置内容 |
|
|
35
|
+
| `zp-cli config path` | 显示配置文件路径 |
|
|
36
|
+
| `zp-cli --help` | 查看帮助 |
|
|
37
|
+
| `zp-cli -v` | 查看版本 |
|
|
38
|
+
|
|
39
|
+
### upload 命令选项
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
zp-cli upload <路径> [选项]
|
|
43
|
+
|
|
44
|
+
选项:
|
|
45
|
+
-s, --server <别名> 指定目标服务器(覆盖自动匹配)
|
|
46
|
+
-r, --remote-path <路径> 指定远程目标路径(覆盖配置中的默认值)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 配置文件说明
|
|
52
|
+
|
|
53
|
+
配置文件路径:`~/.zp-cli.json`(Windows 下为 `%USERPROFILE%\.zp-cli.json`)
|
|
54
|
+
|
|
55
|
+
执行 `zp-cli init` 会生成如下 demo 配置:
|
|
56
|
+
|
|
57
|
+
```jsonc
|
|
58
|
+
{
|
|
59
|
+
"servers": [
|
|
60
|
+
{
|
|
61
|
+
"alias": "test-server", // 服务器别名,命令行中用于指定目标
|
|
62
|
+
"host": "192.168.1.100", // 服务器 IP 或域名
|
|
63
|
+
"port": 22, // SSH 端口,默认 22
|
|
64
|
+
"username": "root", // SSH 登录用户名
|
|
65
|
+
"password": "your-password", // 密码认证(与 privateKeyPath 二选一)
|
|
66
|
+
"privateKeyPath": "~/.ssh/id_rsa",// 私钥认证(与 password 二选一)
|
|
67
|
+
"defaultRemotePath": "/home/www", // 默认远程目录(可被 --remote-path 覆盖)
|
|
68
|
+
"rootPassword": "" // root 密码,需要 su root 时填写
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
|
|
72
|
+
"mappings": [
|
|
73
|
+
{
|
|
74
|
+
"gitRemoteUrl": "git@github.com:yourorg/project.git",
|
|
75
|
+
"serverAlias": "test-server",
|
|
76
|
+
"remotePath": "/var/www/project",
|
|
77
|
+
"subdirectoryMappings": {}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### servers 字段
|
|
84
|
+
|
|
85
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
86
|
+
|------|------|------|------|
|
|
87
|
+
| `alias` | string | **必填** | 服务器别名,用于 `--server` 参数和 `mappings` 中引用 |
|
|
88
|
+
| `host` | string | **必填** | 服务器 IP 或域名 |
|
|
89
|
+
| `port` | number | 选填 | SSH 端口,默认 `22` |
|
|
90
|
+
| `username` | string | **必填** | 登录用户名 |
|
|
91
|
+
| `password` | string | **条件必填** | 登录密码,与 `privateKeyPath` 至少填一个 |
|
|
92
|
+
| `privateKeyPath` | string | **条件必填** | SSH 私钥路径,与 `password` 至少填一个。支持 `~` |
|
|
93
|
+
| `defaultRemotePath` | string | 选填 | 默认远程部署目录,可被 `--remote-path` 覆盖 |
|
|
94
|
+
| `rootPassword` | string | 选填 | root 密码,需要提权操作时填写 |
|
|
95
|
+
|
|
96
|
+
> **条件必填**:`password` 和 `privateKeyPath` 至少填一个。同时存在时优先使用 `privateKeyPath`。
|
|
97
|
+
|
|
98
|
+
### mappings 字段
|
|
99
|
+
|
|
100
|
+
每条映射将一个 Git 仓库关联到服务器部署路径。
|
|
101
|
+
|
|
102
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
103
|
+
|------|------|------|------|
|
|
104
|
+
| `gitRemoteUrl` | string | **必填** | Git 远程仓库地址,支持 SSH 和 HTTPS 两种格式(自动归一化匹配) |
|
|
105
|
+
| `serverAlias` | string | **条件必填** | 目标服务器别名,有子映射时可省略 |
|
|
106
|
+
| `remotePath` | string | **条件必填** | 远程部署根路径,有子映射时可省略 |
|
|
107
|
+
| `subdirectoryMappings` | object | 选填 | 子目录映射,可将仓库不同子目录部署到不同路径/服务器 |
|
|
108
|
+
|
|
109
|
+
> **条件必填**:如果所有文件都通过 `subdirectoryMappings` 映射到具体服务器和路径,则顶层 `serverAlias` 和 `remotePath` 可省略。否则必须填写。
|
|
110
|
+
>
|
|
111
|
+
> **优先级**:子目录映射 > 映射顶层 `serverAlias` / `remotePath`
|
|
112
|
+
|
|
113
|
+
### 子目录映射(subdirectoryMappings)
|
|
114
|
+
|
|
115
|
+
支持两种格式:
|
|
116
|
+
|
|
117
|
+
**格式一:字符串 — 同服务器不同路径**
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
"subdirectoryMappings": {
|
|
121
|
+
"web": "/var/www/project/frontend"
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
上传 `./web/index.js` → 部署到 `/var/www/project/frontend/index.js`
|
|
126
|
+
|
|
127
|
+
**格式二:对象 — 部署到不同服务器**
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
"subdirectoryMappings": {
|
|
131
|
+
"api": {
|
|
132
|
+
"serverAlias": "backend-server",
|
|
133
|
+
"remotePath": "/opt/services/api"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
上传 `./api/main.py` → 部署到 `backend-server` 的 `/opt/services/api/main.py`
|
|
139
|
+
|
|
140
|
+
**对象格式字段说明:**
|
|
141
|
+
|
|
142
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
143
|
+
|------|------|------|------|
|
|
144
|
+
| `serverAlias` | string | **必填** | 目标服务器别名 |
|
|
145
|
+
| `remotePath` | string | **必填** | 该子目录在目标服务器上的部署路径 |
|
|
146
|
+
|
|
147
|
+
**完整示例:**
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"servers": [
|
|
152
|
+
{ "alias": "web-server", "host": "10.0.0.1", "username": "root", "password": "xxx" },
|
|
153
|
+
{ "alias": "backend-server", "host": "10.0.0.2", "username": "root", "password": "xxx" }
|
|
154
|
+
],
|
|
155
|
+
"mappings": [
|
|
156
|
+
{
|
|
157
|
+
"gitRemoteUrl": "git@github.com:yourorg/mono-repo.git",
|
|
158
|
+
"serverAlias": "web-server",
|
|
159
|
+
"remotePath": "/var/www/mono",
|
|
160
|
+
"subdirectoryMappings": {
|
|
161
|
+
"web": "/var/www/mono/frontend",
|
|
162
|
+
"api": {
|
|
163
|
+
"serverAlias": "backend-server",
|
|
164
|
+
"remotePath": "/opt/services/api"
|
|
165
|
+
},
|
|
166
|
+
"config": "/etc/mono-repo"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
对应部署结果:
|
|
174
|
+
|
|
175
|
+
| 上传路径 | 目标服务器 | 远程路径 |
|
|
176
|
+
|---------|-----------|---------|
|
|
177
|
+
| `./web/index.js` | web-server | `/var/www/mono/frontend/index.js` |
|
|
178
|
+
| `./api/main.py` | **backend-server** | `/opt/services/api/main.py` |
|
|
179
|
+
| `./config/app.conf` | web-server | `/etc/mono-repo/app.conf` |
|
|
180
|
+
| `./README.md` | web-server | `/var/www/mono/README.md` |
|
|
181
|
+
|
|
182
|
+
**纯子目录映射示例**(顶层不设 serverAlias/remotePath,全部由子映射决定):
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"servers": [
|
|
187
|
+
{ "alias": "web-server", "host": "10.0.0.1", "username": "root", "password": "xxx" },
|
|
188
|
+
{ "alias": "backend-server", "host": "10.0.0.2", "username": "root", "password": "xxx" }
|
|
189
|
+
],
|
|
190
|
+
"mappings": [
|
|
191
|
+
{
|
|
192
|
+
"gitRemoteUrl": "git@github.com:yourorg/full-stack.git",
|
|
193
|
+
"subdirectoryMappings": {
|
|
194
|
+
"frontend": {
|
|
195
|
+
"serverAlias": "web-server",
|
|
196
|
+
"remotePath": "/var/www/frontend"
|
|
197
|
+
},
|
|
198
|
+
"backend": {
|
|
199
|
+
"serverAlias": "backend-server",
|
|
200
|
+
"remotePath": "/opt/services/backend"
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
| 上传路径 | 目标服务器 | 远程路径 |
|
|
209
|
+
|---------|-----------|---------|
|
|
210
|
+
| `./frontend/index.html` | web-server | `/var/www/frontend/index.html` |
|
|
211
|
+
| `./backend/app.py` | **backend-server** | `/opt/services/backend/app.py` |
|
|
212
|
+
| `./README.md` | ❌ 报错 | 未匹配到子映射,且无顶层回退路径 |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Git URL 匹配规则
|
|
217
|
+
|
|
218
|
+
配置中的 `gitRemoteUrl` 和实际仓库的 `origin` 地址会自动归一化后匹配,以下写法等价:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
git@github.com:org/repo.git ←→ https://github.com/org/repo.git
|
|
222
|
+
ssh://git@github.com:22/org/repo.git ←→ git@github.com:org/repo.git
|
|
223
|
+
git@gitlab.com:group/sub/repo.git ←→ https://gitlab.com/group/sub/repo.git
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 部署流程
|
|
229
|
+
|
|
230
|
+
执行 `zp-cli upload` 时的完整流程:
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
1. 检查本地路径是否存在
|
|
234
|
+
2. 读取 ~/.zp-cli.json 配置
|
|
235
|
+
3. 确定目标服务器和远程路径
|
|
236
|
+
├─ 命令行指定了 --server / --remote-path → 直接使用
|
|
237
|
+
└─ 未指定 → 读取 .git/config 获取 origin 地址 → 匹配 mappings
|
|
238
|
+
4. 建立 SSH 连接
|
|
239
|
+
5. 如果是目录 → 本地 tar -czf 打包
|
|
240
|
+
6. 上传文件到服务器 /tmp 临时目录
|
|
241
|
+
7. 在服务器上解压/复制到目标路径
|
|
242
|
+
8. 清理远程临时文件
|
|
243
|
+
9. 关闭连接
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 常见问题
|
|
249
|
+
|
|
250
|
+
**Q: 报错"配置文件不存在"**
|
|
251
|
+
A: 先执行 `zp-cli init` 生成配置文件。
|
|
252
|
+
|
|
253
|
+
**Q: 报错"无法自动确定部署目标"**
|
|
254
|
+
A: 当前目录不在 Git 仓库内,或配置文件中没有匹配的映射。可以用 `--server` 和 `--remote-path` 手动指定。
|
|
255
|
+
|
|
256
|
+
**Q: 如何部署到同一台服务器的不同目录?**
|
|
257
|
+
A: 在 `subdirectoryMappings` 中用字符串格式配置即可。
|
|
258
|
+
|
|
259
|
+
**Q: 如何将仓库的不同子目录部署到不同服务器?**
|
|
260
|
+
A: 在 `subdirectoryMappings` 中用对象格式,指定 `serverAlias` 和 `remotePath`。
|
|
261
|
+
|
|
262
|
+
**Q: Windows 上打包报错?**
|
|
263
|
+
A: 确保系统中有 `tar` 命令(Git Bash 自带)。或使用 WSL。
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 项目结构
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
zp-cli/
|
|
271
|
+
├── package.json
|
|
272
|
+
├── bin/
|
|
273
|
+
│ └── zp-cli.js # 主入口
|
|
274
|
+
├── lib/
|
|
275
|
+
│ ├── commands/
|
|
276
|
+
│ │ ├── init.js # 生成 demo 配置
|
|
277
|
+
│ │ └── upload.js # 上传部署逻辑
|
|
278
|
+
│ ├── core/
|
|
279
|
+
│ │ ├── configManager.js # 配置读写
|
|
280
|
+
│ │ ├── gitHelper.js # Git 仓库感知、URL 归一化、路径映射
|
|
281
|
+
│ │ └── sshDeployer.js # SSH 连接、打包、上传、解压
|
|
282
|
+
│ └── utils/
|
|
283
|
+
│ └── logger.js # 终端彩色输出
|
|
284
|
+
└── README.md
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## License
|
|
288
|
+
|
|
289
|
+
MIT
|
package/bin/zp-cli.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* zp-cli - 命令行部署工具主入口
|
|
5
|
+
* 使用 commander 解析命令行参数,提供 init / upload / config 子命令
|
|
6
|
+
*/
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const configManager = require('../lib/core/configManager');
|
|
10
|
+
const logger = require('../lib/utils/logger');
|
|
11
|
+
const pkg = require('../package.json');
|
|
12
|
+
|
|
13
|
+
const program = new Command();
|
|
14
|
+
|
|
15
|
+
program
|
|
16
|
+
.name('zp-cli')
|
|
17
|
+
.description('zp-cli - 高效的命令行部署工具,将本地代码通过 SSH 部署到远程服务器')
|
|
18
|
+
.version(pkg.version, '-v, --version', '显示版本号');
|
|
19
|
+
|
|
20
|
+
// ========== init 命令 ==========
|
|
21
|
+
program
|
|
22
|
+
.command('init')
|
|
23
|
+
.alias('i')
|
|
24
|
+
.description('生成 demo 配置文件 ~/.zp-cli.json')
|
|
25
|
+
.action(async () => {
|
|
26
|
+
const initCmd = require('../lib/commands/init');
|
|
27
|
+
await initCmd.run();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// ========== upload 命令 ==========
|
|
31
|
+
program
|
|
32
|
+
.command('upload <路径>')
|
|
33
|
+
.alias('up')
|
|
34
|
+
.description('上传文件或目录到远程服务器')
|
|
35
|
+
.option('-s, --server <别名>', '指定目标服务器别名')
|
|
36
|
+
.option('-r, --remote-path <路径>', '指定远程目标路径(覆盖配置中的默认值)')
|
|
37
|
+
.action(async (localPath, options) => {
|
|
38
|
+
const uploadCmd = require('../lib/commands/upload');
|
|
39
|
+
await uploadCmd.run(localPath, options);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ========== config 命令(查看/管理配置) ==========
|
|
43
|
+
const configCmd = program
|
|
44
|
+
.command('config')
|
|
45
|
+
.alias('c')
|
|
46
|
+
.description('查看和管理配置信息');
|
|
47
|
+
|
|
48
|
+
configCmd
|
|
49
|
+
.command('show')
|
|
50
|
+
.alias('ls')
|
|
51
|
+
.description('显示当前配置文件内容')
|
|
52
|
+
.action(() => {
|
|
53
|
+
const config = configManager.loadConfig();
|
|
54
|
+
if (!config) {
|
|
55
|
+
logger.error('配置文件不存在,请先执行 ' + chalk.cyan('zp-cli init'));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
logger.log(chalk.bold('\n📋 当前配置:\n'));
|
|
59
|
+
logger.log(JSON.stringify(config, null, 2));
|
|
60
|
+
logger.newline();
|
|
61
|
+
logger.log(chalk.gray(`配置文件路径: ${configManager.getConfigPath()}`));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
configCmd
|
|
65
|
+
.command('path')
|
|
66
|
+
.alias('p')
|
|
67
|
+
.description('显示配置文件路径')
|
|
68
|
+
.action(() => {
|
|
69
|
+
logger.log(configManager.getConfigPath());
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ========== 未提供子命令时显示帮助 ==========
|
|
73
|
+
program.on('command:*', () => {
|
|
74
|
+
logger.error(`未知命令: ${program.args.join(' ')}`);
|
|
75
|
+
logger.log('');
|
|
76
|
+
program.help();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// 如果没有输入任何命令,显示帮助
|
|
80
|
+
if (process.argv.length <= 2) {
|
|
81
|
+
program.help();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* init.js - 配置初始化命令
|
|
3
|
+
* 直接生成一个 demo 配置文件,用户自行修改
|
|
4
|
+
*/
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const logger = require('../utils/logger');
|
|
7
|
+
const configManager = require('../core/configManager');
|
|
8
|
+
|
|
9
|
+
/** demo 配置模板 */
|
|
10
|
+
const DEMO_CONFIG = {
|
|
11
|
+
servers: [
|
|
12
|
+
{
|
|
13
|
+
alias: "test-server",
|
|
14
|
+
host: "192.168.1.100",
|
|
15
|
+
port: 22,
|
|
16
|
+
username: "root",
|
|
17
|
+
password: "your-password",
|
|
18
|
+
// privateKeyPath: "~/.ssh/id_rsa", // 私钥认证,与 password 二选一
|
|
19
|
+
defaultRemotePath: "/home/www",
|
|
20
|
+
rootPassword: "" // 需要 su root 时填写
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
alias: "prod-server",
|
|
24
|
+
host: "10.0.0.1",
|
|
25
|
+
port: 22,
|
|
26
|
+
username: "deploy",
|
|
27
|
+
password: "",
|
|
28
|
+
privateKeyPath: "~/.ssh/id_rsa",
|
|
29
|
+
defaultRemotePath: "/home/www",
|
|
30
|
+
rootPassword: ""
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
|
|
34
|
+
mappings: [
|
|
35
|
+
// ── 示例1:整个仓库部署到同一台服务器 ──
|
|
36
|
+
{
|
|
37
|
+
"gitRemoteUrl": "git@github.com:yourorg/simple-project.git",
|
|
38
|
+
"serverAlias": "test-server",
|
|
39
|
+
"remotePath": "/var/www/simple-project"
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
// ── 示例2:同一仓库,不同子目录部署到不同服务器(顶层 + 子映射混合) ──
|
|
43
|
+
{
|
|
44
|
+
"gitRemoteUrl": "git@github.com:yourorg/mono-repo.git",
|
|
45
|
+
"serverAlias": "test-server",
|
|
46
|
+
"remotePath": "/var/www/mono",
|
|
47
|
+
"subdirectoryMappings": {
|
|
48
|
+
"web": "/var/www/mono/frontend",
|
|
49
|
+
"api": {
|
|
50
|
+
"serverAlias": "prod-server",
|
|
51
|
+
"remotePath": "/opt/services/api"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
// ── 示例3:纯子目录映射,serverAlias/remotePath 全在子映射里 ──
|
|
57
|
+
{
|
|
58
|
+
"gitRemoteUrl": "git@github.com:yourorg/full-stack.git",
|
|
59
|
+
"subdirectoryMappings": {
|
|
60
|
+
"frontend": {
|
|
61
|
+
"serverAlias": "test-server",
|
|
62
|
+
"remotePath": "/var/www/frontend"
|
|
63
|
+
},
|
|
64
|
+
"backend": {
|
|
65
|
+
"serverAlias": "prod-server",
|
|
66
|
+
"remotePath": "/opt/services/backend"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 执行 init 命令
|
|
75
|
+
*/
|
|
76
|
+
async function run() {
|
|
77
|
+
const configPath = configManager.getConfigPath();
|
|
78
|
+
|
|
79
|
+
// 已存在则提示
|
|
80
|
+
if (configManager.configExists()) {
|
|
81
|
+
logger.warn(`配置文件已存在: ${configPath}`);
|
|
82
|
+
logger.log(chalk.gray('如需重新生成,请先手动删除该文件'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
configManager.saveConfig(DEMO_CONFIG);
|
|
87
|
+
logger.success(`配置文件已生成: ${configPath}`);
|
|
88
|
+
logger.newline();
|
|
89
|
+
logger.log(chalk.bold('请编辑配置文件,填入你的服务器信息和仓库映射。'));
|
|
90
|
+
logger.log(chalk.gray('详细说明请参考 README.md 或执行 zp-cli init --help'));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { run };
|