掌握 GitHub Actions Workflow

从零开始学习 CI/CD 自动化流水线 — 通过 4 个渐进级别,亲手构建真实可用的工作流

4
学习级别
8+
核心概念
~2h
预计时长

📍 知识地图

点击各节点深入了解 GitHub Actions 的核心概念与执行流程

执行流程

⚡ Trigger 触发
push / pull_request / schedule / workflow_dispatch
📦 Workflow 工作流
.github/workflows/*.yml
🖥️ Job A
Build & Test
🚀 Job B
Deploy (needs: A)
🔧 Steps 步骤
run 命令 / uses 引用 Action

概念树 — 点击展开

📄Workflow 文件
存放路径 .github/workflows/*.yml
每个仓库可包含多个 Workflow 文件,互不影响
基本结构 name → on → jobs
名称、触发器、任务列表三大部分
环境变量 env:
可在 workflow / job / step 三个层级设置
Triggers 触发器
push / pull_request
最常用的触发器,可指定分支和路径过滤
schedule
使用 cron 表达式定时执行,如 '0 2 * * *' 每天凌晨 2 点
workflow_dispatch
允许在 GitHub UI 中手动触发,可定义输入参数
repository_dispatch
通过 API 外部触发,适合跨仓库联动
🖥️Jobs 任务
runs-on
指定运行器:ubuntu-latest / windows-latest / macOS-latest / self-hosted
needs
声明 Job 之间的依赖关系,构成 DAG 执行图
strategy.matrix
矩阵构建:一次运行多个 OS / 语言版本的组合
if 条件
控制 Job 是否执行,如 if: github.ref == 'refs/heads/main'
outputs
Job 输出值,供下游 Job 通过 needs 访问
🔧Steps & Actions
uses: actions/checkout@v4
拉取代码仓库 — 几乎所有 Workflow 的第一步
run:
执行 Shell 命令(bash / pwsh / python 等)
with:
给 Action 传参,类似函数参数
常用 Actions
setup-nodesetup-pythoncacheupload-artifact
🔐Secrets & 环境变量
secrets.GITHUB_TOKEN
GitHub 自动提供的认证令牌,无需手动配置
secrets.MY_SECRET
在仓库 Settings → Secrets 中添加的自定义密钥
上下文表达式 ${{ }}
引用变量:${{ github.sha }}${{ env.MY_VAR }}
📦Artifacts & Caching
upload-artifact / download-artifact
在 Job 之间传递文件,或保存构建产物供下载
actions/cache
缓存依赖项(node_modules、pip 等),大幅加速后续运行

📊 常用触发器对比

触发器触发时机典型场景
push代码推送到指定分支CI 构建 & 测试
pull_requestPR 创建/更新代码审查 & 检查
scheduleCron 定时定期巡检、夜间构建
workflow_dispatch手动触发按需部署、调试
release发布版本时发布流水线
workflow_call被其他 Workflow 调用可复用 Workflow

⭐ Level 1 认识 Workflow 结构

目标:读懂一个完整的 Workflow YAML 文件,理解每个字段的含义 · 预计 15 分钟

1.1 阅读你的第一个 Workflow

下面是一个 Node.js 项目的 CI Workflow。点击每行注释旁的 💡 按钮,查看该字段的详细说明。

YAML
# .github/workflows/ci.yml name: Node.js CI # 💡 on: # 💡 push: branches: ["main"] # 💡 pull_request: branches: ["main"] jobs: # 💡 build: # 💡 runs-on: ubuntu-latest # 💡 steps: - uses: actions/checkout@v4 # 💡 - name: Setup Node.js uses: actions/setup-node@v4 # 💡 with: node-version: '20' - run: npm ci # 💡 - run: npm test # 💡

1.2 理解执行顺序

把这个 Workflow 想象成一条流水线。拖动下面的卡片,将它们排列为正确的执行顺序:

npm ci + npm test — 安装依赖并运行测试
push to main — 触发 Workflow
checkout + setup-node — 准备环境

1.3 小试牛刀

在下面的 Workflow 中,有一个 YAML 语法错误。找出来并修正它:

找 Bug
name: My Workflow on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run echo "Hello" ← 这里有问题?
💡 提示

run 后面应该用冒号 : 而不是空格。正确写法是 run: echo "Hello"。YAML 中键值对必须用冒号分隔。

⭐⭐ Level 2 构建你的 CI 流水线

目标:补全一个 Python 项目的 CI Workflow,掌握 Jobs、Steps 和 Matrix 构建 · 预计 25 分钟

2.1 补全 Workflow 模板

你正在为一个 Python Flask 项目搭建 CI。模板已搭好框架,请根据注释补全 TODO 部分。

YAML — 请补全 TODO 部分
name: Python CI on: push: branches: ["main", "develop"] # TODO 1: 添加 pull_request 触发器 # ___________________ jobs: test: runs-on: ubuntu-latest # TODO 2: 添加 matrix 策略,测试 Python 3.10 和 3.12 # strategy: # matrix: # ___________________ steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: # TODO 3: 引用 matrix 中的 Python 版本 # python-version: ___________ - name: Install dependencies # TODO 4: 安装依赖的命令 # run: ___________ - name: Run tests run: pytest --verbose
YAML — 完整答案
name: Python CI on: push: branches: ["main", "develop"] pull_request: # ✅ TODO 1 branches: ["main"] jobs: test: runs-on: ubuntu-latest strategy: # ✅ TODO 2 matrix: python-version: ["3.10", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} # ✅ TODO 3 - name: Install dependencies run: pip install -r requirements.txt # ✅ TODO 4 - name: Run tests run: pytest --verbose

💡 使用 matrix 后,GitHub 会自动创建 2 个并行 Job,分别测试 Python 3.10 和 3.12。

2.2 添加依赖缓存

每次 CI 都重新 pip install 太慢了。用 actions/cache 缓存依赖,加速后续运行:

YAML
- name: Cache pip packages uses: actions/cache@v4 with: path: ~/.cache/pip # 缓存目录 key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip-

这里的 key 是缓存的唯一标识。当 requirements.txt 内容变化时,哈希值改变,缓存失效并重新生成。restore-keys 允许精确匹配失败时回退到前缀匹配。

💡 关键理解

缓存和 Artifacts 的区别:
Cache = 加速依赖安装,在同一 Job 的后续步骤中复用
Artifacts = 在不同 Job 之间传递文件,或保存构建产物
缓存有 10GB 上限,7 天不用自动清理。

⭐⭐⭐ Level 3 搭建完整 CI/CD 流水线

目标:独立编写一个包含构建、测试、部署的多 Job Workflow · 预计 40 分钟

📋 需求描述

你有一个 Node.js + Docker 的 Web 应用。请编写一个 Workflow 满足以下要求:

  • push 到 main 分支时触发
  • Job 1 build:安装依赖 → 运行 lint → 运行测试
  • Job 2 docker:构建 Docker 镜像 → 推送到 Docker Hub(依赖 build 成功)
  • Job 3 deploy:SSH 部署到服务器(依赖 docker 成功,且仅在 main 分支执行)
  • 使用 Secrets 存储 Docker Hub 密码和 SSH 私钥

✏️ 开始编写

在下方编辑器中编写你的 Workflow YAML。可以随时点击「查看参考」对比答案。

name: Deploy Pipeline on: # TODO: 添加触发器 jobs: build: runs-on: ubuntu-latest steps: # TODO: checkout, setup, lint, test docker: # TODO: 声明依赖 + 运行器 steps: # TODO: build & push docker image deploy: # TODO: 条件判断 + SSH 部署
等待验证...
参考答案
YAML
name: Deploy Pipeline on: push: branches: ["main"] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - run: npm ci - run: npm run lint - run: npm test docker: needs: build # 依赖 build Job runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Login to Docker Hub run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USER }}" --password-stdin - name: Build & Push run: | docker build -t myapp:${{ github.sha }} . docker push myapp:${{ github.sha }} deploy: needs: docker # 依赖 docker Job runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' # 仅 main 分支 steps: - name: Deploy via SSH uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: deploy key: ${{ secrets.SSH_PRIVATE_KEY }} script: | docker pull myapp:${{ github.sha }} docker stop myapp || true docker run -d --name myapp -p 80:3000 myapp:${{ github.sha }}

⭐⭐⭐⭐ Level 4 进阶挑战

目标:优化流水线性能、处理边缘场景、构建可复用 Workflow · 预计 40 分钟

挑战 A:性能优化 🔥

你的 Workflow 运行时间从 3 分钟增长到了 12 分钟。在不改变功能的前提下,用以下手段优化:

缓存依赖

用 actions/cache 缓存 node_modules 或 pip 包

并行执行

lint 和 test 可以在两个 Job 中并行运行

路径过滤

仅当 src/ 目录变更时才触发 CI

条件跳过

文档更新不需要跑测试

YAML — 路径过滤示例
on: push: paths: # 仅当这些路径有改动时触发 - 'src/**' - 'tests/**' - 'package.json' paths-ignore: # 忽略这些改动 - 'docs/**' - '*.md'

挑战 B:可复用 Workflow 🔄

当你有多个项目使用相似的 CI 配置时,可以抽取为 Reusable Workflow

YAML — reusable-ci.yml
# .github/workflows/reusable-ci.yml name: Reusable CI on: workflow_call: # 可被其他 Workflow 调用 inputs: node-version: type: string default: '20' secrets: NPM_TOKEN: required: true 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 test
YAML — 调用方
# 在另一个仓库中调用 jobs: ci: uses: ./.github/workflows/reusable-ci.yml with: node-version: '22' secrets: inherit # 自动传递所有 secrets

挑战 C:处理失败与通知 📢

测试失败时自动发送通知,且允许某些非关键步骤失败而不阻塞整个流水线:

YAML
steps: - name: Run linter run: npm run lint continue-on-error: true # lint 失败不阻塞后续 - name: Run tests run: npm test notify: needs: [build, test] if: failure() # 任何前置 Job 失败时执行 runs-on: ubuntu-latest steps: - name: Send notification run: | curl -X POST ${{ secrets.WEBHOOK_URL }} \ -d "Build failed: ${{ github.repository }}@${{ github.sha }}"
🎯 进阶技巧总结

concurrency: 同一分支只保留最新运行,取消旧的
concurrency: { group: ${{ github.ref }}, cancel-in-progress: true }

environment: 部署环境保护,需要人工审批
environment: production

permissions: 精细控制 GITHUB_TOKEN 的权限范围
permissions: { contents: read, packages: write }

🧪 自测小测验

10 道题检验你的学习成果,点击选项作答

📖 术语表

点击卡片展开完整定义

🎉 学习完成!

你已经掌握了 GitHub Actions Workflow 的核心知识

🔰 入门

为个人项目添加基础 CI Workflow

📦 进阶

Matrix 构建 + 缓存 + Artifacts

🚀 高级

Reusable Workflow + 自定义 Action

📚 推荐阅读:GitHub Actions 官方文档 · 官方 Starter Workflows