← 返回首页
🔧

GitHub Actions:工作流自动化

📂 devops ⏱ 4 min 639 words

GitHub Actions:工作流自动化

GitHub Actions简介

GitHub Actions是GitHub的原生CI/CD平台,允许在代码仓库中直接定义自动化工作流。

基础配置

工作流文件结构

# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run linting
        run: npm run lint
      
      - name: Run tests
        run: npm test

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      
      - name: Build Docker image
        run: docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
      
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Push to registry
        run: docker push ghcr.io/${{ github.repository }}:${{ github.sha }}

事件触发

多种触发方式

on:
  # Push触发
  push:
    branches: [main]
    tags: ['v*']
    paths:
      - 'src/**'
      - '!src/**/*.test.js'
  
  # PR触发
  pull_request:
    types: [opened, synchronize, reopened]
  
  # 定时触发
  schedule:
    - cron: '0 2 * * *'
  
  # 手动触发
  workflow_dispatch:
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

矩阵构建

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16, 18, 20]
      fail-fast: false
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

复用工作流

创建可复用工作流

# .github/workflows/reusable-deploy.yml
name: Reusable Deploy

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
      image:
        required: true
        type: string
    secrets:
      kubeconfig:
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    steps:
      - uses: azure/k8s-set-context@v3
        with:
          kubeconfig: ${{ secrets.kubeconfig }}
      
      - name: Deploy
        run: |
          kubectl set image deployment/myapp \
            myapp=${{ inputs.image }} \
            -n ${{ inputs.environment }}

调用可复用工作流

# .github/workflows/main.yml
jobs:
  deploy-staging:
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: staging
      image: ghcr.io/${{ github.repository }}:${{ github.sha }}
    secrets:
      kubeconfig: ${{ secrets.KUBE_CONFIG }}

  deploy-production:
    needs: deploy-staging
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: production
      image: ghcr.io/${{ github.repository }}:${{ github.sha }}
    secrets:
      kubeconfig: ${{ secrets.KUBE_CONFIG }}
    if: github.ref == 'refs/heads/main'

自定义Actions

# action.yml
name: 'Deploy to Kubernetes'
description: 'Deploy application to Kubernetes cluster'
inputs:
  image:
    description: 'Docker image to deploy'
    required: true
  namespace:
    description: 'Kubernetes namespace'
    required: true
  replicas:
    description: 'Number of replicas'
    required: false
    default: '3'
runs:
  using: 'composite'
  steps:
    - name: Deploy
      shell: bash
      run: |
        kubectl set image deployment/myapp myapp=${{ inputs.image }} -n ${{ inputs.namespace }}
        kubectl scale deployment myapp --replicas=${{ inputs.replicas }} -n ${{ inputs.namespace }}

实践:完整CI/CD工作流

# .github/workflows/ci-cd.yml
name: Complete CI/CD

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

env:
  IMAGE: ghcr.io/${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - name: Install & Test
        run: |
          npm ci
          npm run lint
          npm test
          npm run build

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'HIGH,CRITICAL'
          exit-code: '1'

  build:
    needs: [test, security]
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    permissions:
      contents: read
      packages: write
    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}
    steps:
      - uses: actions/checkout@v4
      
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.IMAGE }}
          tags: |
            type=sha
            type=ref,event=branch
      
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy-staging:
    needs: build
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up kubectl
        uses: azure/setup-kubectl@v3
      
      - name: Configure kubeconfig
        run: echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
      
      - name: Deploy to staging
        run: |
          kubectl set image deployment/myapp \
            myapp=${{ env.IMAGE }}:${{ github.sha }} \
            -n staging
          kubectl rollout status deployment/myapp -n staging --timeout=300s

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to production
        run: |
          kubectl set image deployment/myapp \
            myapp=${{ env.IMAGE }}:${{ github.sha }} \
            -n production
          kubectl rollout status deployment/myapp -n production --timeout=600s

常用Actions

# 缓存依赖
- uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

# 上传制品
- uses: actions/upload-artifact@v3
  with:
    name: build-output
    path: dist/

# 下载制品
- uses: actions/download-artifact@v3
  with:
    name: build-output

# Slack通知
- uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {"text": "Build succeeded: ${{ github.sha }}"}
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

总结

GitHub Actions是GitHub原生的CI/CD解决方案。掌握工作流配置、复用和高级功能,可以构建高效的自动化交付流水线。