用途
该技能面向 Go 项目的搭建与持续集成配置,目标是让 CI 门禁真正起到验证作用,而不是“绿色但无意义”。它总结了一系列来自真实 CI 失败或误报的规则,帮助开发者避免模块路径错误、工具链版本漂移、linter 配置不匹配、测试空转、输出不确定、dry-run 失真、UTF-8 截断损坏、数值异常以及外部命令与 HTTP 调用脆弱等问题。
主要能力
- 模块路径正确性:要求 go.mod 的 module 行与所有内部导入使用用户实际执行 go install/go get 的规范仓库 URL。仓库改名或所有者变更时,需同步重命名所有内部导入引用。
- 工具链版本固定:指出 GOTOOLCHAIN=auto 会让 CI 矩阵失效,因为 Go 会静默下载并使用 go.mod 中 go 指令指定的版本。要求 go 指令、setup-go 版本和 CI 矩阵保持一致。
- gofmt 版本一致性:gofmt 运行在 setup-go 安装的 SDK 版本下,而非运行时工具链。升级 setup-go 可能改变 gofmt 输出,导致未改代码的 PR 格式检查失败。建议在本地使用与 CI 相同的版本运行 gofmt,并固定 setup-go 版本。
- golangci-lint 配置匹配:.golangci.yml 的 version 键必须与安装的 golangci-lint 主版本匹配。v1 无顶层 version 键,使用 disable-all/exclude-use-default;v2 使用 version: "2"、linters.default: none 和 enable 列表。v2 移除了 --timeout CLI 标志,超时应设置在 run.timeout。
- linter 版本固定与问题上限:action 的 version: latest 只跟踪该 action 支持的主版本的最新发布,可能静默安装已停止维护的 linter。建议固定显式版本,并提交明确启用 linter 的配置文件。golangci-lint 默认最多报告 3 个相同问题,需运行 errcheck ./... 或临时设置 issues.max-same-issues: 0 来清除全部问题。
- 测试任务有效性:go test -race ./... 在零个 *_test.go 文件时退出码为 0,导致竞态检测 CI 任务形同虚设。建议先为纯函数添加真实测试,确保测试任务实际执行断言。
- 确定性输出:遍历 Go map 的键顺序是随机的,直接用于构建切片、JSON 文件或任何提交/比较的产物会导致每次运行字节顺序不同。应先排序再输出。
- dry-run 状态模拟:dry-run 应抑制外部写入,而非跳过用于决策的内存状态变更。将准备性状态转换放在 !dryRun 条件下会导致预览基于过期状态计算,低估真实操作。应拆分模拟与副作用,两种模式应用相同的内存转换,仅对持久化或破坏性外部操作加门禁。
- UTF-8 边界截断:Go 字符串索引和切片基于字节,body[:500] 可能切断多字节码点,产生无效 UTF-8。若限制是字节预算,应回退到前一个 rune 边界;若需求是字符限制,则按 rune 截断。建议为所有构造同类上下文的路径使用一个共享限制器。
- 数值输入校验:strconv.ParseFloat 会接受 "NaN"、"inf"、"-Infinity" 并返回 nil 错误。有限输入在算术中也可能溢出为 Inf。这些值无法通过 encoding/json 编码。应在解析值和计算结果两端校验,返回错误而非非有限数。NaN != NaN,switch 无法捕获 NaN,需在 switch 或提前返回前用 math.IsNaN 防护。
- 变异测试注意事项:在 Go 中变异守卫可能破坏构建而非导致测试失败。例如将 if math.IsNaN(x) { … } 改为 if false { … } 可能导致 math 导入未使用,go test 报告 imported and not used 而无测试失败。应保持标识符被引用,并检查输出是否包含 FAIL 行。
- 可注入的 git/gh 运行器:通过 exec 调用 git/gh 并用 strings.Contains(stderr, "404") 分类失败的方式脆弱且难以测试。应定义小型 Runner 接口,依赖接口而非 os/exec,优先使用结构化输出(gh api、--json)。
- 出站 HTTP 超时与 User-Agent:默认 http.Get 无超时且无 User-Agent。应使用显式客户端设置 Timeout 和 User-Agent。当解析器匹配显示文本时,应固定 Accept-Language。建议将客户端保存在包级变量中,便于测试替换 transport。
使用方式
该技能以规则和检查清单形式提供,可直接应用于 Go 项目的 CI 配置和代码审查。文末提供了一份 Go 项目健康检查清单,涵盖模块路径、工具链一致性、gofmt 版本、golangci-lint 配置与版本、测试有效性、map 排序、dry-run 状态转换、UTF-8 截断、git/gh 运行器注入以及 HTTP 超时与 User-Agent 等检查项。
适用场景
适用于需要搭建或维护 Go 项目 CI 流水线的开发者,尤其是希望确保 CI 门禁真实有效、避免绿色但无意义的检查、处理多版本工具链矩阵、配置 golangci-lint、编写可测试的外部命令封装以及健壮的 HTTP 客户端的场景。
限制
该技能为规则与最佳实践集合,不提供自动化脚本或工具。具体项目需根据自身 CI 环境调整版本号和配置。部分规则(如 Accept-Language 固定)只能缩小风险,不能完全消除基于正则或标记的抓取脆弱性。