mcpField
G
go-ci

go-ci

github.com/eduardo-sl云与 DevOps8398 次安装2 周前更新
代码仓库

关于 go-ci

go-ci 面向 Go 项目维护者,规划涵盖构建、vet 与 lint、竞态检测测试和漏洞扫描的 CI 流水线。内容还包括 GitHub Actions 配置、本地与 CI 检查对齐以及仓库安全实践。

主要功能

  1. 01CI 四项核心门禁
  2. 02GitHub Actions 工作流建议
  3. 03golangci-lint 配置
  4. 04竞态测试与覆盖率门禁
  5. 05安全扫描与依赖更新

适用场景

  1. 01搭建 Go CI 流水线
  2. 02使本地检查与 CI 保持一致
  3. 03添加竞态和覆盖率检查
  4. 04加固仓库自动化流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/eduardo-sl/go-agent-skills --skill go-ci

安装后在 Claude Code 中输入/go-ci确认已加载。

附带文件references/security-and-automation.md

详细介绍

Go CI

Go 流水线恰好有四道关卡:构建、vet/lint、运行竞态检测器的测试,以及漏洞扫描。其他一切都是优化。

详细参考资料按需加载:

  • references/security-and-automation.md — CodeQL 和 gosec SARIF、Dependabot 配置、SHA 固定、仓库加固、Trivy、AI 评审工作流。

只有在下方摘要不够时,才读取参考文件。

1. 基础 GitHub Actions 工作流

name: ci
on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-go@v7
        with:
          go-version-file: go.mod   # single source of truth
          cache: true               # caches module + build cache
      - run: go build ./...
      - run: go vet ./...
      - run: go test -race -shuffle=on -coverprofile=coverage.out ./...

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-go@v7
        with:
          go-version-file: go.mod
      - uses: golangci/golangci-lint-action@v9  # v7+ runs golangci-lint v2
        with:
          version: v2.6                         # pin a minor; v2.6+ has `modernize`

  vuln:
    runs-on: ubuntu-latest
    steps:
      - uses: golang/govulncheck-action@v1
        with:
          go-version-file: go.mod

Action 的主要版本每年会更新数次。请将上面的版本视为一个快照,并让 Dependabot 的 github-actions 生态系统保持其最新状态,而不要手动编辑。

其中的关键决策:

  • go-version-file: go.mod — 绝不要在两个地方硬编码 Go 版本。
  • 在 setup-go 中启用 cache: true 可处理模块和构建缓存;不要再为 Go 添加手动的 actions/cache 步骤。
  • -race -shuffle=on — 竞态和依赖顺序的测试应在 CI 中失败,而不是在生产环境中。
  • permissions: contents: read — 默认遵循最小权限原则。
  • 将 lint 放在单独的任务中 — 这样可以快速失败,并与测试并行运行。

2. golangci-lint 配置

提交 .golangci.yml;未配置的 linter 只会制造噪声:

version: "2"            # required: golangci-lint v2 rejects v1 files

linters:
  default: standard     # errcheck, govet, ineffassign, staticcheck, unused
  enable:
    - errorlint         # %w misuse, == on errors
    - gosec             # security patterns
    - revive            # style, replaces golint
    - misspell
  exclusions:
    rules:
      - path: _test\.go
        linters: [gosec]  # test code may use weak randomness etc.

golangci-lint v2 将排除项从 issues.exclude-rules 移到了 linters.exclusions.rules,并将 version 键设为必填。v1 文件会加载失败,而 golangci-lint migrate 可原地转换文件。

从这组精简配置开始,并有意识地添加 linter。启用所有检查会产生数百条无人处理的问题。nolint 指令必须说明原因://nolint:gosec // G404: jitter, not crypto。

3. 构建矩阵——仅在发布时使用

strategy:
  matrix:
    go: [oldstable, stable]      # the two releases the Go team supports
    os: [ubuntu-latest, macos-latest, windows-latest]

