触发器(on)完整指南
事件驱动的核心
GitHub Actions 的 on 字段定义什么情况下触发 Workflow。触发器的精确配置对流水线效率至关重要——过宽的触发条件浪费 CI 资源,过窄则可能遗漏重要检查。
常用触发事件
on:
# 推送到指定分支时触发
push:
branches:
- main
- 'release/**' # 通配符匹配
branches-ignore:
- 'feature/**' # 排除某些分支
paths: # 只有这些文件变更时才触发
- 'src/**'
- 'tests/**'
paths-ignore:
- 'docs/**'
- '**.md'
# Pull Request 相关事件
pull_request:
branches: [ main ]
types: [opened, synchronize, reopened]
# 定时触发(cron 格式)
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点 UTC
# 手动触发(带输入参数)
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
type: choice
options: [staging, production]
debug_enabled:
description: '开启调试模式'
type: boolean
default: false
# Release 发布时触发
release:
types: [published]
paths 过滤的重要性
在 Monorepo 中,使用 paths 过滤可以避免每次任意文件变更都触发所有 Workflow。例如,前端代码变更只触发前端测试,后端代码变更只触发后端测试,大幅节省 CI 时间和成本。
Jobs 作业结构
并行与顺序执行
jobs:
# Job 1:代码检查(并行)
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
# Job 2:单元测试(并行)
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
# Job 3:构建(必须等 lint 和 test 都成功)
build:
runs-on: ubuntu-latest
needs: [lint, test] # 依赖声明
steps:
- uses: actions/checkout@v4
- run: npm run build
# Job 4:部署(只在 main 分支)
deploy:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main' # 条件执行
environment: production # 部署环境(可设置保护规则)
steps:
- run: echo "部署到生产环境"
Jobs 的输出传递
jobs:
setup:
runs-on: ubuntu-latest
outputs: # 定义输出变量
version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@v4
- id: get-version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
deploy:
needs: setup
runs-on: ubuntu-latest
steps:
- run: |
echo "部署版本: ${{ needs.setup.outputs.version }}"
Steps 步骤详解
run:执行 Shell 命令
steps:
# 单行命令
- run: echo "单行命令"
# 多行命令(使用 | 折叠块)
- name: 运行测试并生成报告
run: |
npm install
npm run test:coverage
echo "测试完成,覆盖率报告在 coverage/ 目录"
shell: bash # 默认 bash,也支持 sh/python/pwsh
working-directory: ./frontend # 在指定目录执行
# 条件执行
- name: 只在失败时发送通知
if: failure()
run: curl -X POST $SLACK_WEBHOOK -d '{"text":"构建失败!"}'
# 超时控制
- name: 长时间运行的测试
run: npm run test:e2e
timeout-minutes: 30
# 继续执行即使失败(用于收集全部测试结果)
- name: 运行所有测试(不提前终止)
run: npm test
continue-on-error: true
uses:调用 Action
steps:
# 官方 Action(GitHub 维护)
- uses: actions/checkout@v4 # 检出代码
- uses: actions/setup-node@v4 # 配置 Node.js
with:
node-version: '20'
cache: 'npm' # 自动缓存 npm 依赖
# 社区 Action(第三方发布)
- uses: codecov/codecov-action@v4 # 上传覆盖率
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
# 本地 Action(当前仓库中的自定义 Action)
- uses: ./.github/actions/my-action
# 引用特定提交哈希(最安全,防止供应链攻击)
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
安全实践:固定 Action 版本
使用 @v4 等标签而非 @main。更安全的做法是使用完整的 commit SHA(如上例),防止 Action 维护者恶意修改标签指向的版本(供应链攻击)。GitHub 的 Dependabot 可以自动更新这些固定的 SHA。
完整 CI Workflow 示例(Node.js 项目)
name: Node.js CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22] # 多版本并行测试
steps:
- uses: actions/checkout@v4
- name: 配置 Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: 安装依赖
run: npm ci # ci 比 install 更快、更可靠
- name: 代码检查
run: npm run lint
- name: 运行测试
run: npm test
- name: 构建
run: npm run build
触发器详解:常见配置误区
branches vs branches-ignore 互斥
同一事件中,
branches 和 branches-ignore 不能同时使用,只能二选一。paths 和 paths-ignore 同理。通配符支持 *(不匹配 /)、**(匹配任意,包括 /)、?(单字符)。pull_request 的安全边界
来自 Fork 仓库的 PR 触发时,默认不能读取仓库 Secrets(出于安全考虑)。如需为外部贡献者的 PR 运行需要 Secrets 的步骤,需用
pull_request_target 事件(运行基础分支代码,有安全风险,需谨慎)。workflow_dispatch 手动触发价值
支持手动输入参数(string/boolean/choice/environment 类型),通过
${{ github.event.inputs.参数名 }} 访问。适合一次性迁移脚本、按需部署到特定环境等场景,结合 GitHub CLI 可以从命令行触发。schedule cron 的时区
GitHub Actions 的 cron 触发时区始终是 UTC,没有本地时区选项。北京时间(CST = UTC+8)的早上 9 点对应 UTC 1 点:
cron: '0 1 * * *'。定时 Workflow 在繁忙时可能延迟几分钟触发。Job 级别的常用配置
jobs:
build:
runs-on: ubuntu-latest
# 超时保护:Job 最多运行 30 分钟(默认 360 分钟)
timeout-minutes: 30
# 权限声明(最小权限原则)
permissions:
contents: read # 只读代码
packages: write # 允许推送包
pull-requests: write # 允许评论 PR
# 并发控制:同一组只运行一个实例
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true # 新推送时取消旧的运行
steps:
- uses: actions/checkout@v4
# 步骤输出:向后续步骤传递数据
- name: 生成构建 ID
id: build-id
run: |
BUILD_ID="build-$(date +%Y%m%d)-${{ github.run_number }}"
echo "id=$BUILD_ID" >> $GITHUB_OUTPUT
- name: 使用构建 ID
run: echo "构建 ID: ${{ steps.build-id.outputs.id }}"
本章小结
本章核心要点
- 触发器精确配置:push/pull_request 用 branches/paths 过滤,避免无关变更触发 CI;schedule 使用 UTC 时区;workflow_dispatch 支持输入参数实现手动部署。
- Job 依赖与并行:默认并行执行,needs 声明顺序依赖;if: 条件控制 Job 是否运行;outputs + needs.JOB.outputs 实现 Job 间数据传递。
- Step 关键字段:name(可读标签)、id(供 steps 上下文引用)、if(条件)、run(Shell 命令)、uses(Action)、with(参数)、env(环境变量)、continue-on-error(失败继续)。
- GITHUB_OUTPUT vs GITHUB_ENV:
echo "key=value" >> $GITHUB_OUTPUT设置步骤输出(用 steps.ID.outputs.key 访问);echo "VAR=value" >> $GITHUB_ENV设置环境变量(后续步骤的 $VAR 可用)——二者不可混淆。 - Action 安全引用:开发用 @v4 标签,生产关键步骤用完整 SHA 固定版本(防止供应链攻击);uses: actions/setup-node@v4 中的 @v4 是 Git Tag,不是 npm 版本。
- timeout-minutes 必设:默认 360 分钟(6 小时)会消耗大量 CI 额度;建议为每个 Job 设置合理超时(如 30-60 分钟),避免卡住的进程耗尽月度额度。