CI/CD 与 GitHub Actions
完整的 C++ CI/CD 流水线:多平台构建、静态分析、Sanitizers 测试、性能基准、Docker 发布,一次提交全自动验证。
完整 CI 配置
yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/.vcpkg-cache
jobs:
# ===== 多平台构建 =====
build:
name: Build (${{ matrix.os }}, ${{ matrix.compiler }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
compiler: gcc-12
cc: gcc-12
cxx: g++-12
- os: ubuntu-22.04
compiler: clang-16
cc: clang-16
cxx: clang++-16
- os: windows-2022
compiler: msvc
- os: macos-13
compiler: clang
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: 缓存 vcpkg
uses: actions/cache@v4
with:
path: |
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
${{ env.VCPKG_ROOT }}
key: vcpkg-${{ matrix.os }}-${{ hashFiles('vcpkg.json') }}
- name: 安装 vcpkg
run: |
git clone https://github.com/microsoft/vcpkg.git $VCPKG_ROOT
$VCPKG_ROOT/bootstrap-vcpkg.sh -disableMetrics
if: runner.os != 'Windows'
- name: 配置(Linux/macOS)
if: runner.os != 'Windows'
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_BUILD_TYPE=Release \
-G Ninja
- name: 构建
run: cmake --build build --parallel
- name: 测试
run: ctest --test-dir build --output-on-failure --parallel 4
# ===== Sanitizers =====
sanitizers:
name: Sanitizers
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: 安装工具
run: sudo apt-get install -y cmake ninja-build clang-16
- name: 构建(ASan + UBSan)
env:
CC: clang-16
CXX: clang++-16
run: |
cmake -B build-asan \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -g" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" \
-G Ninja
cmake --build build-asan
- name: 运行测试(ASan)
env:
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1
run: ctest --test-dir build-asan --output-on-failure
- name: 构建(TSan)
env:
CC: clang-16
CXX: clang++-16
run: |
cmake -B build-tsan \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=thread -g" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread" \
-G Ninja
cmake --build build-tsan
- name: 运行测试(TSan)
run: ctest --test-dir build-tsan --output-on-failure
# ===== 静态分析 =====
static-analysis:
name: Static Analysis
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: 安装工具
run: sudo apt-get install -y cmake ninja-build clang-tidy-16
- name: 生成 compile_commands.json
run: |
cmake -B build \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_BUILD_TYPE=Debug \
-G Ninja
cmake --build build
- name: 运行 Clang-Tidy
run: |
run-clang-tidy-16 -p build -j$(nproc) \
-header-filter='(src|include)/.*' \
2>&1 | tee clang-tidy.log
! grep -q "warning:" clang-tidy.log
# ===== 代码格式检查 =====
format:
name: Code Format
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: 检查格式
run: |
find src include -name "*.cpp" -o -name "*.h" | \
xargs clang-format --dry-run --Werror
# ===== Docker 发布 =====
docker:
name: Docker Build & Push
runs-on: ubuntu-22.04
needs: [build, sanitizers]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: 登录 Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: 构建并推送
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
myorg/myapp:latest
myorg/myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max性能回归检测
yaml
benchmark:
name: Performance Benchmark
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: 构建 Benchmark
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_BENCHMARKS=ON
cmake --build build
- name: 运行 Benchmark
run: |
./build/benchmarks/bench \
--benchmark_out=benchmark_results.json \
--benchmark_out_format=json
- name: 存储结果
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'googlecpp'
output-file-path: benchmark_results.json
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
alert-threshold: '120%' # 性能下降 20% 时报警
comment-on-alert: true
fail-on-alert: true关键认知
C++ CI 的核心是多平台 + Sanitizers + 静态分析三位一体。vcpkg 缓存(actions/cache)避免每次重新编译依赖,是 CI 速度的关键。Sanitizers 在 CI 中运行,能在合并前发现内存问题。性能基准测试防止性能回归。