# Builder 构建发布契约 v1 本契约是 builder skill 的规范本体。`scripts/check.py` 是它的可执行形态:改契约先改 check.py,本文档跟随。所有接入项目按同一套 make 目标、产物形状和环境变量执行, builder 脚本只做发布,不做项目特定的构建逻辑。 分工原则:**make 管构建(项目内、确定性),skill 脚本管发布(跨项目 SSOT), Agent 只保留授权判断和歧义处理。** ## 1. Make 目标 ### 必备目标(所有项目) | 目标 | 要求 | |------|------| | `help` | 分组列出全部目标;首屏含当前版本 | | `version` | 输出一行版本号,适合脚本消费 | | `clean` | 只删除明确、受限的构建产物目录 | | `build` | 编译/打包主产物;尊重 `ARCH`;**不得内含任何上传动作** | ### 条件目标 | 目标 | 适用 | 要求 | |------|------|------| | `deb` | 有 DEB 产物的项目 | 产出唯一 `$(DIST_DIR)/__.deb`;只构建不上传 | | `docker` | 有镜像的项目 | 构建本地单平台镜像 `linux/$(ARCH)`;**禁止 `--push`、禁止多平台** | | `push-deb` | 同时有 DEB 和镜像的项目 | 仅调 builder 的 `upload_deb.sh` 上传 `dist/*.deb` | | `push-docker` | 同时有 DEB 和镜像的项目 | 仅调 builder 的 `publish_docker.sh` | | `push` | 单一产物类型时必备;双产物项目为聚合 | 依序调用对应 push-* 或直接调脚本;是发布的唯一 make 入口 | 规则: 1. 项目有 DEB 产物的判据:Makefile 配方引用 `dpkg-deb`/`debuild` 或产出 `.deb`。 有镜像的判据:项目根存在 `Dockerfile`。 2. 双产物项目必须拆 `push-deb`/`push-docker`,`push` 依序聚合两者;单产物项目一个 `push` 即可。 3. `docker` 目标只能本地构建。多平台镜像无法拆成"make 构建 + 单独推送" (`buildx --push` 是一步),因此多平台发布只能走 `publish_docker.sh`。 4. push 类目标必须是薄包装:解析脚本路径后委托,不内联 curl/token/端点。 ## 2. 变量 | 变量 | 默认 | 说明 | |------|------|------| | `ARCH` | `amd64` | 仅允许 `amd64` \| `arm64`,非法值必须 `$(error)` 报错并提示合法值 | | `VERSION` | `` (空) | 为空时由 make 从 `git describe --tags --always --dirty` 推导 | | `DIST_DIR` | `dist` | DEB 产物目录 | | `PROJECT_NAME` | git 仓库名 | 包名/镜像名主体 | ## 3. 发布环境变量 ### DEB 轨道 | 变量 | 必填 | 说明 | |------|------|------| | `DEB_SERVER_URL` | 是 | 仓库服务地址 | | `DEB_TOKEN` | 是 | 认证令牌;只从环境读取,绝不进 argv/日志/git | | `DEB_REPOSITORY` | 是 | 目标仓库名 | | `DEB_UPLOAD_PATH` | 否 | 覆盖默认上传路径 `/api/v2/upload/package` | ### Docker 轨道 | 变量 | 必填 | 说明 | |------|------|------| | `DOCKER_REGISTRY` | 是 | registry 主机,无 scheme | | `DOCKER_REPOSITORY` | 否 | 默认取 git 仓库名 | | `IMAGE_TAG` | 否 | 默认 `git describe --tags --always --dirty` | | `PLATFORMS` | 否 | 默认 `linux/amd64`;多平台如 `linux/amd64,linux/arm64` | 配置来源优先级:shell 已显式设置的值 > 项目根 `.env` > 失败并询问用户。 `.env` 由 builder 脚本自动向上查找并加载(不回显任何值);当前 shell 已设置的值 优先于 `.env`。 ### 工作区安全 脏工作树(有未提交修改)默认拒绝发布;`ALLOW_UNCOMMITTED=1` 显式放行并在汇报中 注明镜像/包包含哪些未提交修改。该门在 builder 脚本层实现,不在 make 层。 ## 4. 脚本解析顺序 push 目标定位 builder 脚本时按以下顺序,命中即用,不做静默兜底: 1. `$BUILDER_SKILL_DIR/scripts/`(特殊安装位置) 2. `$HOME/.skills/skills/builder/scripts/`(标准 clone 位) 两个位置都不可用时必须失败并提示:设置 `BUILDER_SKILL_DIR`,或把 skills 仓库 clone 到 `~/.skills`。 ## 5. 校验 `python3 -I -S /check.py [--build]` 对本项目逐条检查 上述要求,任一 FAIL 退出码非零,可直接挂 CI。`--build` 额外实构 `make deb` 并核对 产物元数据(默认只静态检查配方)。校验失败时的修复路径:用 create-makefile skill 补齐或修正 Makefile,不要绕过校验器。 ## 6. 存量项目(legacy fallback) 未接入契约的项目:builder 仍可按发现流程工作——从 `Makefile`、CI 配置、`debian/` 与发布文档中找已有构建/上传入口,优先复用;上传仍使用 builder 脚本。完成一次成功 交付后应引导用户用 create-makefile 把项目迁移到本契约,之后以 check.py 为准。