GitHub Actions 条件执行 #

条件执行允许你根据特定条件控制作业和步骤的执行。本节详细介绍条件表达式的使用。

条件概述 #

什么是条件执行? #

条件执行使用 if 表达式决定是否执行:

  • 作业级别条件
  • 步骤级别条件
  • 基于上下文和状态

基本语法 #

yaml
jobs:
  job-name:
    if: expression
    steps:
      - name: step-name
        if: expression

作业条件 #

基本条件 #

yaml
jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to production"

多条件组合 #

yaml
jobs:
  deploy:
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying"

基于依赖状态 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building"

  deploy:
    needs: build
    if: success()
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying"

步骤条件 #

基本条件 #

yaml
steps:
  - name: Only on main
    if: github.ref == 'refs/heads/main'
    run: echo "This is main branch"

基于前序步骤状态 #

yaml
steps:
  - name: Step 1
    id: step1
    run: echo "Step 1"

  - name: On success
    if: success()
    run: echo "Previous steps succeeded"

  - name: On failure
    if: failure()
    run: echo "Previous steps failed"

基于步骤输出 #

yaml
steps:
  - id: check
    run: echo "should_deploy=true" >> $GITHUB_OUTPUT

  - name: Deploy
    if: steps.check.outputs.should_deploy == 'true'
    run: echo "Deploying"

状态函数 #

success() #

所有前序步骤成功时返回true。

yaml
steps:
  - name: On success
    if: success()
    run: echo "All previous steps succeeded"

failure() #

任一前序步骤失败时返回true。

yaml
steps:
  - name: On failure
    if: failure()
    run: echo "Some previous step failed"

always() #

总是返回true,无论前序步骤状态。

yaml
steps:
  - name: Always run
    if: always()
    run: echo "This always runs"

cancelled() #

工作流被取消时返回true。

yaml
steps:
  - name: On cancelled
    if: cancelled()
    run: echo "Workflow was cancelled"

条件表达式 #

比较运算符 #

yaml
# 等于
if: github.ref == 'refs/heads/main'

# 不等于
if: github.ref != 'refs/heads/develop'

# 包含
if: contains(github.ref, 'release')

# 开头匹配
if: startsWith(github.ref, 'refs/tags/')

# 结尾匹配
if: endsWith(github.ref, '.js')

逻辑运算符 #

yaml
# 与
if: github.ref == 'refs/heads/main' && success()

# 或
if: github.event_name == 'push' || github.event_name == 'pull_request'

# 非
if: !failure()

复杂表达式 #

yaml
jobs:
  deploy:
    if: |
      github.event_name == 'push' &&
      github.ref == 'refs/heads/main' &&
      !contains(github.event.head_commit.message, '[skip deploy]')

常见使用场景 #

分支条件 #

yaml
jobs:
  deploy-production:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to production"

  deploy-staging:
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to staging"

事件条件 #

yaml
jobs:
  on-push:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Push event"

  on-pr:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Pull request event"

标签条件 #

yaml
jobs:
  release:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - run: echo "Release from tag"

矩阵条件 #

yaml
jobs:
  test:
    strategy:
      matrix:
        node: [16, 18, 20]
    runs-on: ubuntu-latest
    steps:
      - name: Coverage report
        if: matrix.node == '20'
        run: npm run coverage

手动触发条件 #

yaml
on:
  workflow_dispatch:
    inputs:
      environment:
        type: choice
        options:
          - staging
          - production

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to staging
        if: github.event.inputs.environment == 'staging'
        run: ./deploy.sh staging

      - name: Deploy to production
        if: github.event.inputs.environment == 'production'
        run: ./deploy.sh production

路径条件 #

yaml
jobs:
  build:
    if: contains(github.event.head_commit.modified, 'src/')
    runs-on: ubuntu-latest
    steps:
      - run: echo "Source files changed"

作业依赖条件 #

基于依赖状态 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building"

  test:
    needs: build
    if: success()
    runs-on: ubuntu-latest
    steps:
      - run: echo "Testing"

  deploy:
    needs: [build, test]
    if: success() && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying"

检查特定依赖状态 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: exit 0

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: exit 1

  notify:
    needs: [build, test]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Build status
        run: echo "Build: ${{ needs.build.result }}"
      - name: Test status
        run: echo "Test: ${{ needs.test.result }}"
      - name: Overall status
        if: needs.build.result == 'success' && needs.test.result == 'success'
        run: echo "All succeeded"

部分依赖成功 #

yaml
jobs:
  test-unit:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Unit tests"

  test-integration:
    runs-on: ubuntu-latest
    steps:
      - run: exit 1

  deploy:
    needs: [test-unit, test-integration]
    if: needs.test-unit.result == 'success'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying despite integration test failure"

continue-on-error #

步骤级 #

yaml
steps:
  - name: Might fail
    run: exit 1
    continue-on-error: true

  - name: Will still run
    run: echo "This runs even if previous step failed"

条件continue #

yaml
steps:
  - name: Conditional continue
    run: exit 1
    continue-on-error: ${{ github.ref != 'refs/heads/main' }}

实际应用示例 #

CI/CD流水线 #

yaml
name: CI/CD

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

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  test:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build

  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - run: ./deploy.sh staging

  deploy-production:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: ./deploy.sh production

  notify:
    needs: [deploy-staging, deploy-production]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Success notification
        if: success()
        run: echo "Deployment successful"
      - name: Failure notification
        if: failure()
        run: echo "Deployment failed"

回滚工作流 #

yaml
jobs:
  validate:
    runs-on: ubuntu-latest
    outputs:
      can-rollback: ${{ steps.check.outputs.can }}
    steps:
      - id: check
        run: |
          if [ "$(./check-version.sh)" == "valid" ]; then
            echo "can=true" >> $GITHUB_OUTPUT
          else
            echo "can=false" >> $GITHUB_OUTPUT
          fi

  rollback:
    needs: validate
    if: needs.validate.outputs.can-rollback == 'true'
    runs-on: ubuntu-latest
    steps:
      - run: ./rollback.sh

最佳实践 #

1. 使用有意义的条件 #

yaml
# 推荐
if: github.ref == 'refs/heads/main'

# 不推荐
if: ${{ true }}

2. 组合条件使用多行 #

yaml
if: |
  github.event_name == 'push' &&
  github.ref == 'refs/heads/main' &&
  !contains(github.event.head_commit.message, '[skip ci]')

3. 使用环境变量简化 #

yaml
env:
  IS_MAIN: ${{ github.ref == 'refs/heads/main' }}

jobs:
  deploy:
    if: env.IS_MAIN == 'true'

4. 总是清理资源 #

yaml
jobs:
  cleanup:
    if: always()
    runs-on: ubuntu-latest
    steps:
      - run: ./cleanup.sh

5. 使用环境保护 #

yaml
jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    environment: production

下一步学习 #

小结 #

  • 使用if表达式控制执行
  • 支持作业级和步骤级条件
  • 状态函数检查前序步骤状态
  • 使用比较和逻辑运算符
  • continue-on-error允许失败继续
  • 基于上下文和依赖状态判断
  • 使用always()确保清理步骤执行
最后更新:2026-03-28