跳到主要内容

GitHub Actions 基础

GitHub Actions 是 GitHub 提供的持续集成和持续部署(CI/CD)平台,可以自动化构建、测试和部署流程。

核心概念

工作流(Workflow)

工作流是一个可配置的自动化过程,定义在一个或多个作业中。工作流文件使用 YAML 格式,存放在仓库的 .github/workflows 目录下。

一个仓库可以有多个工作流文件,每个文件定义一个独立的工作流。

作业(Job)

作业是工作流中的一组步骤,在同一个运行器上执行。默认情况下,多个作业并行运行,可以通过依赖关系配置顺序执行。

步骤(Step)

步骤是作业中的最小执行单元,可以是:

  • 执行 shell 命令
  • 运行一个 Action

Action

Action 是可重用的代码单元,可以在工作流中引用。GitHub 提供了官方 Actions,社区也贡献了大量第三方 Actions。

运行器(Runner)

运行器是执行工作流的服务器。GitHub 提供:

  • ubuntu-latest:Linux 环境
  • windows-latest:Windows 环境
  • macos-latest:macOS 环境

也可以使用自托管运行器。

工作流文件结构

一个完整的工作流文件包含以下部分:

name: 工作流名称

on:
push:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 运行脚本
run: echo "Hello, GitHub Actions!"

触发器配置

on 字段定义工作流的触发条件。

推送触发

on:
push:
branches:
- main
- 'release/*'
tags:
- 'v*'
paths:
- 'src/**'
- '.github/workflows/**'

拉取请求触发

on:
pull_request:
branches: [ main ]
types: [ opened, synchronize, closed ]

定时触发

使用 cron 表达式定时执行:

on:
schedule:
- cron: '0 0 * * *'

cron 表达式格式:分 时 日 月 周

  • 0 0 * * *:每天零点
  • 0 0 * * 1:每周一零点
  • 0 0 1 * *:每月一号零点

手动触发

on:
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options:
- staging
- production

多事件触发

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

作业配置

运行环境

jobs:
build:
runs-on: ubuntu-latest

支持的运行器:

运行器系统说明
ubuntu-latestUbuntu最常用,预装主流开发工具
windows-latestWindows支持 .NET、PowerShell
macos-latestmacOS支持 iOS、macOS 开发

作业依赖

使用 needs 指定作业依赖关系:

jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "构建完成"

test:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "测试完成"

deploy:
needs: [build, test]
runs-on: ubuntu-latest
steps:
- run: echo "部署完成"

条件执行

使用 if 条件控制作业或步骤执行:

jobs:
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: echo "部署到生产环境"

常用条件表达式:

if: github.event_name == 'push'
if: github.ref == 'refs/heads/main'
if: startsWith(github.ref, 'refs/tags/')
if: github.event.pull_request.merged == true

环境变量

作业级别环境变量:

jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: production
DATABASE_URL: postgres://localhost:5432/test
steps:
- run: echo $NODE_ENV

工作流级别环境变量:

env:
GLOBAL_VAR: value

jobs:
build:
runs-on: ubuntu-latest

默认值

为所有 run 步骤设置默认 shell 和工作目录:

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
working-directory: ./app
steps:
- run: pwd

步骤配置

运行命令

使用 run 执行 shell 命令:

steps:
- name: 安装依赖
run: npm install

- name: 多行命令
run: |
npm install
npm run build
npm test

使用 Action

使用 uses 引用 Action:

steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

条件步骤

steps:
- name: 仅在主分支执行
if: github.ref == 'refs/heads/main'
run: echo "主分支"

- name: 仅在失败时执行
if: failure()
run: echo "前面的步骤失败了"

- name: 始终执行
if: always()
run: echo "清理工作"

继续执行

即使步骤失败也继续执行后续步骤:

steps:
- name: 可能失败的步骤
continue-on-error: true
run: exit 1

- name: 继续执行
run: echo "继续执行"

超时设置

steps:
- name: 限时步骤
timeout-minutes: 10
run: ./long-running-script.sh

Secrets 和上下文

使用 Secrets

Secrets 用于存储敏感信息,在仓库设置中配置:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 部署
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_PASSWORD: ${{ secrets.DB_PASSWORD }}
run: |
echo "使用 API_KEY 进行部署"

GitHub 上下文

GitHub 提供了丰富的上下文信息:

steps:
- name: 打印上下文
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"

常用上下文变量:

变量说明
github.event_name触发事件名称
github.ref分支或标签引用
github.sha提交 SHA
github.repository仓库名称
github.workflow工作流名称
github.run_id运行 ID
github.run_number运行序号
github.actor触发者用户名

环境变量引用

env:
MY_VAR: ${{ github.repository }}-${{ github.run_number }}

steps:
- run: echo $MY_VAR

输出变量

步骤可以定义输出变量供后续步骤使用:

jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}

steps:
- id: get_version
run: echo "version=1.0.0" >> $GITHUB_OUTPUT

- run: echo "版本是 ${{ steps.get_version.outputs.version }}"

deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "部署版本 ${{ needs.build.outputs.version }}"

矩阵构建

矩阵构建可以在多个配置组合下运行作业:

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
fail-fast: false
max-parallel: 4

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm test

这个配置会生成 9 个作业(3 系统 × 3 Node 版本)。

排除特定组合

strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
exclude:
- os: windows-latest
node: 18

包含特定组合

strategy:
matrix:
os: [ubuntu-latest]
node: [18, 20]
include:
- os: macos-latest
node: 20
experimental: true

缓存依赖

缓存可以加速工作流执行:

steps:
- uses: actions/checkout@v4

- name: 缓存 Node 模块
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-

- run: npm ci

常用缓存路径:

包管理器路径
npm~/.npm
pnpm~/.pnpm-store
Yarn~/.cache/yarn
pip~/.cache/pip
Maven~/.m2/repository
Gradle~/.gradle/caches

工件上传

工件用于在作业间共享文件或保存构建产物:

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

- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 5

deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: 下载构建产物
uses: actions/download-artifact@v4
with:
name: build-output
path: dist/

完整示例

以下是一个完整的 Node.js 项目 CI 工作流:

name: Node.js CI

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

env:
NODE_ENV: test

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint

test:
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20, 22]

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- run: npm ci
- run: npm test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}

build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/

常用官方 Actions

Action用途
actions/checkout检出代码
actions/setup-node配置 Node.js
actions/setup-python配置 Python
actions/setup-java配置 Java
actions/setup-go配置 Go
actions/cache缓存依赖
actions/upload-artifact上传工件
actions/download-artifact下载工件
actions/github-script执行 GitHub API 脚本

最佳实践

  1. 使用具体的 Action 版本:使用 SHA 或具体版本号,避免使用 @main
  2. 最小权限原则:配置 permissions 限制 GITHUB_TOKEN 权限
  3. 使用缓存:缓存依赖加速构建
  4. 保护 Secrets:不要在日志中暴露敏感信息
  5. 设置超时:防止工作流无限运行
  6. 使用矩阵构建:多版本、多系统测试
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: write

参考资源