简介
想象一下,你正在和一个大型团队一起写书。每当有人提交新章节,你都需要检查拼写错误和情节漏洞。手动完成这些工作非常耗时。
在软件开发中,我们使用持续集成(CI)来解决这个问题。CI 会自动及早检查代码变更,通常包括安装依赖、运行测试,并在每次更新后验证项目。
其中的关键是快速反馈。与其在几天后才发现问题,不如在变更刚发生后立即发现,这样更容易修复。
正因为速度快,CI 通常是团队构建的第一层自动化。它会把每次推送都变成一次自动质量检查,从而保护主分支。
在本实验中,你将为一个简单的 Node.js 应用搭建这道安全网。你将:
- 创建一个能够执行基本数学运算的小型应用。
- 编写测试,验证数学运算是否正确。
- 配置 GitHub Actions,使其在每次推送代码时自动运行测试。
- 有意破坏代码,观察安全网如何捕获错误。
前置条件
本实验建立在上一个实验的基础上。我们将继续使用你之前创建的 github-actions-basics 仓库。
准备 Node.js 项目
首先,我们需要准备一些要测试的代码。接下来创建一个很小的 Node.js 应用。如果你不是程序员,也不用担心——我们会提供所需的全部代码。
进入项目目录。由于这是一个新的实验环境,我们需要重新下载仓库。
cd ~/project
git clone https://github.com/your-username/github-actions-basics.git
cd github-actions-basics
注意:请将 your-username 替换为你实际的 GitHub 用户名。
我们需要创建 3 个文件来模拟真实项目。这里使用 cat 命令,它可以直接从命令行快速创建包含内容的文件。
1. 「配方」(package.json)
这个文件告诉计算机项目是什么,以及项目需要哪些工具。我们会在其中声明项目依赖一个名为 jest 的测试工具。
cat > package.json << EOF
{
"name": "ci-demo",
"version": "1.0.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"jest": "^29.7.0"
}
}
EOF
2. 「食物」(index.js)
这是应用程序的实际代码。它包含一个用于计算两个数字之和的简单函数。
cat > index.js << EOF
function sum(a, b) {
return a + b;
}
module.exports = sum;
EOF
3. 「味道测试」(index.test.js)
这是自动化测试。它断言:如果把 1 和 2 相加,结果必须是 3。
cat > index.test.js << EOF
const sum = require('./index');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
EOF
文件创建完成后,需要将它们保存到 GitHub。运行标准 Git 命令上传你的工作。
git add .
git commit -m "Add Node.js project files"
git push
系统可能会要求你再次登录 GitHub。像之前一样,使用你的 Username 和 Personal Access Token(PAT)。
创建 CI 工作流
现在需要告诉我们的机器人助手如何测试这些代码。我们将在标准的 .github/workflows 文件夹中创建一个名为 ci.yml 的新工作流文件。
touch .github/workflows/ci.yml
使用 nano 编辑器打开该文件。
nano .github/workflows/ci.yml
添加以下配置。下面会解释其中新增的部分。
name: Node.js CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
这里引入了一个重要的新关键词:uses。
这是 GitHub Actions 中一种重要的使用模式。工作流通常不会手动编写每个 shell 步骤,而是组合可复用的 action,将检出代码、设置编程语言环境或上传构件等常见任务封装起来。
你可以把 uses 理解为将一项技能下载到机器人的大脑中。这样就不必从头编写复杂脚本,而是可以使用其他人创建好的 action。
- **
actions/checkout@v4**:这个标准 action 告诉机器人「下载我的代码」。没有它,机器人的工作区就是空的。 - **
actions/setup-node@v3**:这个 action 会在运行器上安装 Node.js。我们还传入了具体版本(16),以确保环境一致。
保存并退出编辑器(Ctrl+X、Y、Enter)。
添加安装和测试步骤
现在我们已经有了代码(检出代码)和工具(Node.js),接下来需要实际运行测试。
在 Node.js 中,通常使用以下两个标准命令:
npm install:下载package.json中列出的所有依赖项(例如jest测试工具)。npm test:运行package.json中定义的测试脚本。
这两个步骤体现了 CI 的核心流程:准备环境、安装依赖,并在干净的运行器中验证代码,然后再接受这次变更。
将这些步骤添加到工作流中。再次打开 .github/workflows/ci.yml。
nano .github/workflows/ci.yml
将以下两个步骤追加到文件末尾。确保缩进与前面的步骤对齐。
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
完整文件应如下所示:
name: Node.js CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
保存并退出编辑器。
现在,将这个文件推送到 GitHub,启动你的安全网。
git add .
git commit -m "Add CI pipeline"
git push
打开 GitHub 上的仓库,然后点击 Actions 标签页。你应该会看到一个名为「Node.js CI」的新工作流正在运行。运行完成后,你会看到一个绿色对勾。这表示代码运行正常!

破坏构建
只有在你跌倒时能够接住你,安全网才有用。现在有意「破坏」代码,观察 CI 系统如何工作。
我们将编辑测试文件,让它故意做出错误断言:声称 1 + 2 应该等于 4。
使用 nano 打开 index.test.js。
nano index.test.js
将测试期望值从 3 改为 4。
const sum = require("./index");
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(4); // CHANGED 3 to 4
});
保存并退出。现在提交并推送这个「错误」。
git add .
git commit -m "Intentionally break the test"
git push
立即切回 GitHub 上的 Actions 标签页,查看新的工作流运行情况。
很快,这次运行应该会失败。你会在提交旁边看到一个红色 X 图标。这表示 CI 系统正在发出警告:「停止!出现问题了!」
点击失败的运行记录,然后点击 build 作业。展开 Run tests 步骤,查看错误日志:
Error: expect(received).toBe(expected) // Object.is equality
Expected: 4
Received: 3
这个简单的红色 X 能够在错误刚发生时捕获问题,而不是等到几天或几周后才发现,从而为开发人员节省大量时间。

总结
在本实验中,你创建了一个达到专业水平的持续集成流水线。
你学习了:
- 如何使用
package.json定义项目「配方」。 - 如何使用
uses关键词安装actions/checkout和actions/setup-node等强大工具。 - 如何自动运行测试,让机器人验证每次代码变更。
- 「红色 X」如何作为代码的安全网。
接下来,我们将学习如何把能够正常运行的代码打包起来,让全世界都能看到!



