CI:移除本仓非主分支构建能力 —— 分支 push 会推 runtime-base:latest 并污染正式镜像(主 issue xm/yuvu#10) #1
Labels
No labels
P0
P1
P2
P3
blocked
fixed-pending-verify
manual-fallowup
manual-followup
needs-fix
rewrite
verified
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
zx/matchsubtitles#1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
关联
主 issue:xm/yuvu#10(P1)——本 issue 是该根因在本仓的落地项,优先级降为 P2,是否可关闭以主 issue 的验收口径为准。
现象
.woodpecker.yml根when:是裸 trigger(不含branch:):发布逻辑内联在 yml 里,无任何分支判定,且两个镜像都打
:latest:注意第二个构建把
runtime-base:$${TAG}作为 build-arg 输入 → 非主分支 push 时,被同时污染的 base 会被当次正式镜像构建直接消费。实测证据
本仓共 7 条流水线(Woodpecker repo id=8),全部是
main:即非主分支构建 0 条 —— 属潜伏缺陷(能力已具备,尚未被触发)。对照
yuvuNode今天已经真实发生三次(见 xm/yuvu#10)。本仓实例部署在节点5b(受管适配器matchsubtitles-5b)。推测根因
Woodpecker
3.18.1的流水线配置是从被推送的那个 ref 上读取的(本仓 repo 设置config_file为空 → 走默认路径.woodpecker/*.{yaml,yml}/.woodpecker.yaml/.woodpecker.yml);服务器侧 repo 对象没有分支白名单字段(仅pr_enabled / allow_pr / allow_deploy / require_approval / timeout / config_file)。因此when:未声明branch时,push 事件对任意分支成立;发布侧又没有分支判定。期望(完成定义)
发布侧二选一:
when: { branch: main }(照yuvuAdapter)should_publish_latest判定,只在 main 上附加:latest(照yuvuCore/scripts/ci/publish_image.sh)最小复现
fix/ci-scope-probe);matchsubtitles:latest与runtime-base:latest的 digest 是否变化。(期望:无流水线;或发布步骤
skipped且 digest 不变。)验收
见 xm/yuvu#10「验收口径」1–4。
本轮复核(2026-10-01)
main 的
.woodpecker.yml仍是裸- event: [push, manual](发布脚本无 branch 守卫),自 3~7 月起无修改 ⇒ 未修。对照:
yuvuCore、yuvuAdapter两仓已完成同样收口。修复归属本仓 coding agent。总控复验并合入(2026-10-01 21:2x CST)
分支
fix/ms-1-ci-publish-scope(worktreewt/wms-01,4 提交,tip588c9a7)→ 已--no-ff合入 main1761e69并 push。改动(仅 3 文件;未动 Dockerfile 构建内容与缓存参数、未部署、未推删任何 tag):
.woodpecker.yml:顶层when收窄为push: branch=main+manual(任意 ref,保留分支真机构建);docker-publish里runtime-base与matchsubtitles的-t …:latest改为由scripts/ci/publish_scope.sh --tag-args <repo>产出;新增test步骤真跑测试脚本。scripts/ci/publish_scope.sh(纯函数should_publish_latest/publish_latest_decision/latest_tag_args+ CLI 入口;缺省/不可判定一律 fail-closed 判 no)。scripts/ci/test_publish_scope.sh。门禁(原始输出):分支与合并后 main 各跑一次,均为
真跑判定(两例 + CLI):
反向验证(变异必红 -> 还原逐字节一致 -> 复绿)
should_publish_latest直接return 0):test_publish_scope.shrc=1,FAIL: should_publish_latest('refs/heads/fix/ms-1-ci-publish-scope')=yes want no;真跑分支 ref 得到yes(错)。latest_tag_args无条件输出:latest:rc=1,FAIL: latest_tag_args(...,'refs/heads/fix/ms-1-ci-publish-scope')='-t ...:latest' want ''。sha256sum scripts/ci/publish_scope.sh = cf5c317e20d04e66784dd4e9342c4223fec6d44fa47dae6efccb51f88fc403ee(与变异前逐位相同),测试复绿 rc=0。未通过项(如实标注):
go build ./.../go test ./...本机无法全绿,但与本轮改动无关且 main 同样失败——仓内无vendor/而环境默认GOFLAGS=-mod=vendor;改-mod=mod后internal/httpapi与cmd/matchsubtitles因缺github.com/go-chi/chi/v5@v5.2.5、github.com/danielgtaylor/huma/v2@v2.37.2且GOPROXY=off而[setup failed](在 mainb9f0141复现同样两条 FAIL)。本轮改动不含任何 Go 代码。请验证这几点
matchsubtitles:latest与matchsubtitles/runtime-base:latest的 digest 不变;:latest,且 CI 日志中test步骤可见publish scope checks passed;<UTC 日>-<commit7>标签、不带动:latest。issue 保持 open,由归属方/真机验收会话关闭。
补充验证通过:CI 发布面收口已合入 main(
245d2e6)245d2e6(--no-ff合并fix/ms-1-ci-publish-scope;含新提交29e86cc「test: 覆盖 publish_scope --tag-args 的 CI_COMMIT_REF 缺省路径」= 29 行新增测试),已 push 到zx/matchsubtitlesmain。此前1761e69的收口改动(顶层- event: [push, manual]已移除、docker-publish 走publish_latest_decision、base image 不再无条件推 latest)保持不变。env -u GOFLAGS go build ./...→ build OK;go test ./...→ 全 ok;bash scripts/ci/test_publish_scope.sh→publish scope checks passed(rc=0)。latest_tag_args的ref="${2-${CI_COMMIT_REF:-}}"改成ref="${2:-}"→FAIL: latest_tag_args with CI_COMMIT_REF=main must emit :latest,rc=1;② 把 CLI 分支--tag-args的同一缺省去掉 →FAIL: publish_scope.sh --tag-args ... (CI_COMMIT_REF='refs/heads/main') => '' want '-t ...:latest',rc=1。两次还原后sha256=cf5c317e20d04e66784dd4e9342c4223fec6d44fa47dae6efccb51f88fc403ee与git show HEAD:scripts/ci/publish_scope.sh逐位一致、git status干净、复绿 rc=0 ⇒ 新测试确实承重。matchsubtitles:latest与共享 base 镜像 tag 未被改写(可对比 push 前后 registry digest);② main 分支 push 仍能正常产出:latest;③ Woodpecker 本仓流水线docker-publish步骤:main 带-t ...:latest,非 main 不带(这正是publish_latest_decision的判定口径:main→yes、非 main→no、空 ref→no)。