Appearance
GitHub Actions工作流语法
GitHub Actions工作流使用YAML语法定义,存储在仓库的.github/workflows/目录下。本章详细介绍工作流文件的语法结构和各项配置选项。
工作流文件基本结构
完整的工作流示例
yaml
# .github/workflows/example.yml
name: Example Workflow
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: '18.x'
BUILD_PATH: './dist'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
env:
BUILD_PATH: ${{ env.BUILD_PATH }}
工作流顶级属性
name
工作流的显示名称,在GitHub界面中可见:
yaml
name: CI/CD Pipeline # 可选,如果不设置则使用文件名
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: echo "Hello World"
on
定义触发工作流的事件:
yaml
# 单个事件
on: push
# 多个事件
on: [push, pull_request]
# 详细配置事件
on:
push:
branches: [main, develop]
tags: ['v*']
paths:
- 'src/**'
- 'package.json'
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
schedule:
- cron: '0 2 * * 1' # 每周一凌晨2点
workflow_dispatch: # 手动触发
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
type: choice
options:
- info
- warning
- debug
tags:
description: 'Test scenario tags'
required: false
type: boolean
environment:
description: 'Environment to run tests against'
type: environment
required: true
concurrency
控制并发执行,确保同一时间只有一个工作流实例运行:
yaml
name: Deploy Workflow
on: [push]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 取消进行中的工作流
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- run: echo "Deploying..."
env
定义全局环境变量:
yaml
env:
NODE_VERSION: '18.x'
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DEBUG: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo $NODE_VERSION
# 输出: 18.x
defaults
为所有作业设置默认值:
yaml
defaults:
run:
shell: bash
working-directory: ./subdirectory
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: pwd # 实际运行在 ./subdirectory
jobs
工作流的核心部分,包含一个或多个作业:
yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Build job"
test:
runs-on: ubuntu-latest
needs: build # 依赖build作业
steps:
- run: echo "Test job"
deploy:
runs-on: ubuntu-latest
needs: [build, test] # 依赖多个作业
if: github.ref == 'refs/heads/main' # 条件执行
steps:
- run: echo "Deploy job"
作业配置选项
runs-on
指定作业运行的环境:
yaml
jobs:
linux-job:
runs-on: ubuntu-latest
windows-job:
runs-on: windows-latest
macos-job:
runs-on: macos-latest
# 使用自定义标签
custom-job:
runs-on: [self-hosted, linux, x64]
# 使用表达式
dynamic-job:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
strategy
定义作业的执行策略,支持矩阵构建和并行执行:
yaml
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
include:
- node-version: 16
experimental: true
exclude:
- os: windows-latest
node-version: 16
fail-fast: false # 即使一个矩阵作业失败也继续执行其他作业
max-parallel: 2 # 最大并行作业数
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm test
needs
定义作业依赖关系:
yaml
jobs:
setup:
runs-on: ubuntu-latest
steps:
- run: echo "Setup completed"
build:
needs: setup # 等待setup作业完成
runs-on: ubuntu-latest
steps:
- run: echo "Build completed"
test:
needs: build # 等待build作业完成
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- run: echo "Testing on ${{ matrix.os }}"
deploy:
needs: [setup, build, test] # 等待多个作业完成
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- run: echo "Deploying to production"
if
条件执行作业:
yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Always runs"
deploy:
needs: build
runs-on: ubuntu-latest
if: |
github.ref == 'refs/heads/main' &&
github.event_name == 'push' &&
!contains(github.event.head_commit.message, '[skip ci]')
steps:
- run: echo "Deploying to production"
debug:
runs-on: ubuntu-latest
if: ${{ contains(github.event.head_commit.message, 'debug') }}
steps:
- run: echo "Debug mode enabled"
environment
为作业指定环境,用于部署保护规则和变量:
yaml
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- run: echo "Deploying to staging"
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com # 部署URL
steps:
- run: echo "Deploying to production"
步骤配置选项
uses
使用action:
yaml
steps:
# 使用GitHub Marketplace的action
- uses: actions/checkout@v4
# 使用特定版本的action
- uses: actions/setup-node@v4
with:
node-version: '18'
# 使用仓库中的action
- uses: ./path/to/local/action
# 使用Docker Hub的action
- uses: docker://alpine:latest
run
执行shell命令:
yaml
steps:
- name: Install dependencies
run: |
npm install
npm run build
- name: Single command
run: echo "Hello World"
- name: Multi-line command
run: |
ls -la
pwd
whoami
shell: bash # 指定shell类型
- name: Conditional command
run: npm run deploy
if: github.ref == 'refs/heads/main'
with
为action传递参数:
yaml
steps:
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
- uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: dist/
retention-days: 7
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest
build-args: |
NODE_VERSION=18
ENVIRONMENT=production
env
设置步骤的环境变量:
yaml
steps:
- name: Set environment variables
run: |
echo "API_URL is $API_URL"
echo "NODE_ENV is $NODE_ENV"
env:
API_URL: ${{ secrets.API_URL }}
NODE_ENV: production
TIMESTAMP: ${{ github.run_started_at }}
id
为步骤设置唯一标识符,以便后续步骤引用:
yaml
steps:
- id: vars
run: |
echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT
echo "commit=${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
- name: Use outputs
run: |
echo "Tag: ${{ steps.vars.outputs.tag }}"
echo "Commit: ${{ steps.vars.outputs.commit }}"
continue-on-error
即使步骤失败也继续执行后续步骤:
yaml
steps:
- name: Lint code
run: npm run lint
continue-on-error: true # 即使lint失败也继续
- name: Run tests
run: npm test
上下文和表达式
上下文对象
yaml
steps:
- name: Use contexts
run: |
echo "Repository: ${{ github.repository }}"
echo "Actor: ${{ github.actor }}"
echo "SHA: ${{ github.sha }}"
echo "Runner OS: ${{ runner.os }}"
echo "Job Status: ${{ job.status }}"
env:
WORKFLOW_NAME: ${{ github.workflow }}
BRANCH_NAME: ${{ github.ref_name }}
表达式语法
yaml
steps:
- name: Conditional logic
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
echo "Push event detected"
fi
if [[ "${{ contains(github.event.head_commit.message, 'fix') }}" == "true" ]]; then
echo "Fix commit detected"
fi
- name: String manipulation
run: |
echo "Lowercase: ${{ fromJSON(toJSON(github.repository)) }}"
echo "Length: ${{ length(github.ref) }}"
输出和依赖
步骤输出
yaml
jobs:
build:
runs-on: ubuntu-latest
outputs:
build-number: ${{ steps.version.outputs.build-number }}
artifact-name: ${{ steps.package.outputs.name }}
steps:
- id: version
run: |
BUILD_NUM=$(date +%s)
echo "build-number=$BUILD_NUM" >> $GITHUB_OUTPUT
shell: bash
- id: package
run: |
PKG_NAME="app-${{ steps.version.outputs.build-number }}"
echo "name=$PKG_NAME" >> $GITHUB_OUTPUT
test:
needs: build
runs-on: ubuntu-latest
steps:
- run: |
echo "Testing build ${{ needs.build.outputs.build-number }}"
echo "Artifact name: ${{ needs.build.outputs.artifact-name }}"
矩阵输出
yaml
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- name: Test Node.js version
run: |
echo "Testing Node.js ${{ matrix.node-version }}"
node --version
id: test
summary:
needs: test
runs-on: ubuntu-latest
if: always() # 无论前面的作业成功与否都执行
steps:
- run: echo "All tests completed"
高级配置示例
复杂工作流
yaml
name: Complex CI/CD Pipeline
on:
push:
branches: [main, develop]
tags: ['v*']
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: '18.x'
BUILD_PATH: './dist'
defaults:
run:
shell: bash
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
needs: lint
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: ['16.x', '18.x']
fail-fast: false
max-parallel: 3
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
- name: Upload coverage
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}-${{ matrix.node-version }}
path: coverage/
build:
needs: test
runs-on: ubuntu-latest
outputs:
build-number: ${{ steps.version.outputs.number }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run build
- id: version
run: |
echo "number=$(date +%s)" >> $GITHUB_OUTPUT
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ steps.version.outputs.number }}
path: ${{ env.BUILD_PATH }}
deploy-dev:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
environment: development
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build-${{ needs.build.outputs.build-number }}
path: ${{ env.BUILD_PATH }}
- name: Deploy to dev
run: ./deploy.sh dev
deploy-prod:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && startsWith(github.ref, 'refs/tags/')
environment:
name: production
url: https://production.example.com
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build-${{ needs.build.outputs.build-number }}
path: ${{ env.BUILD_PATH }}
- name: Deploy to production
run: ./deploy.sh prod
env:
AWS_ROLE_TO_ASSUME: ${{ secrets.AWS_ROLE }}
最佳实践
文件组织
yaml
# .github/workflows/ci.yml - 持续集成
# .github/workflows/cd.yml - 持续部署
# .github/workflows/security.yml - 安全扫描
# .github/workflows/release.yml - 发布流程
可维护性
yaml
# 使用描述性的作业和步骤名称
jobs:
run-unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Execute unit tests
run: npm run test:unit
通过掌握这些工作流语法,您可以创建功能强大且灵活的自动化工作流,满足各种CI/CD需求。