项目 内容
这个作业属于哪个课程 课程社区
这个作业的要求在哪里 作业要求
我在这个课程的目标是 凝聚整个团队通过一定的软件开发流程,在预计时间内发布”足够好”的符合用户需求的软件,并证明其是可维护和持续发展的,并在其中做出应有的贡献,提升进行软件工程开发的能力。
这个作业在哪个具体方面帮助我实现目标 帮助我们熟悉CI/CD实践构建流程,为后续的开发提供自动化测试与集成部署的有效帮助。

[T.10] 团队项目:CI/CD实践

选择选项及选择理由

选项

我们选择了方案 A:GitHub Actions,任务选择的是自动运行测试,以单元测试为主,同时还补充了 Cypress E2E 冒烟测试。

理由

  1. 我们的项目代码已经托管在 GitHub 上,直接使用 GitHub Actions即可,不需要再额外搭建 Jenkins等其他集成框架,配置成本最低。
  2. GitHub ActionsPull Request 流程结合紧密,每次 pushPRdev分支都会自动执行测试,适合团队协作开发,也便于代码可能存在的潜在bug的及时发现。
  3. 相比 Git HooksGitHub Actions 运行环境统一、日志可追溯、结果对全队可见,更符合真正的 CI 思路。
  4. 对前端项目来说,自动测试的价值很高。它可以在代码合并前尽早发现页面结构变化、状态逻辑错误和基础交互失效,减少“本地能跑、合并后出错”的情况发生。

现有仓库中的CI配置文件的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
name: frontend-test

on:
push:
branches: [dev, test/work]
pull_request:
branches: [dev, test/work]

jobs:
test:
runs-on: ubuntu-24.04
container:
image: cypress/browsers:22.15.0
options: --user 1001
env:
CYPRESS_CACHE_FOLDER: ${{ github.workspace }}/.cache/Cypress
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: npm

- name: Cache Cypress binary
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/Cypress
key: cypress-${{ runner.os }}-${{ hashFiles('package-lock.json') }}

- name: Install dependencies
run: |
for attempt in 1 2 3; do
if npm ci --ignore-scripts; then
break
fi

if [ "$attempt" -eq 3 ]; then
exit 1
fi

rm -rf node_modules
echo "npm ci failed on attempt $attempt, retrying..."
sleep 5
done

- name: Restore build scripts
run: npm rebuild esbuild vue-demi

- name: Run unit tests
run: npm run test:unit

- name: Install Cypress binary
run: |
mkdir -p "$CYPRESS_CACHE_FOLDER"
for attempt in 1 2 3; do
if npx cypress install; then
break
fi

if [ "$attempt" -eq 3 ]; then
exit 1
fi

echo "cypress install failed on attempt $attempt, retrying..."
sleep 5
done

- name: Check Cypress binary
run: |
npx cypress cache path
npx cypress cache list

- name: Run E2E tests
run: |
Xvfb :99 -screen 0 1280x1024x24 >/tmp/xvfb.log 2>&1 &
export DISPLAY=:99
sleep 2
npm run test:e2e

实现方式及选择理由

实现方式

我们采用的是“单元测试 + E2E 冒烟测试”的实现方式。

  1. 单元测试使用 Vitest
    用来验证前端中较小粒度的逻辑和组件行为,例如:
    • userStore 的登录/退出逻辑
    • RoomCreateRoomJoin 组件的输入与按钮启用逻辑
    • 一些工具函数行为
  2. E2E 测试使用 Cypress
    用来验证页面在浏览器环境中的基本交互,例如:
    • 首页是否正常渲染
    • CREATE ROOM”“JOIN ROOM”等按钮是否可见
    • 房间输入后按钮是否按预期启用
  3. CI 运行环境选择 GitHub Actions + Cypress 官方浏览器容器。
    这样做的原因是:
    • 浏览器、Node 环境更稳定
    • 更适合运行 Cypress
    • 减少“本地能跑、CI 跑不起来”的环境差异
  4. 为了让 CI 更稳定,我们额外做了以下处理:
    • 使用 npm 缓存和 Cypress 二进制缓存,减少重复下载
    • npm cicypress install 都加了重试逻辑
    • 通过 Xvfb 提供虚拟显示环境,支持 headless 图形测试
    • test:e2e 中先 buildpreview,使测试更接近生产环境

分支范围、触发条件、执行动作

当前实际配置如下:

  1. 分支范围:

    • dev
    • test/work
  2. 触发条件:

    • push
    • pull_request
  3. 执行动作:

    • 检出代码 actions/checkout
    • 配置 Node.js 环境
    • 安装依赖 npm ci
    • 恢复构建脚本依赖
    • 运行单元测试 npm run test:unit
    • 安装并检查 Cypress 二进制
    • 启动虚拟显示环境
    • 运行 E2E 测试 npm run test:e2e

因此,这套流程本质上是:提交代码后自动验证前端测试是否通过。

触发结果

image