Skip to content

🔄 CI/CD 流程

lzt 项目采用现代化的 CI/CD 流程,通过 GitHub Actions 实现自动化构建、测试和部署。

🎯 CI/CD 策略

核心原则

  • 自动化优先 - 减少手动操作,提高效率和准确性
  • 快速反馈 - 快速发现和解决问题
  • 质量门禁 - 确保只有高质量代码进入主分支
  • 环境一致性 - 开发、测试、生产环境保持一致

流水线架构

🔧 GitHub Actions 配置

主要工作流

CI 流程 (.github/workflows/ci.yml)

yaml
name: Continuous Integration
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

env:
  GO_VERSION: '1.24.3'
  NODE_VERSION: '18'

jobs:
  lint:
    name: Code Quality
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v4
        with:
          go-version: ${{ env.GO_VERSION }}
      
      - name: Run go fmt
        run: |
          if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
            echo "Go formatting errors:"
            gofmt -s -l .
            exit 1
          fi
      
      - name: Run go vet
        run: go vet ./...
      
      - name: Run staticcheck
        uses: dominikh/staticcheck-action@v1.3.0
        with:
          version: "2023.1.6"

  test:
    name: Unit Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v4
        with:
          go-version: ${{ env.GO_VERSION }}
      
      - name: Run tests
        run: go test -v -race -coverprofile=coverage.out ./...
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.out
          flags: unittests
          name: codecov-umbrella

  integration-test:
    name: Integration Tests
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: test_db
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=3
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v4
        with:
          go-version: ${{ env.GO_VERSION }}
      
      - name: Wait for MySQL
        run: |
          while ! mysqladmin ping -h127.0.0.1 -P3306 -uroot -ppassword --silent; do
            sleep 1
          done
      
      - name: Run integration tests
        run: go test -tags=integration ./...
        env:
          DB_HOST: 127.0.0.1
          DB_PORT: 3306
          DB_USER: root
          DB_PASSWORD: password
          DB_NAME: test_db

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v4
        with:
          go-version: ${{ env.GO_VERSION }}
      
      - name: Build binary
        run: |
          go build -o lzt main.go
          ./lzt version
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: lzt-binary
          path: lzt

发布流程 (.github/workflows/release.yml)

yaml
name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - uses: actions/setup-go@v4
        with:
          go-version: '1.24.3'
      
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v4
        with:
          distribution: goreleaser
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

📊 质量门禁

代码质量检查

  • 格式化检查 - gofmt 确保代码格式一致
  • 静态分析 - go vetstaticcheck 发现潜在问题
  • 测试覆盖率 - 要求单元测试覆盖率 ≥ 80%
  • 依赖安全扫描 - 检查已知安全漏洞

自动化测试

yaml
# 测试矩阵 - 多环境测试
strategy:
  matrix:
    go-version: ['1.23', '1.24.3']
    os: [ubuntu-latest, macos-latest, windows-latest]
    
steps:
  - name: Test on ${{ matrix.os }} with Go ${{ matrix.go-version }}
    run: go test ./...

性能回归检测

yaml
- name: Benchmark tests
  run: |
    go test -bench=. -benchmem ./... > bench-new.txt
    
- name: Compare benchmarks
  run: |
    if [ -f bench-baseline.txt ]; then
      benchcmp bench-baseline.txt bench-new.txt
    fi

🚀 部署策略

环境管理

  • 开发环境 - 特性分支自动部署
  • 测试环境 - develop 分支持续部署
  • 预生产环境 - release 分支部署
  • 生产环境 - tagged 版本部署

Docker 容器化部署

dockerfile
# Dockerfile
FROM golang:1.24.3-alpine AS builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o lzt main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/

COPY --from=builder /app/lzt .

EXPOSE 8080
CMD ["./lzt", "ledger", "server"]

Kubernetes 部署

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: lzt
spec:
  replicas: 3
  selector:
    matchLabels:
      app: lzt
  template:
    metadata:
      labels:
        app: lzt
    spec:
      containers:
      - name: lzt
        image: lzt:latest
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          value: "mysql-service"
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: username

🔍 监控和告警

构建监控

yaml
- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: failure
    channel: '#ci-cd'
    message: |
      Build failed for ${{ github.repository }}
      Branch: ${{ github.ref }}
      Commit: ${{ github.sha }}
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

部署健康检查

yaml
- name: Health check
  run: |
    timeout 300 bash -c 'until curl -f http://localhost:8080/health; do sleep 5; done'
    
- name: Run smoke tests
  run: |
    ./scripts/smoke-tests.sh

📈 性能优化

构建缓存

yaml
- 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: Cache Docker layers
  uses: actions/cache@v3
  with:
    path: /tmp/.buildx-cache
    key: ${{ runner.os }}-buildx-${{ github.sha }}
    restore-keys: |
      ${{ runner.os }}-buildx-

并行化执行

yaml
jobs:
  test:
    strategy:
      matrix:
        package: [./pkg/bubble, ./pkg/errors, ./internal/app/ledger]
    steps:
      - name: Test ${{ matrix.package }}
        run: go test -v ${{ matrix.package }}

🛡️ 安全最佳实践

密钥管理

yaml
- name: Deploy to production
  run: |
    echo "$DEPLOY_KEY" | base64 -d > deploy_key
    chmod 600 deploy_key
    ssh -i deploy_key user@server "deploy.sh"
  env:
    DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

依赖扫描

yaml
- name: Run security scan
  uses: securecodewarrior/github-action-add-sarif@v1
  with:
    sarif-file: 'govulncheck-report.sarif'

📚 相关文档

CI/CD 详细指南

相关实践


💡 最佳实践: CI/CD 不仅仅是自动化工具,更是软件开发文化的体现。要持续优化流程,追求快速反馈和高质量交付。

基于 MIT 许可证发布