GitHub 给我们每人每月 2000 分钟的 Actions 免费额度,可以用来跑 CI,不好好利用就太浪费了。正好最近想学学 Cypress,于是就拿前面说的 mywordle.org 项目练手,加上了自动化 Lighthouse+Cypress。下面主要分享过程,希望对大家有帮助。
0. 开启 GitHub Action 并完成 hello world
点击项目里的 Actions 选项卡,如果该项目之前没有 workflow,就会自动进入创建 workflow 的界面。
建议直接选择 node.js 模版,可以节省很多配置成本。因为免费额度只有 2000分钟/月,所以我建议只保留一个 node.js 版本;又因为我要用 pnpm 管理依赖,所以改造后的配置是这样的:
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v2
- uses: pnpm/action-setup@v2.2.1
with:
version: 6.32.2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: pnpm i
- run: npm run build --if-present
这个阶段我只需要确保代码可以完成构建就行了,没有运行更多脚本。
1. 使用 Lighthouse 校验 CLS
Lighthouse 是 Google 提供的网页评价工具,可以对网页的众多指标进行打分,帮助我们提升网页的运行效率和用户体验。CLS=Cumulative Layout Shift,即页面初始化阶段,布局变化的统计值,变化越多值就越大,页面抖动越厉害,评分就越低。
据说这个值很影响 Google 对页面的评价,所以我们必须时时关注。
首先,使用 pnpm 安装 Lighthouse:pnpm i lighthouse -D
。
我们还需要静态服务器提供网页服务。如果你仔细看前面的配置文件,会发现这个环境基于 Ubuntu 搭建。在配置里增加一行 - run: nginx -v
,确认镜像里集成了 nginx 1.18,那就好办了,添加 mime.types 和 nginx 配置文件:
pid logs/travis.nginx.pid;
events {
accept_mutex off;
}
http {
server {
access_log logs/travis.access.log;
error_log logs/travis.error.log warn;
listen 9000;
include mime.types;
location / {
alias dist/;
# 下面这行是 SPA 的关键
try_files $uri $uri/ /index.php$args;
}
}
}
放到 workflow 里跑一下,报错了:
Run nginx -c conf/travis.conf -p `pwd`
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2022/03/18 09:38:08 [emerg] 1870#1870: open() "/var/log/nginx/access.log" failed (13: Permission denied)
Error: Process completed with exit code 1.
因为 Nginx 一定要把全局错误日志放在 /var/log/nginx/error.log
,而又没有权限,所以报错。解决方案有两个:
- 升级到 nginx 1.19,便可以使用
-e
参数自定义全局错误日志的路径。不过这意味着我们每次都必须更新镜像,毫无疑问会浪费宝贵的免费额度。基本放弃。 - 确保 nginx 可以操作这个文件,这可能需要 root 权限。
在配置文件里随便加一行 sudo touch /var/log/nginx/error.log
,顺利完成,说明我们拥有 root 权限。于是加入以下配置,完成 nginx 配置:
- run: sudo chmod -R 755 /var/log/nginx
- run: sudo touch /var/log/nginx/error.log
- run: sudo chmod 777 /var/log/nginx/error.log
- run: nginx -c conf/travis.conf -p `pwd`
接下来就简单了,使用下面的命令可以调用 Lighthouse 给网页打分,并且将数据输出到 lighthouse.json
,然后我们写个脚本分析即可:
lighthouse --chrome-flags="--headless --disable-gpu --no-sandbox" --output json --output-path=lighthouse.json http://localhost:9000
2. Cypress
接下来搞 Cypress,时间因素我就不详细介绍 Cypress 的用法了,他们官网有很详细的视频,虽然是英文的,不过我觉得大概也看得懂。建议大家先看一下,了解个大概:Installing Cypress | Cypress Documentation。
这次我打算添加两个测试:过关,和失败。
尝试 Cypress 的过程并不顺利,主要原因是 Cypress 的语法设计有点难懂。比如下面两行代码:
cy.visit('http://localhost:9000/');
cy.get('#header').should('contain', 'Wordle Unlimited');
看起来它要完成两步操作,其实不然。Cypress 只是暂时把这两步操作存入操作队列,未来满足某个条件才会执行。所以,我们不能将其它操作插入这些步骤中间。比如我的游戏数据存在 localStroage 里,我希望在网页打开后校验这些数据,于是我就后面读取 localStorage,但怎么也读不到。正确的做法是在第二句的后面用 .then(() => {})
,然后把操作放在里面。
哦,对了,基于同样的原因,Cypress 的测试函数也不能是 Async Function。
不知道如果将来需要做条件判断或者循环的话,应该怎么写。
接下来,只要配置对应的 action 即可。我选择使用官方的 cypress-io/github-action@v2,虽然我也不知道它比自己写多了些什么,不过我觉得能省事总是好的。需要注意的是,因为我使用了 pnpm,所以我不需要官方配置里的 install
步骤。
3. 使用环境变量
有时候,我们的项目依赖一些第三方工具,这就需要我们能够在构建或测试的时候配置第三方工具的鉴权方式,比如 access_key,secret_key 之类的东西。很显然,我们不能把这些鉴权信息入库。(实际上,随便搜一搜,能找到大量这么做的代码。)所以我们需要用别的方式来配置这些信息。
最常见的做法是环境变量。比如我们配置一个 WX_PAY_PRIVATE_KEY
,然后我们就可以在代码中使用 process.env.WX_PAY_PRIVATE_KEY
。GitHub Actions 可以使用 env:
配置环境变量,但是这些变量一样不适合入库,所以我们需要配置安全信息。
配置位于上图所示的地方,添加完之后,就可以在配置文件中使用:
- name: 步骤
env:
AIRTABLE_API_KEY: ${{ secrets.AIRTABLE_API_KEY }}
run: 命令
4. 完整配置文件
name: Node.js CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v2
- uses: pnpm/action-setup@v2.2.1
with:
version: 6.32.2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
# setup local server
- run: pnpm i
- name: build repo
env:
AIRTABLE_API_KEY: ${{ secrets.AIRTABLE_API_KEY }}
run: npm run build --if-present
- run: mkdir logs
- run: sudo chmod -R 755 /var/log/nginx
- run: sudo touch /var/log/nginx/error.log
- run: sudo chmod 777 /var/log/nginx/error.log
- run: nginx -c conf/travis.conf -p `pwd`
# run lighthouse
- run: pnpm add lighthouse -g
- run: lighthouse --chrome-flags="--headless --disable-gpu --no-sandbox" --output json --output-path=lighthouse.json http://localhost:9000
- run: node tools/lighthouse.js
- name: Cypress run
uses: cypress-io/github-action@v2
with:
install: false
贴上完整配置,供各位参考。
5. 总结
实际体验下来,大约花了 60 分钟,每次运行大约两分半钟,看起来一个月 2000 分钟额度还是蛮充足的。
建议大家都学习一下,CI/CD 是现代化开发的基础设施,可以大大提升我们的开发效率。Lighthouse 是非常重要的网站评价工具,Cypress 可能是现在最好的 UI e2e 测试工具,结合这几个工具可以保障我们的网站始终可用,始终好用。
如果你看过我的上一篇文章《在 Code.fun 做 Code Review》,其实偿还技术债最好的办法就是写自动化测试,因为只有自动化测试才能告诉你重构有没有引入新问题、能不能上线,优化有没有成功;以及,能否推进下一步重构与优化。
欢迎吐槽,共同进步