etherpad-lite/.github
John McLear 8dbd917718
test(ci): kill Windows + Node 24 backend-test flake; capture native crashes (#7748)
* test(ci): kill Windows + Node 24 backend-test flake; capture native crashes

The Backend tests suite has a ~22% silent-failure rate on Windows + Node
24 specifically (Linux 22/24/25 ✓, Windows 22/25 ✓). Two prior PRs
instrumented the failure — common.ts handlers (#7663), then an unconditional
diagnostics.ts (#7665) — and confirmed it's a hard kill:
diagnostics.ts:23-27 documents the matrix, and every recurrence (run
25279692065, 25754938013, 25906496503) shows only `[diag +0ms]
diagnostics loaded`, no beforeExit / exit / unhandledRejection /
uncaughtException / signal handlers. Process dies 700–900 ms after the
last passing test, in a varying spec each time. That's a native crash in
V8 / libuv / the tsx loader, not anything reachable from JS.

This PR ships two independent attacks at the failure:

1. Mitigation — add --exit to the mocha command in src/package.json.
   Mocha's default (--exit=false) waits for the event loop to drain
   after tests complete. The hard kill happens during that drain or the
   inter-spec transition. With --exit, mocha calls process.exit(failures)
   directly once the run finishes, closing the cleanup-race window.
   Linux/Windows-22/25 are green today, so the natural-drain path is
   not surfacing real leaks worth preserving. Verified locally:
     `cd src && pnpm test` -> 1121 passing, 0 failing, 23s.

2. Capture — set NODE_OPTIONS in each Backend tests step to
   --report-on-fatalerror, --report-uncaught-exception,
   --report-on-signal, --report-compact, plus
   --report-directory=${{ github.workspace }}/node-report. If Node
   crashes at the C++ level (segfault, V8 abort, libuv panic) the
   runtime writes a JSON diagnostic report with the V8 stack, libuv
   handle table, JS heap state, and OS info. A new "Upload Node
   diagnostic reports on failure" step (actions/upload-artifact@v7,
   `if: failure()`, `if-no-files-found: ignore`) uploads that directory
   as an artifact per matrix cell — the data we have been unable to
   capture from JS instrumentation alone.

If (1) eliminates the flake on the next push to develop, great. If not,
(2) finally gives us the crash dump and we can fix the root cause.

Touches all four Backend tests jobs (Linux × 2, Windows × 2). The
Windows steps now also set `shell: bash` so the same `mkdir -p ...`
line works under git-bash; the existing `working-directory: src` is
preserved. NODE_OPTIONS is scoped to the test step only, so the
existing vitest step is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(ci): address Qodo review on PR #7748

Three findings from Qodo's review of the Windows + Node 24 flake fix:

1. (bug) "mocha --exit masks handle leaks". --exit removes the post-suite
   event-loop drain that surfaces leaked timers / sockets — exactly the
   class of regression that lowerCasePadIds.ts notes is otherwise visible.
   Linux/local runs are currently green on natural drain, so dropping
   that signal everywhere would silence real leaks to fix a Windows-only
   flake.

   Fix: scope --exit to Windows only.
     - Remove --exit from src/package.json's "test" script (shared with
       local dev + Linux CI; both keep natural-drain behaviour).
     - Append `pnpm test -- --exit` in just the two Windows backend-test
       steps so the mitigation only runs where the flake actually lives.

2. (observability) "diagnostics exit-matrix misleading". With --exit on
   Windows, "only exit fires" becomes the EXPECTED pattern there, not a
   sign of unexpected process.exit(). Update the matrix comment in
   tests/backend/diagnostics.ts to spell out: clean drain on
   Linux/local → beforeExit + exit; Windows under --exit → only exit;
   "only exit" elsewhere still implies an unexpected process.exit
   somewhere.

3. (rule violation) "no regression test for the mitigation". Repo
   convention (see admin-i18n-source-lint.test.ts) is to pin
   policy-bearing config with a source-lint spec so a future refactor
   can't silently revert it.

   Add src/tests/backend-new/specs/backend-tests-flake-mitigation.test.ts:
     - Asserts every "Run the backend tests" step sets NODE_OPTIONS with
       the report-on-fatalerror diag flags AND is followed by an Upload
       Node diagnostic reports step (4 of each in the current matrix).
     - Asserts exactly 2 Windows jobs invoke `pnpm test -- --exit`.
     - Asserts the shared mocha "test" script in src/package.json does
       NOT bake in --exit globally.

Verified locally:
  - cd src && pnpm exec vitest run tests/backend-new/specs/backend-tests-flake-mitigation.test.ts
    → 3 passed (3).
  - Stream.ts spec without --exit → 31 passing, diag prints
    "beforeExit code=0" + "exit code=0" (clean drain restored).
  - Existing admin-i18n-source-lint suite still passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 09:22:45 +01:00
..
ISSUE_TEMPLATE Fix bug_report.md bug template 2021-11-22 17:25:00 -05:00
workflows test(ci): kill Windows + Node 24 backend-test flake; capture native crashes (#7748) 2026-05-15 09:22:45 +01:00
dependabot.yml Bundle dev-dependency updates (#6268) 2024-03-25 12:38:34 +01:00
FUNDING.yml Create FUNDING.yml 2020-10-23 20:31:17 +01:00
PULL_REQUEST_TEMPLATE.md chore: Rename some occurences of etherpad-lite to etherpad (#7552) 2026-04-19 16:53:57 +02:00