使用GitHub Actions为Go项目实现高级CI/CD
构建、测试和部署的自动化是现代Go开发的基石。基础流水线适合起步,但当项目规模增长时,需要高级技术:依赖缓存、并行任务、针对不同操作系统和架构的矩阵构建、将工件发布到Docker Hub以及智能部署。本文将讲解如何以专业级别配置Go项目的GitHub Actions。
1. 缓存Go模块和二进制文件
每次运行流水线都可能下载数十兆字节的依赖。为了加速这一过程,我们使用GitHub Actions内置的缓存功能来缓存go mod和构建缓存。
name: Go CI (高级)on: [push, pull_request]
jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: 安装Go uses: actions/setup-go@v5 with: go-version: '1.22'
- name: 缓存Go模块 uses: actions/cache@v4 with: path: | ~/go/pkg/mod ~/.cache/go-build key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go-
- name: 下载依赖 run: go mod download
- name: 代码检查 (golangci-lint) uses: golangci/golangci-lint-action@v6 with: version: latest
- name: 带覆盖率的测试 run: go test -v -race -coverprofile=coverage.out ./...
- name: 构建二进制文件 run: go build -o myapp ./cmd/app键hashFiles('**/go.sum')仅在依赖发生变化时使缓存失效。构建缓存(~/.cache/go-build)保存已编译的对象,加速重新构建。
2. 矩阵构建:针对不同Go版本和操作系统进行测试
Go项目通常需要在Linux、macOS和Windows上运行,并支持多个语言版本。矩阵策略允许为每种组合并行运行任务。
jobs: matrix-test: strategy: matrix: go-version: ['1.21', '1.22', '1.23'] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: 安装Go ${{ matrix.go-version }} uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - name: 测试 run: go test ./...这种方法能发现不同平台上的兼容性问题。对于Windows,可能需要额外配置路径和换行符。添加fail-fast: false,以便即使某个任务失败,其他任务也能继续运行。
3. 发布Docker镜像和GitHub Release
测试成功后,自然要发布工件:将Docker镜像发布到Docker Hub(或GitHub Container Registry),将二进制文件发布到GitHub Release。下面介绍这两种场景。
发布Docker镜像
创建一个仅在测试之后运行,且仅在推送到main或创建标签时运行的任务。
jobs: docker: needs: [build-and-test] if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: 登录Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: 构建并推送镜像 uses: docker/build-push-action@v5 with: context: . push: true tags: | ${{ secrets.DOCKER_USERNAME }}/myapp:latest ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}不要