feat(readers): 4 more generous fixes from the 648-dataset audit re-run #129
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |