GitHub Actions 完全指南:CI/CD 工作流设计、可复用 Actions、自制 Action 与企业级最佳实践

GitHub Actions 深度指南:工作流语法(触发器/任务/步骤)、环境变量与 Secrets 管理、矩阵构建、缓存策略(npm/Docker/BuildKit)、Artifact 传递、可复用工作流(reusable workflows)、自制 Action 开发、Self-hosted Runner、权限安全与审计。

GitHub Actions 是 GitHub 提供的原生 CI/CD(持续集成/持续部署)服务,直接集成在代码仓库中。当代码推送、PR 创建、Issue 打开等事件触发时,自动执行预定义的工作流——运行测试、构建应用、部署到服务器。它与 GitHub 生态无缝集成,且对公共仓库完全免费,是独立开发者和团队的首选 CI/CD 工具。


一、核心概念

概念说明
Workflow(工作流)一个 YAML 文件,定义一组自动化任务,放置在 .github/workflows/ 目录
Event(事件)触发工作流的条件:push、pull_request、schedule 等
Job(任务)工作流中的一个执行单元,默认并行运行
Step(步骤)Job 中的执行步骤,按顺序运行
Action(动作)可复用的步骤单元,如 actions/checkout@v4
Runner(运行器)执行 Job 的虚拟机(Ubuntu/macOS/Windows)
Artifact(产物)Job 间传递的文件(构建结果、测试报告)

二、工作流设计模式

2.1 最小可运行示例

name: Hello World
on:
  push:
    branches: [main]
jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: echo "Hello, GitHub Actions!"

2.2 完整语法速查

name: Comprehensive Workflow

on:
  push:
    branches: [main, develop]
    paths: ['src/**', 'tests/**']
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'            # 每天凌晨 2 点
  workflow_dispatch:               # 手动触发
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'staging'
        type: choice
        options: [staging, production]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true         # 新执行取消正在运行的旧执行

env:
  NODE_VERSION: '20'

jobs:
  lint:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
      - run: npm ci
      - run: npm run lint

  test:
    needs: lint                    # 等待 lint 完成后执行
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        node: [18, 20, 22]
        os: [ubuntu-latest]
        include:
          - node: 20
            os: windows-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm test

  deploy:
    needs: [lint, test]
    runs-on: ubuntu-latest
    environment:
      name: Production
      url: https://myapp.com
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

2.3 环境变量与 Secrets

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      PUBLIC_VAR: 'visible'              # 普通环境变量
    steps:
      - name: Use secrets
        env:
          API_KEY: ${{ secrets.API_KEY }}           # 敏感信息
          STAGE: ${{ vars.DEPLOY_STAGE }}           # 非敏感配置
        run: |
          echo "Deploying to $STAGE"
          npx deploy-cli --key "$API_KEY"

Secrets vs Variables

  • Secrets:加密存储,不可在日志中显示,适合 API Key、密码
  • Variables:明文存储,可在日志中显示,适合环境名、Region

三、可复用工作流(Reusable Workflows)

3.1 定义可复用工作流

# .github/workflows/reusable-test.yml
name: Reusable Test Workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
        default: '20'
      run-e2e:
        required: false
        type: boolean
        default: false
    secrets:
      codecov-token:
        required: false

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm run test
      - if: inputs.run-e2e
        run: npm run test:e2e
      - if: secrets.codecov-token
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.codecov-token }}

3.2 调用可复用工作流

# .github/workflows/main.yml
jobs:
  call-reusable:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: '20'
      run-e2e: true
    secrets:
      codecov-token: ${{ secrets.CODECOV_TOKEN }}

跨仓库调用

jobs:
  call-remote:
    uses: my-org/shared-workflows/.github/workflows/test.yml@main
    with:
      node-version: '20'

四、自制 Action 开发

4.1 Composite Action(组合型)

# .github/actions/setup-node-pnpm/action.yml
name: 'Setup Node + pnpm'
description: 'Setup Node.js with pnpm caching'

inputs:
  node-version:
    description: 'Node.js version'
    required: true
    default: '20'

runs:
  using: "composite"
  steps:
    - uses: pnpm/action-setup@v3
      with:
        version: 9
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'pnpm'
    - run: pnpm install --frozen-lockfile
      shell: bash

使用:

steps:
  - uses: actions/checkout@v4
  - uses: ./.github/actions/setup-node-pnpm
    with:
      node-version: '20'

4.2 JavaScript Action

// .github/actions/my-action/index.js
const core = require('@actions/core');
const github = require('@actions/github');

async function run() {
  try {
    const name = core.getInput('name');
    const greeting = `Hello, ${name}!`;
    core.setOutput('greeting', greeting);
    core.info(greeting);
  } catch (error) {
    core.setFailed(error.message);
  }
}

run();
# .github/actions/my-action/action.yml
name: 'My Action'
inputs:
  name:
    required: true
    default: 'World'
outputs:
  greeting:
    description: 'The greeting message'
runs:
  using: 'node20'
  main: 'index.js'

五、Self-hosted Runner

5.1 配置企业内网 Runner

# 在目标服务器上执行
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.317.0.tar.gz \
  -L https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.317.0.tar.gz
./config.sh --url https://github.com/my-org/my-repo --token <TOKEN>
./run.sh

5.2 使用 Self-hosted Runner

jobs:
  deploy-internal:
    runs-on: [self-hosted, linux, x64]  # 标签匹配
    steps:
      - uses: actions/checkout@v4
      - run: docker-compose up -d

适用场景

  • 需要访问内网资源(私有 Registry、内部 API)
  • 需要特殊硬件(GPU、专用网络)
  • 数据合规要求(代码不出企业网络)

六、权限安全最佳实践

6.1 最小权限原则

jobs:
  deploy:
    permissions:
      contents: read         # 只读代码
      packages: write        # 推送镜像
      id-token: write        # OIDC 认证

6.2 OIDC 免密认证(AWS/Azure/GCP)

permissions:
  id-token: write
  contents: read

jobs:
  deploy-aws:
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
          aws-region: us-east-1
      # 无需存储 AWS 密钥,使用临时 Token

常见问题(FAQ)

GitHub Actions 免费吗?

公共仓库:完全免费,无限制。私有仓库:每月 2000 分钟(Linux)、500MB Artifact 存储。超出后按使用量计费。

和 GitLab CI / Jenkins 怎么选?

工具适用场景
GitHub ActionsGitHub 仓库、快速上手、开源项目
GitLab CIGitLab 仓库、一体化 DevOps 平台
Jenkins企业自托管、复杂 Pipeline、大量插件需求
CircleCI需要高级并行、可视化、企业级支持
Travis CI简单开源项目

如何调试失败的 Workflow?

  1. 查看 Actions 日志(每个 step 的输出)
  2. 开启 debug 模式:ACTIONS_STEP_DEBUG=true secret
  3. 使用 tmate 远程 SSH 到 runner:
    - uses: mxschmitt/action-tmate@v3
      if: failure()
    

相关阅读

← 上一篇

继续阅读

探索更多技术文章

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

全部文章 返回首页

「saas」更多文章