GitHub Actions Go/Rust CI:交叉编译、静态检查与发布

GitHub Actions Go/Rust CI 实战:Go Modules 缓存与矩阵构建(1.19/1.20/1.21/1.22)、Rust Cargo 缓存与 clippy/fmt 检查、交叉编译(Go GOOS/GOARCH、Rust cross/cargo-cross)、静态链接与 musl 目标、测试覆盖率(Go cover/Rust tarpaulin/codecov)、Bench 性能基准(Go bench/Rust criterion)、安全扫描(Go nancy/Rust cargo-audit)、Release 自动化(GoReleaser/cargo-release)、多平台 Artifact 发布

Go 和 Rust 作为编译型语言,CI 流程与解释型语言差异显著:编译速度、交叉编译能力、静态链接、二进制分发。Go 的工具链简洁高效,Rust 的类型系统和 borrow checker 在编译期捕获大量错误。本文覆盖 Go/Rust 的 GitHub Actions CI 最佳实践——从缓存策略到交叉编译,从安全扫描到多平台发布。


一、Go CI 流水线

1.1 基础工作流

# .github/workflows/go.yml
name: Go CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        go: ['1.19', '1.20', '1.21', '1.22']

    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go }}

      - name: Cache Go modules
        uses: actions/cache@v3
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-

      - name: Download dependencies
        run: go mod download

      - name: Run tests
        run: go test -v -race -coverprofile=coverage.out ./...

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage.out

1.2 关键要点

actions/setup-go@v5 自动处理 GOMODCACHE 缓存
-race 标志:启用数据竞争检测(Go 并发必备)
-coverprofile:生成覆盖率文件
# Go 的测试文化是「内置的」——go test 是标准工具链的一部分

二、Rust CI 流水线

2.1 基础工作流

# .github/workflows/rust.yml
name: Rust CI

on: [push, pull_request]

env:
  CARGO_TERM_COLOR: always

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        rust: [stable, beta, nightly]

    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-action@stable
        with:
          toolchain: ${{ matrix.rust }}

      - name: Cache Cargo
        uses: actions/cache@v3
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Check formatting
        run: cargo fmt -- --check

      - name: Run clippy
        run: cargo clippy -- -D warnings

      - name: Run tests
        run: cargo test --verbose

      - name: Generate coverage
        run: cargo tarpaulin --verbose --out Xml

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./cobertura.xml

2.2 Rust 工具链

rustfmt:代码格式化(类似 Black/Prettier)
clippy:Lint 工具(比编译器更严格的检查)
cargo-check:快速编译检查(不生成二进制)
cargo-tarpaulin:覆盖率工具
# Rust 的「编译即检查」哲学使大量问题在编译期消除

三、交叉编译

3.1 Go 交叉编译

      - name: Cross compile
        run: |
          GOOS=linux   GOARCH=amd64 go build -o bin/app-linux-amd64
          GOOS=linux   GOARCH=arm64 go build -o bin/app-linux-arm64
          GOOS=darwin  GOARCH=amd64 go build -o bin/app-darwin-amd64
          GOOS=darwin  GOARCH=arm64 go build -o bin/app-darwin-arm64
          GOOS=windows GOARCH=amd64 go build -o bin/app-windows-amd64.exe

3.2 Rust 交叉编译

      - name: Install cross
        run: cargo install cross --git https://github.com/cross-rs/cross

      - name: Build for Linux ARM64
        run: cross build --target aarch64-unknown-linux-gnu --release

      - name: Build for Linux x86_64
        run: cross build --target x86_64-unknown-linux-musl --release

3.3 musl 静态链接

Go:默认静态链接(CGO_ENABLED=0)
Rust:musl 目标实现真正静态链接(不依赖 glibc)
# 静态链接的优势:
#   - Alpine 镜像运行(无 glibc)
#   - 跨 Linux 发行版兼容
#   - 更小的攻击面

四、性能基准测试

4.1 Go Benchmark

      - name: Run benchmarks
        run: go test -bench=. -benchmem ./... | tee benchmark.txt

      - name: Store benchmark result
        uses: benchmark-action/github-action-benchmark@v1
        with:
          tool: 'go'
          output-file-path: benchmark.txt
          github-token: ${{ secrets.GITHUB_TOKEN }}
          auto-push: true

4.2 Rust Criterion

      - name: Run Criterion benchmarks
        run: cargo bench

      - name: Upload benchmark results
        uses: actions/upload-artifact@v3
        with:
          name: benchmark-results
          path: target/criterion/

五、安全扫描

5.1 Go 安全扫描

      - name: Run Nancy
        uses: sonatype-nexus-community/nancy-github-action@main
        with:
          goListFile: go.list

      - name: Run gosec
        uses: securego/gosec@master
        with:
          args: '-fmt sarif -out results.sarif ./...'

5.2 Rust 安全扫描

      - name: Run cargo-audit
        uses: actions-rs/audit-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Run cargo-deny
        uses: EmbarkStudios/cargo-deny-action@v1

六、Release 自动化

6.1 GoReleaser

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v5
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# .goreleaser.yml
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
    goarch:
      - amd64
      - arm64
archives:
  - format: tar.gz
    name_template: >-
      {{ .ProjectName }}_
      {{- title .Os }}_
      {{- if eq .Arch "amd64" }}x86_64
      {{- else if eq .Arch "386" }}i386
      {{- else }}{{ .Arch }}{{ end }}
checksum:
  name_template: 'checksums.txt'
snapshot:
  name_template: "{{ incpatch .Version }}-next"
changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'

6.2 Rust cargo-release

      - name: Publish to crates.io
        run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}

七、多平台 Artifact 发布

7.1 矩阵构建多平台

    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: macos-latest
            target: aarch64-apple-darwin
          - os: windows-latest
            target: x86_64-pc-windows-msvc

    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: cargo build --release --target ${{ matrix.target }}

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: binary-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/myapp*

总结

Go 和 Rust 的 CI 都受益于「编译即检查」的哲学——大量问题在编译期消除。Go 的 CI 重点是:go test -race 检测数据竞争、交叉编译简便(GOOS/GOARCH)、GoReleaser 一键多平台发布。Rust 的 CI 重点是:cargo fmt/clippy 保持代码质量、tarpaulin 生成覆盖率、cargo-audit 扫描依赖漏洞、cross 工具链处理交叉编译。两者的缓存都关键——Go 的 ~/go/pkg/mod 和 Rust 的 ~/.cargo + target/ 目录缓存能显著加速 CI。静态链接(Go 默认/Rust musl)让二进制分发变得简单,一个文件即可跨发行版运行。

延伸阅读:

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「github-actions」更多文章

  1. GitHub Actions Java/JVM CI:Maven、Gradle、JaCoCo 与 Jib 容器化
  2. GitHub Actions PR 自动化:标签、审查、合并与发布
  3. GitHub Actions 定时任务:自动化备份、清理与报表