|
| 1 | +# Webhook-CD: 基于 Webhook 的持续部署工具 |
| 2 | + |
| 3 | +[English](README.md) | 简体中文 |
| 4 | + |
| 5 | +[](https://npmjs.org/package/@axiosleo/webhook-cd) |
| 6 | +[](https://npmjs.org/package/@axiosleo/webhook-cd) |
| 7 | +[](http://nodejs.org/download/) |
| 8 | +[](LICENSE) |
| 9 | + |
| 10 | +> **⚠️ 重要警告 / IMPORTANT WARNING** |
| 11 | +> |
| 12 | +> **🚫 本工具严禁在生产环境中使用!仅限开发环境使用!** |
| 13 | +> |
| 14 | +> **🚫 DO NOT USE THIS TOOL IN PRODUCTION ENVIRONMENTS! DEVELOPMENT USE ONLY!** |
| 15 | +> |
| 16 | +> 此工具为开发阶段的自动化部署工具,未经过生产环境的安全性和稳定性验证。在生产环境中使用可能导致数据丢失、服务中断或安全风险。 |
| 17 | +> |
| 18 | +> This tool is designed for development automation and has not been validated for production security and stability. Using it in production may result in data loss, service interruption, or security risks. |
| 19 | +
|
| 20 | +Webhook-CD 是一个通过监听来自 Coding.net 和 GitHub 平台的 webhook 来自动化持续部署工作流的工具。它处理 Git 合并请求/拉取请求事件,以触发已配置仓库的部署操作。 |
| 21 | + |
| 22 | +## 概述 |
| 23 | + |
| 24 | +系统工作原理: |
| 25 | + |
| 26 | +1. **监听 Webhook**:HTTP 服务器监听来自 Coding.net 和 GitHub 的 webhook 事件,特别是与合并请求/拉取请求相关的事件(创建、更新、合并、关闭)。 |
| 27 | +2. **自动化部署**:基于仓库配置,工具监控可部署事件(如合并的合并请求/拉取请求)。当为已配置的仓库和分支发生此类事件时,它会在指定的本地目录中执行 Git 操作(例如 checkout、pull)来部署更改。 |
| 28 | +3. **CLI 手动控制**:提供命令行界面(CLI)工具 `wcd`,用于手动任务检查和触发。 |
| 29 | + |
| 30 | +## 功能特性 |
| 31 | + |
| 32 | +- 与 Coding.net 和 GitHub 的 Webhook 集成(用于合并请求/拉取请求事件) |
| 33 | +- 基于 webhook 触发器的自动化 Git 操作部署 |
| 34 | +- 与 RabbitMQ 的消息队列集成,确保任务处理的可靠性 |
| 35 | +- 通过环境变量进行配置,提供灵活性 |
| 36 | +- CLI 工具(`wcd`)用于手动交互和任务管理 |
| 37 | + |
| 38 | +## 环境要求 |
| 39 | + |
| 40 | +- Node.js 和 npm |
| 41 | +- 访问您希望部署的 Coding.net 和/或 GitHub 仓库的权限 |
| 42 | +- RabbitMQ 服务器(推荐:在开发环境中使用 Docker) |
| 43 | +- Docker(可选,用于在开发中运行 RabbitMQ) |
| 44 | + |
| 45 | +## 安装和配置 |
| 46 | + |
| 47 | +### 1. 克隆仓库 |
| 48 | + |
| 49 | +```bash |
| 50 | +git clone <repository-url> |
| 51 | +cd webhook-cd |
| 52 | +``` |
| 53 | + |
| 54 | +### 2. 配置环境变量 |
| 55 | + |
| 56 | +应用程序使用环境变量进行配置。在项目根目录创建 `.env` 文件或在部署环境中设置这些变量。 |
| 57 | + |
| 58 | +**RabbitMQ 配置:** |
| 59 | + |
| 60 | +- `RABBITMQ_HOST`:RabbitMQ 服务器的主机名(默认:`localhost`) |
| 61 | +- `RABBITMQ_PORT`:RabbitMQ 端口(默认:`5672`) |
| 62 | +- `RABBITMQ_USER`:RabbitMQ 用户名(默认:`guest`) |
| 63 | +- `RABBITMQ_PASS`:RabbitMQ 密码(默认:`guest`) |
| 64 | + |
| 65 | +**Coding.net 配置:** |
| 66 | + |
| 67 | +- `CODING_USER`:您的 Coding.net 用户名 |
| 68 | +- `CODING_TOKEN`:您的 Coding.net 用户令牌,用于 API 访问 |
| 69 | + |
| 70 | +**GitHub 配置:** |
| 71 | + |
| 72 | +- `GITHUB_USER`:您的 GitHub 用户名 |
| 73 | +- `GITHUB_TOKEN`:您的 GitHub 个人访问令牌,用于 API 访问 |
| 74 | +- `GITHUB_WEBHOOK_SECRET`:(可选)用于 webhook 签名验证的密钥令牌 |
| 75 | + |
| 76 | +**应用程序配置:** |
| 77 | + |
| 78 | +- `WORKSPACE`:(可选)基础工作区目录。默认为相对于应用程序根目录的 `runtime/repos` |
| 79 | +- `LISTEN_HOST`:webhook 监听器的主机(默认:`0.0.0.0`) |
| 80 | +- `LISTEN_PORT`:webhook 监听器运行的端口(默认:`8800`) |
| 81 | + |
| 82 | +### 3. 启动 RabbitMQ(开发环境) |
| 83 | + |
| 84 | +对于开发环境,您可以使用 Docker 轻松启动 RabbitMQ 容器: |
| 85 | + |
| 86 | +```bash |
| 87 | +docker run -d --name rabbitmq \ |
| 88 | + -p 5672:5672 \ |
| 89 | + -p 15672:15672 \ |
| 90 | + -e RABBITMQ_DEFAULT_USER=guest \ |
| 91 | + -e RABBITMQ_DEFAULT_PASS=guest \ |
| 92 | + rabbitmq:3-management |
| 93 | +``` |
| 94 | + |
| 95 | +这将启动 RabbitMQ,包含: |
| 96 | + |
| 97 | +- AMQP 端口:`5672` |
| 98 | +- 管理界面:`http://localhost:15672`(用户名:`guest`,密码:`guest`) |
| 99 | + |
| 100 | +或者,项目包含一个预配置的 `docker-compose.yml` 文件,其中包含 RabbitMQ。您可以使用: |
| 101 | + |
| 102 | +```bash |
| 103 | +docker-compose up -d |
| 104 | +``` |
| 105 | + |
| 106 | +### 4. 配置 PM2 日志轮转 |
| 107 | + |
| 108 | +为了防止日志文件过大并消耗过多磁盘空间,项目使用 PM2 的日志轮转功能。以下是设置方法: |
| 109 | + |
| 110 | +1. 安装 PM2 日志轮转模块: |
| 111 | + |
| 112 | +```bash |
| 113 | +pm2 install pm2-logrotate |
| 114 | +``` |
| 115 | + |
| 116 | +2. 配置全局日志轮转设置: |
| 117 | + |
| 118 | +```bash |
| 119 | +pm2 set pm2-logrotate:max_size 100M # 每个日志文件的最大大小 |
| 120 | +pm2 set pm2-logrotate:retain 7 # 保留日志的天数 |
| 121 | +pm2 set pm2-logrotate:compress true # 压缩轮转的日志 |
| 122 | +pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss # 轮转日志的日期格式 |
| 123 | +pm2 set pm2-logrotate:workerInterval 30 # 检查间隔(秒) |
| 124 | +pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # 每天午夜轮转 |
| 125 | +pm2 set pm2-logrotate:rotateModule true # 启用模块轮转 |
| 126 | +``` |
| 127 | + |
| 128 | +3. 验证配置: |
| 129 | + |
| 130 | +```bash |
| 131 | +pm2 conf pm2-logrotate |
| 132 | +``` |
| 133 | + |
| 134 | +日志轮转配置将: |
| 135 | + |
| 136 | +- 当日志达到 100MB 或每天午夜时轮转日志 |
| 137 | +- 保留日志 7 天 |
| 138 | +- 压缩旧日志以节省空间 |
| 139 | +- 在 `logs` 目录中存储带时间戳的日志 |
| 140 | +- 自动清理旧日志 |
| 141 | + |
| 142 | +### 5. 安装依赖并运行应用程序 |
| 143 | + |
| 144 | +```bash |
| 145 | +npm install |
| 146 | +npm start |
| 147 | +``` |
| 148 | + |
| 149 | +或者,对于带有自动重新加载的开发: |
| 150 | + |
| 151 | +```bash |
| 152 | +npm run dev |
| 153 | +``` |
| 154 | + |
| 155 | +## Docker 部署 |
| 156 | + |
| 157 | +应用程序支持 Docker 容器化,为不同的服务提供灵活的部署选项。 |
| 158 | + |
| 159 | +### 1. 构建 Docker 镜像 |
| 160 | + |
| 161 | +```bash |
| 162 | +docker build -t webhook-cd . |
| 163 | +``` |
| 164 | + |
| 165 | +### 2. 容器启动选项 |
| 166 | + |
| 167 | +Docker 镜像支持基于 `MAIN_BIN` 环境变量运行两种不同的服务: |
| 168 | + |
| 169 | +- `MAIN_BIN=api`:运行 webhook API 服务器(`./bin/api.js`) |
| 170 | +- `MAIN_BIN=consumer`:运行消息队列消费者(`./bin/consumer.js`) |
| 171 | + |
| 172 | +### 3. 运行 API 服务器容器 |
| 173 | + |
| 174 | +API 服务器监听 webhook 并默认在端口 8800 上运行: |
| 175 | + |
| 176 | +```bash |
| 177 | +# 使用环境文件运行 |
| 178 | +docker run --env-file .env -e MAIN_BIN=api -p 8800:8800 webhook-cd |
| 179 | + |
| 180 | +# 或使用显式环境变量 |
| 181 | +docker run -e MAIN_BIN=api \ |
| 182 | + -e LISTEN_HOST=0.0.0.0 \ |
| 183 | + -e LISTEN_PORT=8800 \ |
| 184 | + -e RABBITMQ_HOST=your_rabbitmq_host \ |
| 185 | + -e CODING_USER=your_username \ |
| 186 | + -e CODING_TOKEN=your_token \ |
| 187 | + -e GITHUB_USER=your_github_username \ |
| 188 | + -e GITHUB_TOKEN=your_github_token \ |
| 189 | + -p 8800:8800 \ |
| 190 | + webhook-cd |
| 191 | +``` |
| 192 | + |
| 193 | +### 4. 运行消费者容器 |
| 194 | + |
| 195 | +消费者处理来自 RabbitMQ 队列的消息: |
| 196 | + |
| 197 | +```bash |
| 198 | +# 使用环境文件运行 |
| 199 | +docker run --env-file .env -e MAIN_BIN=consumer webhook-cd |
| 200 | + |
| 201 | +# 或使用显式环境变量 |
| 202 | +docker run -e MAIN_BIN=consumer \ |
| 203 | + -e RABBITMQ_HOST=your_rabbitmq_host \ |
| 204 | + -e RABBITMQ_USER=guest \ |
| 205 | + -e RABBITMQ_PASS=guest \ |
| 206 | + -e CODING_USER=your_username \ |
| 207 | + -e CODING_TOKEN=your_token \ |
| 208 | + -e GITHUB_USER=your_github_username \ |
| 209 | + -e GITHUB_TOKEN=your_github_token \ |
| 210 | + webhook-cd |
| 211 | +``` |
| 212 | + |
| 213 | +### 5. Docker Compose 示例 |
| 214 | + |
| 215 | +创建 `docker-compose.override.yml` 文件进行完整部署: |
| 216 | + |
| 217 | +```yaml |
| 218 | +version: "3.8" |
| 219 | + |
| 220 | +services: |
| 221 | + rabbitmq: |
| 222 | + image: rabbitmq:3-management |
| 223 | + ports: |
| 224 | + - "5672:5672" |
| 225 | + - "15672:15672" |
| 226 | + environment: |
| 227 | + RABBITMQ_DEFAULT_USER: guest |
| 228 | + RABBITMQ_DEFAULT_PASS: guest |
| 229 | + |
| 230 | + webhook-api: |
| 231 | + build: . |
| 232 | + ports: |
| 233 | + - "8800:8800" |
| 234 | + environment: |
| 235 | + - MAIN_BIN=api |
| 236 | + env_file: |
| 237 | + - .env |
| 238 | + depends_on: |
| 239 | + - rabbitmq |
| 240 | + |
| 241 | + webhook-consumer: |
| 242 | + build: . |
| 243 | + environment: |
| 244 | + - MAIN_BIN=consumer |
| 245 | + env_file: |
| 246 | + - .env |
| 247 | + depends_on: |
| 248 | + - rabbitmq |
| 249 | +``` |
| 250 | +
|
| 251 | +然后运行: |
| 252 | +
|
| 253 | +```bash |
| 254 | +docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d |
| 255 | +``` |
| 256 | + |
| 257 | +### 6. Docker 环境变量 |
| 258 | + |
| 259 | +在 Docker 中运行时,确保您的 `.env` 文件或环境变量包含: |
| 260 | + |
| 261 | +```bash |
| 262 | +# RabbitMQ 配置 |
| 263 | +RABBITMQ_HOST=localhost # 或您的 RabbitMQ 容器名称 |
| 264 | +RABBITMQ_PORT=5672 |
| 265 | +RABBITMQ_USER=guest |
| 266 | +RABBITMQ_PASS=guest |
| 267 | + |
| 268 | +# Coding.net 配置 |
| 269 | +CODING_USER=your_username |
| 270 | +CODING_TOKEN=your_token |
| 271 | + |
| 272 | +# GitHub 配置 |
| 273 | +GITHUB_USER=your_username |
| 274 | +GITHUB_TOKEN=your_token |
| 275 | +GITHUB_WEBHOOK_SECRET=your_webhook_secret |
| 276 | + |
| 277 | +# 应用程序配置 |
| 278 | +WORKSPACE=/app/runtime/repos # 容器路径 |
| 279 | +LISTEN_HOST=0.0.0.0 |
| 280 | +LISTEN_PORT=8800 |
| 281 | +``` |
| 282 | + |
| 283 | +### 7. 持久化数据的卷挂载 |
| 284 | + |
| 285 | +如果您需要在容器重启时保持仓库数据: |
| 286 | + |
| 287 | +```bash |
| 288 | +docker run --env-file .env \ |
| 289 | + -e MAIN_BIN=api \ |
| 290 | + -p 8800:8800 \ |
| 291 | + -v $(pwd)/runtime:/app/runtime \ |
| 292 | + webhook-cd |
| 293 | +``` |
| 294 | + |
| 295 | +## 使用方法 |
| 296 | + |
| 297 | +### 1. 配置 Webhook |
| 298 | + |
| 299 | +#### 对于 Coding.net 项目 |
| 300 | + |
| 301 | +对于您想要集成的每个 Coding.net 项目: |
| 302 | + |
| 303 | +1. 转到 Coding.net 中的项目设置 |
| 304 | +2. 找到"Webhooks"部分 |
| 305 | +3. 添加一个新的 webhook,包含以下详细信息: |
| 306 | + - **负载 URL**:`http://<your_server_address>:<PORT>/{platform}/{team}/{project}` |
| 307 | + - 将 `<your_server_address>` 替换为运行 Webhook-CD 的 IP 或主机名 |
| 308 | + - 将 `<PORT>` 替换为 Webhook-CD 监听的端口(例如 `8800`) |
| 309 | + - 将 `{platform}`、`{team}` 和 `{project}` 替换为实际的平台标识符(例如 `coding`)、您的团队名称和项目名称 |
| 310 | + - **内容类型**:`application/json` |
| 311 | + - **密钥令牌**:(可选但推荐)如果您设置了密钥令牌,您需要修改应用程序来验证它。当前的应用程序主要检查 `User-Agent` |
| 312 | + - **事件**:选择您想要触发 webhook 的事件。此工具主要为"合并请求"事件设计(Push、Opened、Merged、Closed、Commented) |
| 313 | + - 确保 webhook 处于活动状态 |
| 314 | + |
| 315 | +**重要**:应用程序当前通过检查 `User-Agent` 头是否为 `Coding.net Hook` 来验证 Coding.net webhook。 |
| 316 | + |
| 317 | +#### 对于 GitHub 项目 |
| 318 | + |
| 319 | +对于您想要集成的每个 GitHub 仓库: |
| 320 | + |
| 321 | +1. 转到 GitHub 上的仓库设置 |
| 322 | +2. 导航到"Settings" > "Webhooks" > "Add webhook" |
| 323 | +3. 使用以下详细信息配置 webhook: |
| 324 | + - **负载 URL**:`http://<your_server_address>:<PORT>/github/{owner}/{repo}` |
| 325 | + - 将 `<your_server_address>` 替换为运行 Webhook-CD 的 IP 或主机名 |
| 326 | + - 将 `<PORT>` 替换为 Webhook-CD 监听的端口(例如 `8800`) |
| 327 | + - 将 `{owner}` 和 `{repo}` 替换为您的 GitHub 用户名/组织和仓库名称 |
| 328 | + - **内容类型**:`application/json` |
| 329 | + - **密钥**:(可选但推荐)使用与 `GITHUB_WEBHOOK_SECRET` 环境变量相同的值进行签名验证 |
| 330 | + - **事件**:选择"Pull requests"以在拉取请求事件(opened、synchronized、closed)时触发 |
| 331 | + - **活动**:确保 webhook 处于活动状态 |
| 332 | + |
| 333 | +**重要**:当配置了密钥时,GitHub webhook 支持使用 HMAC-SHA256 的签名验证。 |
| 334 | + |
| 335 | +### 2. 部署工作原理 |
| 336 | + |
| 337 | +1. 当为受监控的仓库和分支在 Coding.net 或 GitHub 中发生配置的事件(例如合并请求被合并)时,平台会向您的 Webhook-CD 实例发送 webhook |
| 338 | +2. Webhook-CD 处理事件并触发适当的部署操作 |
| 339 | +3. 系统监控已配置仓库的可部署事件 |
| 340 | +4. 如果找到可部署事件,Webhook-CD 将尝试在相应的本地目录中执行 Git 操作(如 `git checkout`、`git reset --hard origin/{branch}`、`git pull`)。确保此目录存在并正确初始化为 Git 仓库,或者是工具可以克隆到的位置 |
| 341 | + |
| 342 | +## CLI 工具(`wcd`) |
| 343 | + |
| 344 | +项目包含一个名为 `wcd` 的 CLI 工具(在 `package.json` 的 `bin` 字段中定义)。 |
| 345 | + |
| 346 | +**安装(如果通过 `npm install` 不可用):** |
| 347 | +如果在 `npm install` 后未全局安装,您可能需要全局链接它或通过 `npx` 运行它。 |
| 348 | + |
| 349 | +```bash |
| 350 | +npm link # 如果您想直接使用 'wcd' |
| 351 | +# 或通过 npx 运行 |
| 352 | +npx @axiosleo/webhook-cd --help |
| 353 | +``` |
| 354 | + |
| 355 | +**可用命令:** |
| 356 | +CLI 允许您手动触发内部事件系统。这对于测试或重新处理任务很有用。命令在 `commands/` 目录中定义。 |
| 357 | + |
| 358 | +- `wcd push <project> <repo> [options]`:模拟 `GIT_MR_CREATED` 事件(注意:文件 `commands/push.js` 可能有命名错误,将自己称为 'pop') |
| 359 | +- `wcd refresh <project> <repo> [options]`:模拟 `GIT_MR_UPDATED` 事件(注意:文件 `commands/refresh.js` 可能有命名错误) |
| 360 | +- `wcd pop <project> <repo> [options]`:模拟 `GIT_MR_CLOSED` 事件 |
| 361 | + |
| 362 | +**CLI 命令的通用选项:** |
| 363 | + |
| 364 | +- `--platform <name>`:平台名称(默认:`coding`) |
| 365 | +- `-s, --source <branch>`:源分支(默认:`master`) |
| 366 | +- `-t, --target <branch>`:目标分支(默认:`master`) |
| 367 | + |
| 368 | +示例: |
| 369 | + |
| 370 | +```bash |
| 371 | +wcd pop myteam myawesomeproject myfrontendapp --source dev-branch |
| 372 | +``` |
| 373 | + |
| 374 | +## 许可证 |
| 375 | + |
| 376 | +本项目采用 MIT 许可证。详情请参见 `LICENSE` 文件。 |
0 commit comments