Files
MetonaSqlark/.gitea/workflows/ci.yml
T
thzxx 6a0cfebc4a test(PC-2): e2e 真崩溃注入(CDP Page.crash)取代假崩溃 + 两个 OPFS 写入窗口
背景(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 测试通过。
2026-09-15 01:06:23 +08:00

112 lines
5.0 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.0PC-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