库:测试两个受支持的 Go 版本。setup-go 会在运行时解析 stable/oldstable,因此矩阵不会过时。 部署在 Linux 上的服务:跳过操作系统矩阵 — 为永远不会发布的平台测试会使成本翻倍。交叉编译比模拟更便宜: GOOS=windows go build ./... 可发现大多数可移植性问题。

4. 覆盖率关卡

- run: go test -race -coverprofile=coverage.out ./...
- name: enforce coverage floor
  run: |
    total=$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/,"",$3); print $3}')
    echo "coverage: ${total}%"
    awk -v t="$total" 'BEGIN { exit (t < 70.0) }'

设置一个逐步提高的最低门槛,而不是容易被钻空子的目标。通过 //go:generate 生成的文件的构建标签或 grep 过滤器排除生成代码,而不是降低门槛。

5. Makefile — CI 的本地镜像

CI 必须运行开发者本地运行的内容。一个定义,两个调用方:

.PHONY: build lint test vuln ci

build:
	go build ./...

lint:
	golangci-lint run

test:
	go test -race -shuffle=on -coverprofile=coverage.out ./...

vuln:
	go tool govulncheck ./...   # pinned via `go get -tool` (Go 1.24+)

ci: build lint test vuln

如果 CI 执行了 make ci 未执行的操作,开发者就只能在推送后才发现失败。两者应保持一致。

6. 加速规则

  • 将 lint/test/vuln 拆分为并行任务(如 §1 所示)。
  • go test ./... 已会在各软件包间并行运行;小型仓库不要拆分任务。
  • 带有构建标签的集成测试应放在单独的任务中,或按计划运行,而不是每次推送时运行:go test -tags=integration ./...。
  • 如果构建缓存总是未命中,请检查 go.sum 是否作为缓存键的输入(setup-go 会处理),并确认任务不会修改它。

7. 安全关卡

除 govulncheck 外,还应使用 CodeQL(security-extended)和 gosec,并将 SARIF 上传到 Security 标签页;对构建的任何容器镜像运行 Trivy。先以 -no-fail 运行 gosec 来收集基线,然后让新发现的问题导致 PR 失败。

8. 依赖更新与 Action 固定

  • 为 gomod 和 github-actions 启用 Dependabot,每周更新一次,并将次要版本和补丁更新合并到一个 PR 中。主要版本更新应单独处理 — 需要阅读变更日志。
  • 使用提交 SHA 固定第三方 Action,并在注释中注明版本;标签可能被改指向恶意代码,而 Dependabot 会更新 SHA 固定项。

9. 工作流与仓库加固

  • 在默认只读权限的基础上,按作业设置权限。
  • 不使用会检出并运行 fork 代码且提供密钥的 pull_request_target 工作流。
  • 分支保护:必需检查、代码审查、禁止强制推送。
  • 加载了 go-code-review 技能的 AI 审查者可作为额外审查者,但绝不能成为能够自行批准的检查项。

第 7–9 节的代码片段:references/security-and-automation.md。 由标签触发的发布流程——GoReleaser、签名、SBOM、来源证明——由 go-build-release 技能负责。

验证清单

  1. 流水线包含全部四个关卡:构建、vet+lint、test -race、govulncheck
  2. Go 版本从 go.mod 获取(go-version-file),而非重复声明
  3. 在工作流级别设置 permissions: contents: read
  4. 测试使用 -race -shuffle=on 运行
  5. 已提交包含精选 linter 集的 .golangci.yml
  6. 每个 nolint 都注明 linter 名称和原因
  7. 矩阵仅包含实际支持的版本和平台
  8. 强制执行覆盖率下限,并排除生成代码
  9. make ci 可在本地逐字节复现流水线
  10. 集成测试通过标签隔离,不拖慢每次推送
  11. CodeQL/gosec 结果以 SARIF 格式上传;镜像在推送前扫描
  12. Dependabot 覆盖模块和操作;第三方操作按 SHA 固定
  13. 按作业设置权限;不使用密钥运行 fork 代码

评论

支持 Markdown