知识点深化 · CI/CD
CI/CD 流水线:GitHub Actions、GitLab CI 与自动化构建测试部署
"我改完代码手动打包、手动传服务器、手动重启"——这又慢又容易忘。CI/CD 就是把这条从提交代码到上线的路全自动跑通:push 一下,自动跑测试、构建镜像、部署。这一页带你读懂 workflow YAML,亲手写一条能跑的 GitHub Actions 流水线。
① 小白第一课怎么学(4 步走,约 80 分钟)
先搞懂"为什么要有流水线",再看 YAML 怎么写。
1理解痛点(15 分钟)
读②③:手动部署的三大痛——不一致、漏步骤、不敢上线。CI/CD 把流程固化。
2看懂一个现成 workflow(20 分钟)
读④:GitHub Actions 的 on/jobs/steps 三层结构。
3写一条自己的流水线(30 分钟)
跟着⑤写"push 后自动装依赖、跑测试"。
4排错+刷题(15 分钟)
读⑥常见 YAML/缓存/密钥坑,做⑦⑩。
本课小目标学完你要能:① 说清 CI 和 CD 各解决什么;② 读懂 on/jobs/steps 结构;③ 写一条"push 即跑测试"的 workflow;④ 知道 secrets 怎么用、缓存怎么配。
② 一图看懂:CI/CD 流水线全景
读法:代码 push → 触发流水线 → CI 阶段装依赖跑测试 → 通过后构建产物(镜像)→ CD 阶段部署。任何一步失败就停下、通知人。
③ 本质直觉:把"部署 SOP"写成代码
以前部署靠"口口相传的 SOP":先 pull 代码、再 pip install、跑测试、build 镜像、ssh 到服务器 docker compose up。人一多就有人漏步、有人环境不一样。
CI/CD 的本质:把这套 SOP 写成一份 YAML 代码,放进仓库。以后每次 push,系统自动开一台干净机器、严格按 YAML 一步步执行。人人一致、每次一致、永不漏步。
CI(持续集成):每次合并代码就自动构建+跑测试。目的是"尽早发现破坏"——别让 bug 攒到发布日。测试不过就不让合并。
CD(持续交付/部署):测试通过后,自动把产物部署到测试/生产环境。持续交付是"可一键发布",持续部署是"全自动发布"。
为什么要"干净环境"跑每次流水线都用全新虚拟机,不依赖你本地装了啥。这样测试结果可信——你本地过不代表别人环境过,干净环境过才是真过。
④ 完整体系:GitHub Actions 结构与示例
三层结构(背下来)
| 层级 | 是什么 | 例子 |
on | 什么时候触发 | push 到 main、开 PR、打 tag、定时 |
jobs | 要做哪几件事(可并行) | test、build-and-push、deploy |
steps | 一个 job 里一步步命令 | checkout → setup-node → npm ci → npm test |
一条完整的 workflow(.github/workflows/ci.yml)
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
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 lint
- run: npm test # 跑测试,失败则 job 红
build-and-push:
needs: test # 等 test 通过才跑
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: myorg/myapp:${{ github.sha }}
GitHub Actions 关键概念
| 概念 | 说明 |
runs-on | 在什么机器上跑,ubuntu-latest 最常用 |
uses | 复用官方/社区 action(checkout、setup-xxx) |
run | 直接执行 shell 命令 |
needs | job 依赖,等前置 job 成功才跑 |
secrets.XXX | 加密密钥,存在仓库 Settings,不能明文写 |
${{ github.sha }} | 内置变量,当前提交哈希 |
GitLab CI 对照(.gitlab-ci.yml)
stages: [test, build, deploy]
test:
stage: test
image: node:20
script:
- npm ci
- npm test
build:
stage: build
script: docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
only: [main]
GitLab 用 stages 阶段 + script 脚本,变量是 $CI_*。思路和 Actions 一样,只是写法不同。
⑤ 用法场景与典型例题
例1(基础·写测试流水线)给一个 Node 项目,要求 push 到 main 就自动 npm ci 并跑 npm test
on 触发 + 一个 test job,四步走。
① on: push: branches:[main]。
② job runs-on: ubuntu-latest。
③ steps:checkout → setup-node → npm ci → npm test。
④ npm test 非零退出码会让整个 job 标红,PR 显示失败。
解析:关键是 npm ci(按 lock 文件精确装)而不是 npm install,保证可重复。
例2(阶段依赖)希望"测试通过后才构建镜像",怎么配?
用 needs 字段串起来。
① test job 先跑。
② build-and-push job 里写 needs: test。
③ test 失败 → needs 它的 job 自动跳过,不会构建坏镜像。
答案:needs 表达"上游成功才执行",实现流水线阶段串联。
例3(密钥安全)要在流水线里登录 Docker Hub,能把密码写进 YAML 吗?
绝对不能明文,要用 secrets。
① 仓库 Settings → Secrets and variables → 新建 DOCKER_TOKEN。
② YAML 里引用 ${{ secrets.DOCKER_TOKEN }}。
③ 运行时 GitHub 自动注入,日志里显示为 ***。
答案:密钥一律走 secrets/变量,绝不进 git。明文提交密钥会被平台扫描立刻告警。
缓存提速每次 npm ci 都要重新下载依赖,慢。配 cache: 'npm'(setup-node 里)或 actions/cache,把 node_modules 缓存下来,第二次起快很多。
⑥ 高频错误诊断(4 条)
错误 1:YAML 缩进报错CI/CD 的 YAML 对缩进极其敏感,tab 和空格混用直接语法错误。一律用两个空格,层级对齐。本地先用 yamllint 或在线 YAML 校验器过一遍。
错误 2:依赖装错版本用了 npm install 而非 npm ci,每次装的小版本可能不同,导致"本地过、CI 不过"。锁文件(package-lock.json)要提交,CI 用 npm ci。
错误 3:密钥写进 YAML 或日志密码、token 明文写在 workflow 里 = 泄露。必须用 secrets;且在脚本里别 echo 变量把它打出来。
错误 4:CI 过了部署却失败CI 跑在干净 Linux,你本地可能是 macOS/Windows,路径分隔符、shell 差异、缺系统依赖都会让"CI 绿、部署崩"。部署阶段也要在和生产一致的环境验证。
⑦ 考点真题演练(4 题)
考点分布
| 考法 | 出题形式 | 应对 |
| CI vs CD | 各解决什么 | CI 自动构建测试,CD 自动部署 |
| 结构 | on/jobs/steps 关系 | 触发→作业→步骤 |
| 密钥 | 密码怎么进流水线 | secrets,不明文 |
| 依赖 | needs 的作用 | 上游成功才执行 |
真题基础1. CI(持续集成)最核心的目的是?
真题中档2. GitHub Actions workflow 里 needs: test 表示?
真题中档3. 流水线里要用到 Docker Hub 密码,正确做法是?
真题拔高4. CI 里装依赖为什么推荐 npm ci 而不是 npm install?
⑧ 必背命令/知识点卡
CI:持续集成 = 自动构建 + 自动测试 尽早抓 bug
CD:持续交付/部署 = 自动发布到环境 一键上线
三层:on(触发)→ jobs(作业)→ steps(步骤) YAML 骨架
触发:push / PR / tag / schedule on 字段
串接:needs: 上游job 成功才执行
依赖:CI 用 npm ci / pip install -r lock 可重复
铁律:密钥走 secrets,绝不明文进 git 安全红线
⑨ 应用输出:搭一条"提交即上线"流水线
场景:Node 后端,main 分支 push 后自动测试、构建镜像、部署到服务器
① 写 workflow:.github/workflows/ci.yml,on push main。
② test job:checkout、setup-node 20、npm ci、npm test。
③ build job:needs: test,docker login(用 secrets)、build-push 镜像,tag 用 github.sha。
④ deploy job:needs: build,通过 ssh 到生产服务器 docker compose pull && up -d。
⑤ 配 secrets:DOCKER_USER、DOCKER_TOKEN、SSH_KEY 存仓库 Settings。
⑥ 验证:改一行代码 push,Actions 页看到三个 job 依次绿;服务器上容器已是新版本。
口述流水线思路"push 触发,先跑测试挡坏代码,过了再构建镜像打 tag,最后 ssh 部署;密钥走 secrets,任何一步红就停并通知。"
⑩ 分层练习 15 题(基础 5 + 中档 5 + 拔高 5)
▍基础 5 题
基础1CI 和 CD 哪个是自动测试构建?
CI。CD 是自动部署/交付。
基础2workflow 文件放在哪个目录?
.github/workflows/ 下,扩展名 .yml。
基础3on 字段是干嘛的?
定义流水线何时触发(push、PR、tag、定时)。
基础4runs-on: ubuntu-latest 什么意思?
job 在 GitHub 提供的最新 Ubuntu 虚拟机上跑。
基础5steps 里 uses 和 run 的区别?
uses=复用现成 action;run=执行 shell 命令。
▍中档 5 题
中档6为什么流水线要用干净环境跑?
不依赖本地状态,保证测试结果可信、人人一致。
中档7npm test 退出码非 0 会怎样?
该 step 失败 → job 标红 → 后续 needs 它的 job 不执行。
中档8怎么只在 push 到 main 时才部署?
deploy job 加 if: github.ref == 'refs/heads/main'。
中档9actions/checkout 干嘛的?
把仓库代码拉到 Runner 机器上,后续步骤才能用到代码。
中档10缓存 node_modules 有什么用?
避免每次流水线重新下载依赖,大幅缩短运行时间。
▍拔高 5 题
拔高11PR 还没合并就想跑测试,怎么配?
on 里加 pull_request:,每个 PR 都会触发 test job,绿了才允许合并。
拔高12部署用的 SSH 私钥怎么安全传入?
存为 secret,用 webfactory/ssh-agent 之类 action 加载,绝不 echo 到日志。
拔高13要做每天凌晨跑一次的定时任务?
on 加 schedule: - cron: '0 18 * * *'(UTC,对应北京时间凌晨 2 点)。
拔高14持续交付 vs 持续部署的区别?
持续交付=随时可发布、最后一步人工点;持续部署=全自动直接上生产。
拔高15CI 跑 10 分钟太慢,怎么优化?
加依赖缓存、拆 job 并行跑、用更快的 Runner、只改相关文件才触发(path filters)。
⑪ 记忆口诀 + 7 天复习计划
三句口诀
① CI 管测试构建,CD 管自动部署。
② on 触发、jobs 作业、steps 步骤,needs 串上下游。
③ 密钥走 secrets,依赖用 lock,YAML 缩进别用 tab。
| 天 | 任务 | 自检 |
| 第 1 天 | 读②③,跑通一条测试流水线 | Actions 页变绿 |
| 第 2 天 | 背知识点卡 + 做基础 1-5 | 基础全对 |
| 第 3 天 | 给现有项目加 build-and-push job | 镜像推到仓库 |
| 第 4 天 | 做中档 6-10,配 secrets 和缓存 | 密钥不泄露 |
| 第 5 天 | 做拔高 11-15 + 真题 4 题 | 会排错会优化 |
| 第 6-7 天 | 完整搭 test→build→deploy,口述链路 | 不看资料全默对 |
← 返回 FDE 培养总览