CI/CD 与 GitHub Actions 入门

前言

JD 里常见"熟悉 CI/CD"、"了解 GitHub Actions"。CI/CD 说的是一套工程做法:代码提交后,用脚本自动做检查、测试、部署,减少漏步骤等问题。

GitHub Actions 是 GitHub 提供的实现工具, 在仓库里放一份 YAML 配置,由 GitHub 在云端执行环境上按配置跑命令。


一、CI/CD 在解决什么问题

1.1 一次正常发布要经过哪些环节

以前端项目为例,从改代码到用户能打开新版本,通常要经过:

  1. 本地跑测试、lint,确认改动没有明显问题
  2. git push,把 commit 推到 GitHub 远程仓库
  3. 与主分支合并(多人协作时通过 Pull Request)
  4. 构建,例如 npm run build 生成 dist/
  5. 把产物部署到服务器或 Vercel、GitHub Pages 等平台

这些步骤每次发布都要做一遍 。CI/CD 要做的就是:把能写成脚本的步骤固定下来,在指定时机(例如每次 push、每次 PR)自动执行

1.2 CI:Continuous Integration(持续集成)

先拆两个词。

集成(Integration)

在软件工程里指:把你的改动和仓库里已有代码合并成一个整体,并确认这个整体能构建、能跑测试。多人协作时,你改的是模块 A,同事改的是模块 B,集成就是验证 A 和 B 合在一起仍然正常。

持续(Continuous)

每次 向主开发分支合入改动(push 或 merge 到 main),都跑一遍集成验证,而不是积累很多天、很多 PR 再一次合并。单次合并的变更越小,冲突越少,出问题也更容易定位是哪一次 commit 引入的。CI 选的是高频集成,用自动化换更低的合并风险。

CI 在自动化环境里通常做什么

