背景(PLAN-v0.7.5.md 根因 5):项目声称的崩溃语义一直没有被真实验证。
e2e 里的 `crashPage()` 实际是:
win.__ms = null; await page.close();
—— 那是**优雅关闭**:没有未完成 I/O、不经过任何崩溃窗口。于是
`checkpointInterval: 999999999` + 不 close 的"崩溃恢复"用例,测的其实是
"正常关闭后重开"。CI 注释却写着"e2e 覆盖真实崩溃注入(CDP Page.crash)"。
改动:
1. `crashPage()` 改用 CDP `Page.crash` 终止渲染进程(进行中的 OPFS 写入、
未 flush 的缓冲、同步句柄全部立即消失)。实测要点:
- `Page.crash` 之后 `page.isClosed()` 仍为 false,不能用它判成败;
- OPFS 数据**在同一个 context 内**跨崩溃保留(新建 context 是另一份存储),
因此崩溃后新开页面即可继续验证。
2. harness 增加两类真崩溃注入:
- `insertNoAwait`:发起写入但不等待(`page.evaluate` 会等 Promise,
因此"写到一半就崩"无法用普通 await 表达);
- `armCrashOnOpfsWrite({ phase })`:包装 `FileSystemWritableFileStream`
的 `write`/`close`,在第 n 次调用处进入死循环,随后被 Page.crash 杀掉 ——
对应 copy-on-write 的两个真实窗口。**注**:OPFS 用的是 createWritable,
不是 `FileSystemSyncAccessHandle`(后者主线程不可用,实测)。
3. 新增两个用例覆盖上述窗口,并断言钩子**确实装上**(armed === true),
避免"注入了但没走到"的假绿:
- write 阶段崩溃 → 已确认数据完好;
- commit 阶段崩溃 → 3 条旧数据**完全不变**(copy-on-write 的核心不变量:
未 commit 就崩溃不能出现半个文件)。
4. 原"写入后强制终止"用例加逐条抽查(0/1/24/25/49)—— 只断言计数会被
"重复主键覆盖后计数恰好相等"蒙对。
5. CI 注释改为准确描述实际覆盖的窗口,并点明 e2e 依赖 dist/ 产物。
验证:14 项 e2e 全绿(8.9s,真实 Chromium + 真实 OPFS);
jest 全量 85 套件 / 1665 测试通过。
112 lines
5.0 KiB
YAML
112 lines
5.0 KiB
YAML
name: CI
|
||
|
||
on:
|
||
push:
|
||
branches: [master]
|
||
pull_request:
|
||
branches: [master]
|
||
|
||
jobs:
|
||
test:
|
||
runs-on: debian-latest
|
||
|
||
strategy:
|
||
matrix:
|
||
node-version: [18.x, 20.x, 22.x, 24.x]
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Use Node.js ${{ matrix.node-version }}
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ matrix.node-version }}
|
||
# v0.7.2-fix: 不用 cache —— Gitea act runner 对 setup-node 的 npm 缓存
|
||
# post 步骤(cache-save tar 打包)支持不完善,矩阵 job 并行时打包失败
|
||
# 会把整个 job 标红(即便 Run tests 已通过)。npm ci 每次 1~2 分钟可接受。
|
||
|
||
- name: Install dependencies
|
||
run: npm ci
|
||
|
||
# v0.8.0: 源码类型检查
|
||
- name: Type check (src)
|
||
run: npm run typecheck
|
||
|
||
# v0.8.0 新增:**测试代码**类型检查。
|
||
# 此前 tests/ 既不在 tsconfig include 中,babel-jest 又只剥离类型不做检查,
|
||
# 于是测试里的类型错误、拼写错误、未 await 的断言全部不可见
|
||
# (审计实例:v025-fixes 里标题写 indexeddb、实际传 'opfs' 的用例长期存活)。
|
||
- name: Type check (tests)
|
||
run: npm run typecheck:tests
|
||
|
||
# v0.8.0: lint 不再 continue-on-error —— 此前 lint 失败永远不让 CI 变红,
|
||
# 形同虚设。现在 src 与 tests 都纳入,0 error 才通过。
|
||
- name: Lint
|
||
run: npm run lint
|
||
|
||
# v0.7.2: Run tests 拆两步 —— 常规套件并行(快),重型套件串行(runInBand)。
|
||
# 此前重型测试(10 万行 kv/opfs、生产矩阵)与常规套件在慢 runner 上并行
|
||
# 争抢 CPU 与 4GB 堆 → 单测超时(120~180s)与 OOM 类假失败。
|
||
#
|
||
# v0.8.0: 常规套件**带覆盖率**运行(此前 CI 从不跑 --coverage,且 jest.config
|
||
# 没有任何 coverageThreshold → 覆盖率掉到 0% 也全绿)。阈值定义在 jest.config.cjs。
|
||
- name: Run tests (regular suites, with coverage gate)
|
||
run: npx jest --coverage --forceExit --maxWorkers=1 --no-cache --testPathIgnorePatterns='/node_modules/|/tests/e2e/|aria-prod-load|kvstore-stress|aria-matrix-audit|aria-idx-flush-race'
|
||
env:
|
||
NODE_OPTIONS: --max-old-space-size=4096
|
||
|
||
# v0.7.3-ci: 重型套件只在单一 Node 版本(20.x LTS)跑一次 ——
|
||
# 压力测试验证存储正确性/性能护栏,不依赖 Node 版本差异;
|
||
# 4 个矩阵 job 并行时重型套件各占 ~1.2GB RSS(实测),
|
||
# 4G 内存 runner 上 4 份并行必被 OOM killer 杀掉(exit 137)。
|
||
- name: Run tests (heavy suites, serial)
|
||
if: matrix.node-version == '20.x'
|
||
run: npx jest --forceExit --runInBand --no-cache tests/engine/aria-prod-load.test.ts tests/engine/kvstore-stress.test.ts tests/engine/aria-matrix-audit.test.ts tests/engine/aria-idx-flush-race.test.ts
|
||
env:
|
||
NODE_OPTIONS: --max-old-space-size=4096
|
||
|
||
- name: Build
|
||
run: npm run build
|
||
|
||
# v0.8.0: 校验仓库内 dist/ 与源码同步。
|
||
# 此前 dist/ 已提交入库(42 个提交都在改 dist),但 CI 只 build 到工作区、
|
||
# 不校验是否与源码一致 → 发布产物可以静默落后于源码。
|
||
# 仅在单一 Node 版本上校验(构建结果与 Node 版本无关)。
|
||
- name: Verify dist is in sync with src
|
||
if: matrix.node-version == '20.x'
|
||
run: |
|
||
if ! git diff --quiet -- dist/; then
|
||
echo "::error::dist/ 与源码不同步。请在本地运行 npm run build 并提交 dist/。"
|
||
git diff --stat -- dist/
|
||
exit 1
|
||
fi
|
||
echo "dist/ 与源码同步 ✓"
|
||
|
||
e2e:
|
||
runs-on: debian-latest
|
||
# 与 MetonaEditor 一致:Playwright 官方镜像(自带 Chromium 与全部系统依赖),
|
||
# 避免 runner 宿主(Debian 11)不被 Playwright 1.62 支持的问题
|
||
container: mcr.microsoft.com/playwright:v1.62.1-noble
|
||
timeout-minutes: 20
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- name: Use Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: 22.x
|
||
# v0.7.2-fix: 同上,e2e job 也不用 npm 缓存(cache-save post 失败风险)
|
||
- name: Install dependencies
|
||
run: npm ci
|
||
- name: Build
|
||
run: npm run build
|
||
- name: Verify Playwright browsers
|
||
run: npx playwright install chromium
|
||
# v0.8.0(PC-2): e2e 用 CDP `Page.crash` **真崩溃**注入,覆盖三类窗口:
|
||
# ① 写入进行中崩溃(不等 Promise)② OPFS createWritable 的 write 阶段
|
||
# ③ 提交(close/原子替换)阶段;另含 checkpoint 前后、KVStore WAL 半写、
|
||
# 多标签页锁、加密往返、页面化 + 二级索引、repair 自愈。
|
||
# 注意:e2e 依赖 dist/ 产物(harness.html 加载 /dist/metona-sqlark.js),
|
||
# 因此上面的 Build 步骤是必需的;主 job 会校验 dist 与源码同步。
|
||
- name: Run E2E tests
|
||
run: npm run test:e2e
|