Lesson 0006:CI/CD——代码 push,剩下的交给机器

DevOps 四大支柱的第二根:CI/CD(持续集成 / 持续交付)。前几课你学了命令行、Git、脚本、Docker——CI/CD 就是把这些串成一条自动流水线

从现在起,你 push 代码,GitHub 自动帮你做这些事:

git push ──→ 自动跑 lint ──→ 自动跑测试 ──→ 自动构建 Docker 镜像 ──→ 自动部署
               ↓ 失败?                                       ↓ 成功?
           PR 上直接标红,                                  合并后自动上线
           merge 按钮灰掉

GitHub Actions 三要素

GitHub Actions 是最流行的免费 CI/CD 平台,直接内建在 GitHub 里。它的工作方式:

概念是什么类比
Workflow(工作流)一个 YAML 文件,定义整条流水线Shell 脚本的高级版
Job(任务)流水线的一个独立执行单元脚本里的一个函数
Step(步骤)Job 里的一个具体操作函数里的一行命令
Runner(执行器)跑 Workflow 的虚拟机(Ubuntu/macOS/Windows)临时租的一台云服务器
Action(动作)可复用的步骤,社区共享npm 包

你的第一个 Workflow

把它放在 .github/workflows/ci.yml,push 到 GitHub 就自动运行。

name: CI                          # Workflow 的名字(在 GitHub UI 显示)

on:                               # 什么时候触发
  push:
    branches: [main]              # push 到 main 时
  pull_request:
    branches: [main]              # 向 main 发 PR 时

jobs:                             # 要跑哪些任务
  test:                           # 任务名(自定义)
    runs-on: ubuntu-latest        # 在什么系统上跑
    steps:                        # 任务里的步骤
      - uses: actions/checkout@v4    # Step 1: 拉代码(官方 Action)
      
      - uses: actions/setup-node@v4  # Step 2: 装 Node.js
        with:
          node-version: 22
          cache: 'npm'               # 自动缓存 node_modules
      
      - run: npm ci                  # Step 3: 装依赖
      - run: npm run lint --if-present  # Step 4: lint(有的话)
      - run: npm test --if-present   # Step 5: 跑测试

拆解:

--if-present 是什么意思?如果 package.json 里没有 lint/test script,不会报错。防止 workflow 因为缺脚本而失败。

扩建成完整的 CI/CD

加上 Docker 构建和推送(需要先在 GitHub 上设置 Secrets):

name: CI + Docker

on:
  push:
    branches: [main]
    tags: ['v*']                  # v1.0.0 这种 tag push 时也触发

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22, cache: 'npm' }
      - run: npm ci
      - run: npm test

  docker:
    needs: test                   # 等 test job 通过了才跑这个
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}   # 从 GitHub Secrets 读取
          password: ${{ secrets.DOCKER_TOKEN }}
      
      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: myuser/my-app:latest

关键点:

常用触发器一览

on:
  push:                              # 代码 push
  pull_request:                      # 发 PR
  schedule:
    - cron: '0 2 * * 1'             # 每周一凌晨 2 点(UTC)
  workflow_dispatch:                 # 允许手动触发(GitHub UI 上点按钮)

Secrets 怎么设置

在 GitHub 仓库页面 → Settings → Secrets and variables → Actions → New repository secret。把敏感信息(Docker Hub 密码、SSH 私钥、API token)存在这,workflow 里用 ${{ secrets.NAME }} 读取。

Secrets 值在 workflow 日志中会被自动替换为 ***。但如果你在脚本里 echo $SECRET,它会被隐藏;如果你 echo $SECRET | base64,base64 编码后的值不会被隐藏——所以别把 secret 做任何转换再输出。

动手练习:给你的 podcast 项目写 CI

目标:~/code/podcast 创建 GitHub Actions workflow。

# 1. 创建 workflow 目录
mkdir -p ~/code/podcast/.github/workflows

# 2. 创建 ci.yml
cat > ~/code/podcast/.github/workflows/ci.yml << 'EOF'
name: CI

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

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: 'npm'
      
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test --if-present
EOF

# 3. 验证 YAML 语法(可以装个 yamllint)
cat ~/code/podcast/.github/workflows/ci.yml

# 4. (可选)push 到 GitHub 看它跑起来
# cd ~/code/podcast && git add .github && git commit -m "ci: add GitHub Actions" && git push

运行结果:每次 push 到 main,GitHub 会:拉代码 → 装 Node 22 → npm ci → npm run build → npm test。全部通过就在 commit 旁边显示绿色 ✓。

小测验

Q1:GitHub Actions workflow 文件放在哪个目录?
Q2:needs: test 的作用是什么?
Q3:敏感信息(如 Docker Hub 密码)应该存在哪?
Q4:runs-on: ubuntu-latest 是什么意思?

推荐资源

下一步

你的 CI/CD 流水线跑起来了。但代码最终要部署到服务器上。下一课——部署实战:从 Docker 镜像到公网可访问,你将在云服务器上把你的容器真正跑起来。

如果你没有 GitHub 仓库?建议现在就把 ~/code/podcast 推上去试试。没有 GitHub 账户也可以只把 workflow 文件写好,理解结构就行。workflow 的 YAML 本身不依赖 GitHub——GitLab CI、Bitbucket Pipelines 的语法非常相似。
← Lesson 0005 · 术语表 · Mission