# PipeX **Repository Path**: xdho/pipex ## Basic Information - **Project Name**: PipeX - **Description**: pipeline, devops - **Primary Language**: Go - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-18 - **Last Updated**: 2026-04-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### PipeX #### 介绍 DevOps #### 使用 MQTT 作为消息中间件 主题前缀为 `pipex/v1`(与 HTTP `/api/v1` 行为一致)。需在配置中启用 MQTT(如 `mqtt.enable = true` 且配置 `broker`)。 **编码**:MQTT 命令体为 **UTF-8**(可无 BOM)。服务端在解析与写日志前会去掉 **UTF-8 BOM** 并 trim。日志体经 `PayloadForLog`:按 UTF-8 码点安全截断,避免截断半个汉字导致 `%s` 打印异常。 **订阅(客户端 → PipeX,QoS 1)** | 主题 | 说明 | |------|------| | `pipex/v1/project/create` | 创建项目 | | `pipex/v1/project/update/{project_id}` | 更新项目 | | `pipex/v1/build/start` | 启动构建 | | `pipex/v1/build/cancel/{build_id}` | 取消构建 | | `pipex/v1/artifact/request/{build_id}` | 请求产物信息 | | `pipex/v1/env/create` | 创建自定义构建环境 | **发布(PipeX → 客户端)** | 主题 | QoS | 保留 | 说明 | |------|-----|------|------| | `pipex/v1/project/notify/{project_id}` | 1 | 否 | 项目创建/更新通知 | | `pipex/v1/build/status/{build_id}` | 0 | 否 | 构建进度与状态 | | `pipex/v1/build/logs/{build_id}` | 0 | 否 | 构建日志行 | | `pipex/v1/build/event` | 1 | 否 | 构建结束汇总(外层为 Envelope) | | `pipex/v1/artifact/ready/{build_id}` | 1 | 否 | 产物就绪 | | `pipex/v1/env/list` | 1 | 是 | 环境列表 | | `pipex/v1/service/health` | 1 | 是 | 健康检查 | | `pipex/v1/service/stats` | 0 | 否 | 运行统计 | 外层 JSON 结构(`Envelope`)字段:`request_id`、`timestamp`(Unix 秒)、`project_id`、`build_id`、`status`、`data`、`msg`。部分推送整条为 Envelope,部分主题为扁平结构(见下)。 创建项目时可选 `repository`:远程仓库地址(`git@…`、`ssh://`、`http(s)://`)。PipeX **不存储、不处理** Git 账号密码,需在运行进程的环境(如 work 机已配置 SSH 免密)中完成鉴权;提供 `repository` 时会在项目工作区内执行 **`git clone -b `**(因此 **`default_branch` 与 `repository` 配套必填**,例如 `main`),并写入库表作为该仓库的补充元数据。未填 `repository` 时仅创建工作区目录,可不传 `default_branch`。 #### 消息示例(JSON) **1. 创建项目** — 发布至 `pipex/v1/project/create`: ```json { "request_id": "req-001", "name": "demo", "description": "示例项目", "repository": "git@github.com:acme/demo.git", "default_branch": "main" } ``` 不传 `repository` 时仅创建工作区目录,不执行 clone,此时可不传 `default_branch`。 **2. 更新项目** — 发布至 `pipex/v1/project/update/proj_xxxxxxxx`: ```json { "request_id": "req-002", "name": "demo2", "description": "新描述" } ``` **3. 启动构建** — 发布至 `pipex/v1/build/start`: - **`script`**(可选):相对**项目工作区根目录**的脚本路径,如 `build.sh`、`scripts/xxx.sh`;存在时在该目录下用 **`bash`/`sh`** 执行该文件(与 `command` 同时出现时**只执行 script**)。仓库内需已有该文件;`image` 当前不参与执行。 - **`command`**(可选):无 `script` 时在项目目录下执行 **`bash -c ""`**。 - 两者皆空时仍为**占位模拟构建**(仅进度与假日志)。 - 有 **`script` 或 `command`** 时:先在项目目录做 **`git fetch` + 快进合并**(**不再**使用无跟踪分支的裸 `git pull`)。逻辑:`commit_id` 优先 → `fetch` 后 `checkout --detach`;否则若 start 里带了 **`branch`** → `fetch origin `、`checkout`、`merge --ff-only origin/`;若 start 里 **`branch` 与 `commit_id` 皆空** → 使用项目创建时入库的 **`default_branch`**(若老项目为空则退回 `fetch origin` 后与 **`origin/HEAD`** 或 `origin/main` / `origin/master` 做 **`merge --ff-only`**)。**成功后再**执行脚本/命令;失败则构建结束,日志行前缀 **`[git]`**。 - **Windows**:会优先使用 **Git for Windows** 的 `Git\bin\bash.exe`(并避开 `System32\bash.exe`、WindowsApps 等 WSL/商店占位),避免 `execvpe(/bin/bash)` 类错误;`git`/`bash` 子进程会把 `mingw64\bin`、`usr\bin` 等 prepend 到 `PATH`。若仍异常,可设置环境变量 **`PIPEX_BASH`** 为 `bash.exe` 的绝对路径。 使用仓库内脚本示例: ```json { "request_id": "req-003", "project_id": "proj_xxxxxxxx", "script": "build.sh", "branch": "main", "commit_id": "abc1234" } ``` 仅一条 shell 命令示例: ```json { "request_id": "req-003b", "project_id": "proj_xxxxxxxx", "command": "echo build" } ``` **4. 取消构建** — 发布至 `pipex/v1/build/cancel/{build_id}`(`build_id` 可与主题一致): ```json { "request_id": "req-004", "build_id": "build_10001", "operator": "ci" } ``` **5. 请求产物** — 发布至 `pipex/v1/artifact/request/{build_id}`: ```json { "request_id": "req-005", "build_id": "build_10001" } ``` **6. 创建环境** — 发布至 `pipex/v1/env/create`: ```json { "request_id": "req-006", "name": "my-go", "image": "golang:1.22", "labels": { "team": "platform" } } ``` **7. 项目通知(订阅)** — `pipex/v1/project/notify/{project_id}`: ```json { "request_id": "req-001", "timestamp": 1713600000, "project_id": "proj_xxxxxxxx", "status": "ok", "msg": "project created", "data": { "action": "created", "project_id": "proj_xxxxxxxx", "name": "demo", "directory": "/abs/path/to/projects/proj_xxxxxxxx", "repository": "git@github.com:acme/demo.git" } } ``` **8. 构建状态(订阅)** — `pipex/v1/build/status/{build_id}`: ```json { "build_id": "build_10001", "status": "running", "progress": 54, "start_time": "2026-04-20T12:00:00+08:00" } ``` **9. 构建日志行(订阅)** — `pipex/v1/build/logs/{build_id}`: ```json { "build_id": "build_10001", "line": "[INFO] Compiling...", "level": "info", "timestamp": 1713600005 } ``` **10. 构建结束事件(订阅)** — `pipex/v1/build/event`: ```json { "request_id": "req-003", "timestamp": 1713600010, "project_id": "proj_xxxxxxxx", "build_id": "build_10001", "status": "success", "data": { "build_id": "build_10001", "project_id": "proj_xxxxxxxx", "status": "success", "duration": 12, "artifact_url": "/download/artifact/build_10001" } } ``` **11. 产物就绪(订阅)** — `pipex/v1/artifact/ready/{build_id}`: ```json { "build_id": "build_10001", "artifact_url": "/download/artifact/build_10001", "ready": true } ``` **12. 环境列表(订阅,保留消息)** — `pipex/v1/env/list`: ```json { "status": "ok", "data": [ { "name": "go-1.22", "image": "golang:1.22", "custom": false }, { "name": "my-go", "image": "golang:1.22", "custom": true, "labels": { "team": "platform" } } ] } ``` **13. 服务健康(订阅,保留消息)** — `pipex/v1/service/health`: ```json { "status": "ok", "data": { "status": "ok", "version": "1.0.0", "uptime_sec": 3600 } } ``` **14. 服务统计(订阅)** — `pipex/v1/service/stats`: ```json { "status": "ok", "data": { "queue_depth": 0, "running_builds": 0, "total_builds": 5 } } ``` #### 命令行快速验证(mosquitto) 将 `proj_xxxxxxxx`、`build_10001` 换成实际 ID;Broker 默认 `127.0.0.1:1883`。 ```bash mosquitto_pub -h 127.0.0.1 -t pipex/v1/project/create -m '{"request_id":"t1","name":"mqtt-demo"}' -q 1 mosquitto_sub -h 127.0.0.1 -t 'pipex/v1/project/notify/#' -v ``` 更完整的 HTTP 流水线示例见 `scripts/mqtt_smoke.sh`(创建项目、启动构建并订阅 `build/status`)。