--- name: builder description: >- 初始化或检查 makefile.builder 契约,再构建或发布 deb/镜像。触发词:初始化 builder、检查 makefile.builder、构建/发布 deb、推送 apt、构建/发布 Docker 镜像、make push。未授权不上传。Docker 仅用户点名镜像时才走。 --- # Builder:DEB / Docker 构建发布 **make 管构建,skill 脚本管发布,本 SKILL.md 只留脚本做不了的决策。** 项目状态是根目录 `makefile.builder` 与发布用 `.env.builder`,不要创建 `.pouch/builder/`,不要改用户的 `Makefile` / `makefile` / `.env`。 开始时解析当前 `SKILL.md` 所在目录,记为 ``。优先 `git rev-parse --show-toplevel` 解析项目根。 ## 选择模式 - 初始化、接入 builder,或还没有 `makefile.builder`:执行「初始化」。 - 检查契约或发布配置:执行「检查」。 - 构建、发布、上传:执行「工作流」。不要静默初始化。 - 不适用:本地安装/卸载 DEB;RPM/APK/语言包;从零设计打包体系(先出方案);普通编码与 Dockerfile 编辑。 - 改本 skill 自身:契约先改 `scripts/check.py`,再同步 [contract.md](references/contract.md) 与 templates;不在生产上传上试脚本。 ## 初始化 1. 确认项目根。探测 `makefile.builder`、`.env.builder`、用户 Makefile(只当抄配方的证据,不改)、`Dockerfile`、`debian/`。`.env.builder` 只看键是否存在且非空,不读、不打印值。不要读取用户 `.env`。 2. 判定轨道:有 Dockerfile → docker;有 deb 信号或用户要打 deb → deb;都不清则问。不要猜测 registry、token 或仓库名。 3. 没有 `makefile.builder`:把 `/templates/makefile.builder` 拷到项目根。按轨道删掉未使用的 deb/docker/push* 段,把 `build` 的 TODO 换成仓库里已有的真实编译命令(可从用户 Makefile 抄配方,但不要 `include` 或递归调用它)。`include` builder 的 `scripts/version.mk`。双产物把 `push` 改成 `push: push-deb push-docker`。不要改用户 Makefile。 4. 已有 `makefile.builder`:跑检查;按 FAIL 给出修补说明。不覆盖该文件,除非用户明确要求按契约改。不要调用 create-makefile(版本规则冲突)。 5. 没有 `.env.builder`:把 `/templates/env.builder` 拷到项目根(注释键,不含值)。缺发布键时在报告里给出可粘贴示例,并把 `.env.builder` 加入 `.gitignore`,不要提交。 6. 运行 `python3 -I -S /scripts/check.py --ready`。结构校验通过且当前轨道能构建才称「完成」;只缺发布键是「部分完成」。契约 FAIL 或轨道工具缺失是「阻塞」。除非用户明确要求,不提交、不推送、不上传。 ```text ## builder 初始化:完成 | 部分完成 | 阻塞 已具备: … 待配置: 路径 + 字段 + 可粘贴示例 + 缺了会挡住哪步 工具链: make / docker / dpkg-deb(缺则怎么装,不擅自安装) 下一步: 一句话 ``` ```text # .env.builder 键名示例 DEB_SERVER_URL=https://deb.example.com DEB_REPOSITORY=main DEB_TOKEN= DOCKER_REGISTRY=registry.example.com ``` ## 检查 只读。运行 `check.py --ready`,用同一报告格式,标题改为 `## builder 检查:…`。不写 `makefile.builder` / `.env.builder`,不改用户 Makefile 或 `.env`。用户明确要求修复后再转入初始化。 ## 工作流 契约见 [contract.md](references/contract.md)。Docker 的 registry/tag 不明确时再读 [registry.md](references/registry.md)。 1. 跑 `check.py `;需要工具链与发布键时加 `--ready`;要实构 deb 时加 `--build`。契约 FAIL 或轨道工具缺失:停下,转入「初始化」,不要绕过校验,不要改用户 Makefile。只缺发布键:允许构建,禁止上传。未接契约的存量项目按 contract.md §6 发现已有入口,上传仍用 builder 脚本;成功交付一次后引导迁到 `makefile.builder`。 2. 仅当用户明确要求发布、上传或提交时才上传。不猜测生产端点;不把 token 写入输出、文件、提交或回复;不用 `set -x` 跑含凭据的命令。可能覆盖同版本时先问。脏工作树默认拒绝发布;用户明确接受时设 `ALLOW_UNCOMMITTED=1` 并注明未提交修改。 3. 构建:`make -f makefile.builder build ARCH= VERSION=`;DEB 再 `make -f makefile.builder deb ARCH=<...>`。版本按契约从 Git 祖先稳定 tag 推导,不要调用 manage-release,不要用全仓库最新 tag。仅获构建授权时不要走会自动上传的目标。脚本含 `rm -rf` 时先确认为受限构建目录。 4. DEB 上传前:`verify_deb.sh `。多个包时不凭文件时间猜测。镜像轨道由 `publish_docker.sh` 自带远端 inspect。 5. 发布优先 `make -f makefile.builder push[-deb|-docker]`,或直接调 `upload_deb.sh` / `publish_docker.sh`。脚本缺环境变量时加载 `.env.builder`(shell 显式值优先),不读 `.env`。不把 token 当命令行参数;不把脚本复制进项目。多平台镜像只能走 `publish_docker.sh`,不能拆进 make。 6. 发布成功不能只看「curl/push 已执行」。要有退出码、HTTP 成功或远端 digest;索引异步时报告「上传已接受,索引尚待更新」。最终回复给出包名/镜像引用、版本、架构、SHA-256 或 digest、源 commit、工作区状态和未完成项。