Skip to content

feat(readers): 4 more generous fixes from the 648-dataset audit re-run #129

feat(readers): 4 more generous fixes from the 648-dataset audit re-run

feat(readers): 4 more generous fixes from the 648-dataset audit re-run #129

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
# Cancel older runs on the same ref so the latest push wins quickly.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Opt the JS-action runtime into Node 24 ahead of the June 2026 default
# flip. Silences deprecation warnings without affecting our test code,
# which already requests `node-version: '20'` for its own runtime.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
jobs:
# Pure-unit suite. Stubbed/mocked fetch, in-memory Blob, synthetic
# parser fixtures — no real network. Fast (~1s) and deterministic;
# gates every push and PR.
unit:
name: Unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
# Typecheck first — it's faster (~1s) than the unit suite (~5s), so
# contributors get the structural failure signal sooner.
- name: Type check (tsc on JSDoc-annotated files)
run: npm run test:typecheck
- run: npm run test:unit
# Coverage gate. c8 wraps the same unit-only test set as the `unit`
# job above and enforces thresholds from `.c8rc.json` (derived from
# the 2026-05-20 baseline, set 5% below baseline). Gated behind
# `needs: unit` so we don't burn CI minutes on a coverage run when
# the underlying tests already failed. The HTML + json-summary
# reports are uploaded as an artifact so reviewers can inspect
# uncovered lines without re-running locally.
coverage:
name: Coverage gate
runs-on: ubuntu-latest
needs: unit
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run test:coverage
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 14
if-no-files-found: ignore
# Playwright e2e against the real page served by Python's static
# http.server. The viewer pulls a small OpenNeuro recording at
# runtime so this depends on S3 reachability — keep retries on.
e2e:
name: Playwright e2e
runs-on: ubuntu-latest
needs: unit
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- run: npm ci
# Resolve the actually-installed Playwright version (post-`npm ci`)
# so the browser cache key is keyed on the binary contract, not
# on every unrelated package-lock change.
- name: Resolve Playwright version
id: playwright-version
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> "$GITHUB_OUTPUT"
- name: Cache Playwright browsers
id: pw-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}
restore-keys: |
${{ runner.os }}-playwright-
# System-level deps live in the runner image, not in the cache —
# always run install-deps so a cache HIT can't leave us with stale
# libgbm/libnss/etc on a future image refresh. Cheap (apt is a
# near-no-op when packages are already present).
- name: Install Playwright system deps
run: npx playwright install-deps chromium
- name: Install Playwright browsers
if: steps.pw-cache.outputs.cache-hit != 'true'
run: npx playwright install chromium
- run: npm run test:e2e
env:
CI: '1'
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report
retention-days: 7
if-no-files-found: ignore
# Network-bound reader + integration suite (sidecars, EEGLAB / EDF /
# BDF / BrainVision bitwise checks, integration matrix + stress).
# OpenNeuro S3 has variance, so run on a nightly schedule and on
# demand rather than blocking every PR. Keep the schedule on so the
# default branch is exercised against real data continuously.
network:
name: Network suite
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run test:net
- run: npm run test:integration
# Memory-leak gate. Runs the same integration suite under
# `node --expose-gc`, which lets the `memory:` test inside
# tests/integration-rapid-pan.test.mjs drive Joyee Cheung's tryGC
# pattern. Without the flag the test self-skips, so this is a
# cheap-but-real second pass over the same code paths.
- run: npm run test:integration:gc