下面这些是常见步骤,都在云端执行机(Runner)上跑:

  • 安装依赖(npm ci
  • 静态检查(npm run lint、类型检查)
  • 测试(npm test
  • 构建(npm run build,确认能编过)

1.3 CD:Continuous Delivery / Deployment(持续交付 / 持续部署)

CI 通过之后,代码在逻辑上已经可发布。CD 负责把构建产物放到用户能访问的环境(测试服、预发、生产)。

两个英文词经常混用,区别如下:

  • Continuous Delivery(持续交付): 构建和发布准备自动化,但上生产可能还要人工点确认
  • Continuous Deployment(持续部署): CI 通过后自动部署,没有人工审批环节。

很多团队对生产环境保留人工卡点,测试环境则全自动。下文里的 CD 泛指CI 之后的部署环节,不严格区分这两个词。

CD 要回答的问题:已经验证过的版本,如何稳定、重复地到达目标环境。

1.4 和工具的关系

CI/CD 是目标GitHub Actions、GitLab CI、Jenkins 等是实现手段。阶段划分在各工具里大同小异:装依赖 → 检查 → 测试 → 构建 → 部署,差别主要在配置文件写法。

仓库在 GitHub 上时,用 GitHub Actions 最省事:配置放在仓库里,和代码一起版本管理。本文后面都用 Actions 举例。


二、代码提交后,谁在什么地方执行这些命令

理解这一节,后面所有配置才看得懂。很多人第一次学 CI/CD 会卡在这里:「拉代码」到底是谁在拉、拉的是什么。

2.1 Runner

Runner(执行机):GitHub Actions 为每次 Job 分配的执行环境;托管 Runner 通常是临时虚拟机;CI 里的 npm test 等命令在这里执行

GitHub 收到 push,读仓库里的 workflow 配置,在 Runner 上把命令跑一遍。

可以把它理解成:用 GitHub 托管 Runner 时,相当于借你一台用完就还的 Linux 环境,专门用来验证这次提交。

2.2 workflow 里的 "拉代码" 到底是什么

配置文件里几乎总有一步:

yaml 复制代码
- uses: actions/checkout@v6

这不是你在本地 git pull,而是 Runner 从 GitHub 远程仓库克隆代码

一次 push 触发 CI 时,过程大致是:

  1. GitHub 给这个 Job 分配一台空的 Runner
  2. actions/checkout 从 GitHub 下载本次触发所对应的那一个 commit 的文件,写到 Runner 的磁盘上
  3. 后面的 npm cinpm test 都在 Runner 上、针对这份代码执行

2.3 Runner 用完就销毁

Job 结束后 Runner 被回收,上面的代码、node_modules、构建产物都会清掉。因此:

  • 不能指望上一次 CI 装好的依赖留给下一次(除非用缓存,见第六节)
  • 不能 把 Runner 当生产服务器;用户访问的网站要部署到 Vercel、自己的云主机等长期在线的环境

三、GitHub Actions 怎么知道要跑、跑什么

3.1 配置文件放哪

GitHub 只认仓库里的固定路径:

markdown 复制代码
项目根目录/
└── .github/
    └── workflows/
        └── ci.yml

文件必须push 到 GitHub才生效。

3.2 从 push 到跑命令的完整链路

perl 复制代码
你在本机 git push
    → GitHub 更新远程分支,并产生「push 事件」
    → Actions 读取该 commit 里的 .github/workflows/*.yml
    → 看 on: 是否匹配(例如:是否是 push 到 main)
    → 匹配则创建一次 Workflow Run,为每个 Job 分配 Runner
    → 每个 Job 内按 steps 顺序:checkout → 装 Node → npm ci → npm test ...
    → 成功或失败写回 GitHub(Actions 页、PR 上的检查项)
    → Runner 释放

有些外部 CI(例如自建 Jenkins)需要你在 GitHub 的 Webhooks 里填一个 URL:push 时 GitHub 再通知那台外部服务器去干活。GitHub Actions 是 GitHub 内置 功能:你 push 时,GitHub 在接收 push、更新仓库的过程中就会触发 Actions 去读 workflow。只要 push 成功,且仓库里已有 .github/workflows/ 下的 yml,就会按 on: 规则跑起来。

3.3 配置文件的三层结构

一个 YAML 文件是一个 Workflow 。里面有一个或多个 Job ;每个 Job 在一台 Runner 上跑,包含多个 Step

bash 复制代码
Workflow(整个 ci.yml)
  └── Job(例如 test、deploy)
        └── Step(例如 checkout、npm test)
关键字 管什么
on: 什么情况下触发(push、PR、定时等)
jobs: 有哪些任务块
steps: 每个任务里具体执行什么

多个 Job 默认并行 (各占一台 Runner)。如果要求 B 在 A 成功之后 才跑,写 needs: A。A 失败时,依赖它的 B 默认会被跳过(skipped)。


四、usesrun:Step 里两种写法

run: --- 在 Runner 的 shell 里执行你写的命令,和在本机终端里敲一样:

yaml 复制代码
- run: npm ci
- run: npm test

uses: --- 调用写好的 Action,省得每个项目自己写 clone、装 Node 的脚本:

yaml 复制代码
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
  with:
    node-version: '20'

项目自己的测试、构建用 run;拉代码、装运行时这类通用操作用 uses


五、示例:Vue 项目的 CI 配置

假设 Vue 3 + Vite 项目,有 package.jsonpackage-lock.json,主分支叫 main

5.1 一份可以直接用的配置

yaml 复制代码
name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Set up Node
        uses: actions/setup-node@v6
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build
        run: npm run build

5.2 配置解释

on: push / pull_request + branches: [main]

main push,或向 main 开/更新 PR 时,都会触发。

runs-on: ubuntu-latest

使用 GitHub 托管的 Ubuntu Runner(临时虚拟机)。

actions/checkout@v6

Runner 从 GitHub 检出本次触发对应的代码。@v6 是官方 Action 的主版本标签,可按官方文档升级。

actions/setup-node@v6 + node-version: '20'

在 Runner 上安装 Node.js 20。本地和 CI 的 Node 主版本不一致,是常见的「本地过、CI 挂」原因之一,所以建议在配置里写明版本。

npm ci

package-lock.json(或 npm-shrinkwrap.json)安装依赖。CI 里通常用 npm ci 而不是 npm install,结果更可复现。没有 lock 文件时 npm ci 会失败,需先生成 lock,或改用 npm install

npm run lint / npm test / npm run build

对应 package.jsonscripts 下的命令;项目里必须事先定义好这些脚本,否则 CI 会失败。

5.3 跑起来之后去哪看

push 后打开仓库的 Actions 标签页,每次运行一条记录,点进去能看到每个 Step 的完整终端输出。commit 和 PR 页面也会显示检查项是否通过。


六、常见增强:缓存、拆分 Job、部署条件

基础 CI 能跑通之后,通常会做几件事。

6.1 依赖缓存

每次 Job 用新的 Runner,默认要重新 npm ci。若 package-lock.json 没变,重复下载浪费时间。可以:

yaml 复制代码
- uses: actions/setup-node@v6
  with:
    node-version: '20'
    cache: 'npm'

GitHub 会把 npm 缓存存到 Actions Cache 。lock 文件不变时,后续 Run 的 Install 步骤会快很多。日志里出现 Cache hit 表示命中。

6.2 拆分 Job,用 needs 控制顺序

例如先跑 lint,通过后再跑 test:

yaml 复制代码
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci && npm run lint

  test:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci && npm test

needs: lint 表示 lint 成功之后 test 才开始。lint 失败时,test 默认会被标记为 skipped。

每个 Job 使用不同的 Runner ,所以每个 Job 都要各自 checkout、各自安装依赖。若再增加一个不依赖 test、只依赖 lint 的 build Job,并同样写 needs: lint,则 test 与 build 可以并行。

6.3 CD:加一个 deploy Job

CI 只验证;deploy 负责上线。典型写法:

yaml 复制代码
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci && npm run build
      # 在此接入 GitHub Pages、Vercel、SSH 等

needs: test --- 名为 test 的 Job 必须成功,deploy 才运行。若你把测试 Job 改成了别的名字,这里也要改成对应名字。

if: --- 两个条件同时满足才执行:

  • github.event_name == 'push': push 事件
  • github.ref == 'refs/heads/main':当前引用是 main 分支。

Runner 用完会销毁,构建产物要推到托管平台、镜像仓库或目标服务器。

七、Secrets 与分支保护

7.1 密钥

API Token、SSH 私钥写在仓库 Secrets 里,workflow 中引用:

yaml 复制代码
env:
  VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}

${{ secrets.XXX }} 在运行时注入;匹配到的 Secret 值在日志里会被打码。

配置入口:

sql 复制代码
仓库顶栏 Settings → Secrets and variables → Actions → New repository secret

7.2 分支保护

在仓库 Settings → Branchesmain 加规则(需要 Admin),例如:合并前必须通过 PR,且必须通过指定的 CI 检查。这样 CI 失败时无法合并,workflow 才真正起到门禁作用。


参考

相关推荐
gis开发之家1 小时前
《Vue3 从入门到大神32篇》Vue3 源码详解(二):从 GitHub Clone 到断点调试,手把手搭建源码阅读环境
vue.js·前端框架·github·vue3·vue3源码
xiezhr3 小时前
官方文档像天书?这本开源的 WorkBuddy"蓝皮书",或许更适合小白入门
ai·github·开源软件·ai agent·workbuddy
wangruofeng11 小时前
8 小时 10000 星,xAI 把内部编码 Agent 开源了:Grok Build 的架构拆解
开源·github·aigc
胡萝卜术12 小时前
RAG 的知识炼油厂:从原始网页到可检索知识块的工程化之路
面试·架构·github
GoGeekBaird12 小时前
我用 BeeWeave 跑完了一次完整写作闭环
后端·github
wangruofeng12 小时前
2026 年 7 月 GitHub 趋势观察:Skills 生态爆发,744B MoE 跑进消费级机器
github·aigc·ai编程
风向决定发型d78216 小时前
Github Copilot 新手极速上手指南
人工智能·github·copilot
qq_4523962316 小时前
第六篇:《GitLab CI 进阶:多环境部署与环境变量管理》
git·ci/cd·gitlab