Keep ~/.skills as a lookup fallback so existing checkouts still resolve version.sh.
6.7 KiB
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)/<name>_<version>_<arch>.deb;只构建不上传 |
docker |
有镜像的项目 | 构建本地单平台镜像 linux/$(ARCH);禁止 --push、禁止多平台 |
push-deb |
同时有 DEB 和镜像的项目 | 仅调 builder 的 upload_deb.sh 上传 dist/*.deb |
push-docker |
同时有 DEB 和镜像的项目 | 仅调 builder 的 publish_docker.sh |
push |
单一产物类型时必备;双产物项目为聚合 | 依序调用对应 push-* 或直接调脚本;是发布的唯一 make 入口 |
规则:
- 项目有 DEB 产物的判据:Makefile 配方引用
dpkg-deb/debuild或产出.deb。 有镜像的判据:项目根存在Dockerfile。 - 双产物项目必须拆
push-deb/push-docker,push依序聚合两者;单产物项目一个push即可。 docker目标只能本地构建。多平台镜像无法拆成"make 构建 + 单独推送" (buildx --push是一步),因此多平台发布只能走publish_docker.sh。- push 类目标必须是薄包装:解析脚本路径后委托,不内联 curl/token/端点。
2. 变量
| 变量 | 默认 | 说明 |
|---|---|---|
ARCH |
amd64 |
仅允许 amd64 | arm64,非法值必须 $(error) 报错并提示合法值 |
VERSION |
`` (空) | 为空时按「版本号」节从 Git 祖先稳定 tag 推导;禁止 sort -V 取全局最新 |
DIST_DIR |
dist |
DEB 产物目录 |
PROJECT_NAME |
git 仓库名 | 包名/镜像名主体 |
版本号
make version 输出一行规范版本(无 v 前缀)。DEB 的 Version 与文件名
直接用它;Docker tag 由它渲染。推导入口是 scripts/version.sh(make 通过
scripts/version.mk 引用);Builder 只读取 Git 状态,不调用
manage-release,不猜测下一个正式 SemVer。正式 tag 由 manage-release 事先打好。
version.sh 不执行 git fetch。
推导前 git fetch --tags(本地 linked worktree 共享 tags,不必再 fetch 才
能看见其它 worktree 新打的 tag)。基线是 HEAD 祖先上最近的稳定 tag,
不是全仓库 sort -V 的最大号。稳定 tag 仅 v<major>.<minor>.<patch>。
| 判定 | 规范版本 | DEB 文件 | Docker tag |
|---|---|---|---|
HEAD exact-match 稳定 tag v1.4.2 |
1.4.2 |
name_1.4.2_<arch>.deb |
1.4.2 |
其它 commit;祖先最近稳定 tag v1.4.2 |
1.4.2~<branch>.<n>+g<sha> |
name_1.4.2~<branch>.<n>+g<sha>_<arch>.deb |
1.4.2-<branch>.<n>.g<sha> |
| 祖先中没有稳定 tag | 0.0.0~<branch>+g<sha> |
同上替换规范版本 | 同上映射 |
测试与正式进入同一 apt / Docker 仓库。测试 DEB 必须用 ~,使
1.4.2~… < 1.4.2,apt upgrade 不会装上测试包。Docker tag 不得含
~、/、:,由规范版本把 ~ → -、+g → .g。
<branch>:git rev-parse --abbrev-ref HEAD,detached 时用
BUILD_BRANCH / CI_COMMIT_BRANCH / GITHUB_REF_NAME,再没有则
detached。清洗:小写;/、_ → -;去掉非 [a-z0-9-];压缩连续
-;过长截断(给 base、距离、SHA 留位置;Docker tag 上限 128)。
<n> 为基线 tag 到 HEAD 的 commit 数;<sha> 为 7 位短哈希。不要把
--dirty 写入版本;脏树发布仍走既有门禁。显式 VERSION= / IMAGE_TAG=
可覆盖推导,但不得把非 exact-match 的 commit 标成正式 X.Y.Z。
项目 Makefile 不要内联 git describe 或 sort -V,include 本 skill 的
scripts/version.mk:
include $(HOME)/.pouch/skills/builder/scripts/version.mk
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 |
否 | 默认由规范版本渲染:正式为 X.Y.Z;测试将 ~ 换成 -、+g 换成 .g |
PLATFORMS |
否 | 默认 linux/amd64;多平台如 linux/amd64,linux/arm64 |
配置来源优先级:shell 已显式设置的值 > 项目根 .env > 失败并询问用户。
.env 由 builder 脚本自动向上查找并加载(不回显任何值);当前 shell 已设置的值
优先于 .env。
工作区安全
脏工作树(有未提交修改)默认拒绝发布;ALLOW_UNCOMMITTED=1 显式放行并在汇报中
注明镜像/包包含哪些未提交修改。该门在 builder 脚本层实现,不在 make 层。
4. 脚本解析顺序
push 目标与 version.sh 定位 builder 脚本时按以下顺序,命中即用,不做静默兜底:
$BUILDER_SKILL_DIR/scripts/(特殊安装位置)$HOME/.pouch/skills/builder/scripts/(标准 clone 位)
两个位置都不可用时必须失败并提示:设置 BUILDER_SKILL_DIR,或把 pouch 仓库
clone 到 ~/.pouch。
5. 校验
python3 -I -S <builder-scripts>/check.py <project-dir> [--build] 对本项目逐条检查
上述要求,任一 FAIL 退出码非零,可直接挂 CI。--build 额外实构 make deb 并核对
产物元数据(默认只静态检查配方)。校验失败时的修复路径:用 create-makefile skill
补齐或修正 Makefile,不要绕过校验器。
6. 存量项目(legacy fallback)
未接入契约的项目:builder 仍可按发现流程工作——从 Makefile、CI 配置、debian/
与发布文档中找已有构建/上传入口,优先复用;上传仍使用 builder 脚本。完成一次成功
交付后应引导用户用 create-makefile 把项目迁移到本契约,之后以 check.py 为准。