76611a2f65039c6da174e89ae35df07100f7a804(base,即 v1.0.106 的提交)→ abe48b17b7acb5b7030bb21607ef4ca46a2a80f8(head)| 维度 | 结论 |
|---|---|
| 变更性质 | 纯 CI/CD 形态重构 + 文档,无 Go / JS 应用源码改动 |
| 采集器运行时行为 | 不变(无源码改动,镜像内业务逻辑逐字一致) |
| 新增/修复质量问题 | 0 / 0(issues_diff 实测,见 §4) |
| 发布路径 | CI 由「build-check → docker → deploy 三 job」改为「build-push(质量门→宿主编译→buildx 推送)→ deploy」两 job |
| Dockerfile | 删除 builder 段,改为只 COPY 宿主编译产物;版本注入由 --build-arg 改为 go build -ldflags -X main.Build* |
| ⚠️ 核心判断 | 本次改版未解除 tag 触发路的失败根因(AGENTS 自述「CI 那 3 个 Linux 失败未修」),新流水线仍大概率在「脚本语法」步失败→ 新增的宿主编译 / buildx / 部署步骤在真实 CI 中尚未被跑通过 |
一句话:这是一次「把编译从容器搬到宿主机、镜像只打包」的工程化重构,方向合理;但它没有修掉让 tag 路由一直断掉的那个测试失败,所以「打 tag 自动部署」这条路本次改版后大概率仍然不通。
| 文件 | 类型 | 摘要 |
|---|---|---|
.gitea/workflows/build.yml | CI/CD | 三 job 合并为两 job;go vet/go build 位置重排;actions 改为自建镜像全 URL;go-version-file: go.mod;新增宿主编译 + buildx 本地缓存 + push 重试;deploy 合并为单步并加 90s 轮询 |
Dockerfile | 构建 | 删除 golang:1.25-alpine builder 阶段与 ARG BUILD_VERSION/BUILD_TIME/GIT_COMMIT;COPY --from=builder 改为 COPY 宿主机产物 |
AGENTS.md | 文档 | 追加 2026-09-29「v1.0.106 已上线」条目 |
docs/变更审计日志-2026-09.md | 文档 | 追加 A-34 记录(v1.0.106 发版路径与证据) |
.dockerignore未改动(本次核对:其排除项为build/ bin/ tmp/ tests/ coverage/ scripts/ *.md LICENSE .env*等,不含server/importharvest/coalbackfill/metricimport/healthcheck,故 Dockerfile 的新COPY不会被忽略)。
.gitea/workflows/build.yml结构变化(job 层面)
| 改前 | 改后 |
|---|---|
build-check:checkout → setup-go(1.25) → GOPROXY → go mod download → gofmt → go vet → 脚本语法 → go test -race + go build ./... | build-push:checkout → setup-go(go-version-file: go.mod) → GOPROXY → gofmt → 脚本语法 → Quality gate (vet + test) → Build release binaries (host) → buildx 缓存 + Build & Push |
docker(needs: [build-check]):docker build --build-arg … → tag → push | 已合并进 build-push |
deploy(needs: [docker]):两步(升级 / 轮询校验)+ 一步(探活) | deploy(needs: [build-push]):升级+90s 轮询合为一步 + 一步(探活) |
合理之处(正向)
exit $RC,不会假绿(RC=${PIPESTATUS[0]} 明确取 docker 退出码)。concurrency 组保留(防短时间连打两个 tag 产生并发 deploy)。实现细节核对
go-version-file: go.mod:go.mod:3 为 go 1.25.0,与原 go-version: '1.25' 等价 ✅go build -ldflags "-X main.BuildVersion=… -X main.BuildTime=… -X main.GitCommit=…" -o server . → 目标符号确实存在于 main.go:44-48(BuildVersion/BuildTime/GitCommit)→ 通过 buildinfo.Set 暴露到 /api/v1/health 的 data.version(见 §6)✅data.get('version'),与端点字段名 version 匹配 ✅潜在问题
Dockerfilebuilder 阶段(golang:1.25-alpine + go mod download + 5 个 go build)与 ARG BUILD_VERSION/BUILD_TIME/GIT_COMMIT。COPY --from=builder /out/xxx 改为 COPY xxx …(二进制来自仓库根,由 CI 宿主编译产出)。docker build .(未先宿主编译)会因缺 server 等文件而 COPY 失败。这是有意为之,但改变了既有构建契约(见 R-2)。mcr.microsoft.com/playwright:v1.62.1-noble(需浏览器运行时,保留合理)。AGENTS.md / docs/变更审计日志-2026-09.md)W4 新品种[…](未改,登记为下次随版修);docker build --build-arg BUILD_VERSION=…,与新 Dockerfile(已无 ARG)不兼容(见 R-2)。codescan.issues_diff(base=76611a2…, head=abe48b17…) 结果:
修复 0 条 / 新增 0 条(两版本质量无差异)
原因:本次改动不涉及任何 Go / JS 源码文件(仅 .yml / Dockerfile / .md),故质量地图无变化。
存量背景(仅供参考,非本次引入):quality_list 当前共 777 条,样本全部落在 Node 侧(browserworker/*.mjs),典型为「高耦合」「圈复杂度过高」「异步函数中的同步阻塞调用」「行过长」等 Maintainability/Dependency/Concurrency 类;与本次 CI/Dockerfile 改动无关联,不计入本次增量。
AGENTS.md(本次新增条目)记 CI 运行 1351 在 「脚本语法(bash -n / node --check)」步失败,Docker Build & Push 与 Deploy 均 skipped;对照 v1.0.100 运行 1184 失败在同一步;并自述「CI 那 3 个 Linux 失败未修」——即 credentials.test.mjs 1 失败 / ui-harvest.test.mjs ERR_MODULE_NOT_FOUND / trusted-browser.test.sh 3 失败。build.yml 中该步原样保留且 set -e,会无条件执行上述三个脚本;runner 为 Linux(cxy-ubuntu)⇒ 同一步仍会失败,build-push 在到达宿主编译/buildx 之前即中断,deploy 继续被 skip。continue-on-error 并显式告警),否则打 v1.0.107 的 tag 仍不会触发有效部署。builder 段、无 ARG,需先宿主编译出 5 个二进制再 docker build .,否则 COPY server … 直接失败。AGENTS.md / A-34 记录的实际在用的手动构建仍是 docker build --build-arg BUILD_VERSION=…——该命令对新 Dockerfile 既不能注入版本(无 ARG),也会因缺二进制而失败。docker build .,版本由 -ldflags -X 注入」,并说明 tag 路与手动路的一致性。docker buildx build --progress=plain --cache-from … --cache-to … -t "$IMAGE:$TAG" . 未加 --load。
docker-container 驱动,构建结果不会进入本地 docker images,随后 docker tag/docker push 会因「No such image」失败(好消息:会显式非零退出,不会假绿)。--cache-to/from type=local 对 docker 驱动的支持有限,缓存可能不生效。docker buildx ls 默认驱动;必要时显式 --load(或 --push)。build.yml 探活步:if tag and ver and tag not in str(ver): 失败。当端点未返回 version(ver 为空)时判定通过 ⇒ 可能出现「容器可访问但版本未知」被算作成功。ver 为空时至少打 ::warning:: 或判失败。run: | 块内 python 必须单行(多行缩进导致 Gitea YAML 解析失败,tag 不触发)」;但「探活并校验版本」步仍保留多行 python,规则与实现不一致。hashFiles('Dockerfile', 'go.sum'),但影响镜像层的实际输入是宿主编译产物(其内容随源码变化),且 go.mod 未纳入 key。仅影响缓存命中效率,不影响正确性。go build ./... 后的编译覆盖go build ./...。由于 go vet ./... + go test -race ./... 会类型检查/编译全部包与测试包,普通编译错误仍能覆盖;仅带 build tag、既不参与 vet 也不参与 test 的包可能漏检。| 契约 | 证据 |
|---|---|
| 版本注入目标符号存在 | main.go:44-48 var ( BuildVersion="dev"; BuildTime="unknown"; GitCommit="unknown" ) |
| 版本传递到健康接口 | main.go:51 buildinfo.Set(...) → internal/buildinfo/buildinfo.go:53-61 输出键 version/commit/build_time → internal/api/handlers.go:341+ 合并进 /api/v1/health 的 data |
go 版本号与 go-version-file 一致 | go.mod:1 module price-collector,go.mod:3 go 1.25.0 |
| 探活脚本字段名匹配 | 脚本读 data.get('version'),端点实为 data.version |
Dockerfile 新 COPY 不被忽略 | .dockerignore 排除项不含 server/importharvest/coalbackfill/metricimport/healthcheck |
Dockerfile 与 CI 的工程化方向(宿主编译 + 镜像只打包、缓存、push 重试、部署轮询)合理。.gitea/workflows/build.yml 里那个会在 Linux 上失败的「脚本语法」步原样保留。因此「打 tag → 自动部署」这条路本次之后大概率仍不通,新引入的宿主编译/buildx/deploy 轮询步骤在真实 CI 中尚未被验证。建议把修 3 个 Linux 测试失败列为下一批第一优先(或临时非阻断),否则本次重构的收益无法兑现。--load(R-3)。