# builder 按统一契约完成项目的 DEB 包与 Docker 镜像构建和发布。规范本体见 [references/contract.md](references/contract.md),`scripts/check.py` 是契约的 可执行校验器。 ## 什么时候使用 - "用 builder 初始化这个项目" - "帮我构建这个项目的 DEB / Docker 镜像" - "把 1.2.3 发布到包仓库 / 镜像仓库" - "检查这个项目的 makefile.builder 是否符合 builder 契约" - "看看项目现在的发布流程" 只构建不上传时明确说明即可;上传永远需要你显式授权。 ## 项目接入契约 对新项目说「用 builder 初始化」。Agent 会探测轨道、按 `templates/makefile.builder` 写出项目根 `makefile.builder`,并列出缺的发布配置。 不改用户已有的 `Makefile`。 1. `makefile.builder` 目标:`help/build/clean/version` + 条件 `deb/docker/push*`, 变量 `ARCH/VERSION/DIST_DIR/PROJECT_NAME`。 `VERSION` 通过 `include /scripts/version.mk` 从 Git 推导。 2. 运行 `python3 -I -S /scripts/check.py . --ready` 直到构建项 PASS。 缺发布键只挡住上传,不挡住构建。 3. 在项目根 `.env` 配置发布环境变量: ```text DEB_SERVER_URL=https://deb.example.com DEB_REPOSITORY=main DEB_TOKEN= # 只放 .env 或密钥系统,不进 git DOCKER_REGISTRY=registry.example.com ``` 4. 日常发布就是两条命令: `make -f makefile.builder deb && make -f makefile.builder push-deb`、 `make -f makefile.builder push-docker`。 ## 版本号 产物版本从 **当前 HEAD 的 Git 祖先** 推导,不调用 manage-release。 正式 tag 仍由 manage-release 创建;builder 只读取。完整规则见 [contract.md「版本号」](references/contract.md#版本号)。 | 谁 | 做什么 | | --- | --- | | manage-release | 选定下一个正式 SemVer,打 annotated tag `vX.Y.Z` | | builder | 读 HEAD:落在稳定 tag 上则打正式产物,否则打测试产物 | | `make -f makefile.builder version` | 输出一行规范版本(无 `v` 前缀),DEB / Docker 都从它渲染 | **不要**用 `git tag \| sort -V \| tail -1` 取全仓库最大号,也不要把 `git describe --dirty` 的原始字符串写进 DEB 或镜像 tag。 ### 正式(HEAD 恰好是稳定 tag `v1.4.2`) ```text Git tag v1.4.2 规范版本 1.4.2 DEB foo_1.4.2_amd64.deb Version: 1.4.2 Docker registry/ns/foo:1.4.2 ``` 稳定 tag 仅匹配 `v..`,不含 `-rc`、`-app-N` 等后缀。 不是 exact-match 就不是正式包。 ### 测试(其它任何 commit) 基线 = 祖先上最近的那颗稳定 tag(没有则为 `0.0.0`),再加上清洗后的 分支名、相对距离、短 SHA。测试与正式进**同一个** apt / Docker 仓库, 所以 DEB 必须用 `~`,保证测试包不会 `apt upgrade` 盖住正式包。 分支 `feat/login-v2`,相对 `v1.4.2` 第 7 个 commit,SHA `abc1234`: ```text 规范 / DEB 1.4.2~feat-login-v2.7+gabc1234 文件名 foo_1.4.2~feat-login-v2.7+gabc1234_amd64.deb Docker registry/ns/foo:1.4.2-feat-login-v2.7.gabc1234 ``` Docker tag 由规范版本映射:`~` → `-`,`+g` → `.g`(Docker 不允许 `~`)。 安装测试包必须显式指定版本或完整 tag,不能靠无参 `apt upgrade`。 ### 分支名清洗 小写;`/`、`_` 改为 `-`;去掉其它非法字符;压缩连续 `-`;过长截断。 detached HEAD 用 `detached`,CI 可注入 `BUILD_BRANCH` / `CI_COMMIT_BRANCH` / `GITHUB_REF_NAME`。脏工作树不把 `-dirty` 写进版本(发布本身会拒绝)。 ## 使用示例 ```text 用 builder 初始化这个项目。 用 builder 检查这个项目的 makefile.builder 是否符合契约。 用 builder 构建当前版本的 DEB 和镜像,先不要上传。 用 builder 把当前 commit 的产物发布到项目已配置的仓库。 用 builder 发布多平台 linux/amd64,linux/arm64 镜像。 ``` ## 脚本一览 | 脚本 | 用途 | |------|------| | `scripts/check.py` | 校验契约(`--ready` 含工具链与发布键名,`--build` 实构核对产物) | | `templates/makefile.builder` | 初始化用的契约文件骨架,拷到项目根 | | `scripts/version.sh` | 从 Git 祖先稳定 tag 推导规范版本 / Docker tag | | `scripts/version.mk` | `makefile.builder` `include`,设置 `VERSION` 与 `IMAGE_TAG` | | `scripts/upload_deb.sh` | 上传 `.deb` 到 HTTP 包仓库(multipart package/token/repository_name) | | `scripts/publish_docker.sh` | buildx 构建 + 推送镜像,远端 digest 验证 | | `scripts/verify_deb.sh` | 核对包元数据、内容与 SHA-256 | 环境变量契约、脚本解析顺序(`$BUILDER_SKILL_DIR` → `~/.pouch/skills/builder/scripts/`)、 脏工作树策略等完整规则见 contract.md。