Skip to content

fix(socketio-shim): NonNullable<> on harness setTimer type to fix tsgo #45

fix(socketio-shim): NonNullable<> on harness setTimer type to fix tsgo

fix(socketio-shim): NonNullable<> on harness setTimer type to fix tsgo #45

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: typecheck + test + coverage gate
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Typecheck (all packages)
run: |
bun run --cwd packages/shared typecheck
bun run --cwd packages/socialcalc-headless typecheck
bun run --cwd packages/worker typecheck
bun run --cwd packages/client typecheck
bun run --cwd packages/client-multi typecheck
bun run --cwd packages/oracle-harness typecheck
bun run --cwd packages/cli typecheck
bun run --cwd packages/socketio-shim typecheck
bun run --cwd packages/migrate typecheck
bun run --cwd packages/e2e typecheck
- name: shared — tests + 100% coverage gate
run: bun run --cwd packages/shared test:coverage
- name: worker — Node tests + 100% coverage gate
run: bun run --cwd packages/worker test:coverage
- name: client — Vite build (needed for assets/static/player.js)
run: bun run --cwd packages/client build
- name: client-multi — Vite build (needed for assets/multi/)
run: bun run --cwd packages/client-multi build
- name: Build curated assets/ dir (scripts/build-assets.sh)
# Phase 4.1/11: regenerates `assets/` at repo root from the
# client/client-multi dist output plus the legacy static files.
# Must run BEFORE worker integration tests (miniflare reads
# wrangler.toml `[assets]` at startup) and `wrangler deploy
# --dry-run` (validates the directory exists).
run: ./scripts/build-assets.sh
- name: Validate worker D1 migrations
# Phase 5.1: smoke-check each SQL file in packages/worker/migrations/
# by replaying it into a fresh in-memory SQLite DB. Catches syntax
# errors before they blow up at miniflare startup or on a real
# `wrangler d1 migrations apply` in prod. ubuntu-latest ships with
# sqlite3 preinstalled.
run: |
for f in packages/worker/migrations/*.sql; do
echo "applying $f"
sqlite3 :memory: < "$f"
done
- name: worker — integration tests (workerd via miniflare)
run: bun run --cwd packages/worker test:workers
- name: worker — wrangler dry-run build
run: bun run --cwd packages/worker build:dry
- name: socialcalc-headless — smoke tests (workerd)
run: bun run --cwd packages/socialcalc-headless test
- name: client — tests + 100% coverage gate
run: bun run --cwd packages/client test:coverage
- name: client-multi — tests + 100% coverage gate
run: bun run --cwd packages/client-multi test:coverage
- name: oracle-harness — tests + 100% coverage gate
run: bun run --cwd packages/oracle-harness test:coverage
- name: cli — tests + 100% coverage gate
run: bun run --cwd packages/cli test:coverage
- name: socketio-shim — tests + 100% coverage gate
run: bun run --cwd packages/socketio-shim test:coverage
- name: migrate — tests + 100% coverage gate
run: bun run --cwd packages/migrate test:coverage
- name: Upload coverage artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-lcov
path: |
packages/shared/coverage/
packages/worker/coverage/
packages/client/coverage/
packages/client-multi/coverage/
packages/oracle-harness/coverage/
packages/cli/coverage/
packages/socketio-shim/coverage/
packages/migrate/coverage/
retention-days: 7
if-no-files-found: ignore
build-selfhost:
name: build:selfhost — docker image + smoke
runs-on: ubuntu-latest
timeout-minutes: 15
needs: test
# Mirrors CLAUDE.md §11.1 item 10. Uses the Dockerfile + docker-compose
# at the repo root and hits /_health via scripts/smoke-selfhost.sh.
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Smoke — build image, compose up, curl /_health, compose down
run: ./scripts/smoke-selfhost.sh
e2e:
name: e2e — Playwright against wrangler dev
runs-on: ubuntu-latest
timeout-minutes: 20
needs: test
# Mirrors CLAUDE.md §11.1 item 8. Boots wrangler + the client-multi
# Vite dev server via per-worker fixtures in packages/e2e and exercises
# the HTTP surface + SPA mount. Uploads the HTML report on failure so
# traces/screenshots are recoverable.
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install Playwright browsers (chromium + system deps)
run: bunx playwright install --with-deps chromium
working-directory: packages/e2e
# Wrangler 4 reads `[assets] directory = "../../assets"` from
# wrangler.toml; if the dir is missing (or empty, which it is on
# this fresh runner) wrangler hangs on asset-manifest resolution
# — silently, with no stderr — and every fixture setup times out.
# The `test` job builds these before its own suite; `e2e` runs on
# a separate runner with a clean workspace, so rebuild here.
- name: client — Vite build (for assets/static/player.js)
run: bun run --cwd packages/client build
- name: client-multi — Vite build (for assets/multi/)
run: bun run --cwd packages/client-multi build
- name: Build curated assets/ dir
run: ./scripts/build-assets.sh
- name: Run Playwright suite
run: bun run --cwd packages/e2e test
env:
CI: 'true'
- name: Upload Playwright HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: packages/e2e/playwright-report/
retention-days: 7
if-no-files-found: ignore
- name: Upload trace + screenshots on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-test-results
path: packages/e2e/test-results/
retention-days: 7
if-no-files-found: ignore
mutation-gate:
name: mutation-gate — changed packages only
runs-on: ubuntu-latest
timeout-minutes: 20
needs: test
# Fast PR-gate mutation check. Runs Stryker only on packages whose
# `src/` changed in the PR, so docs/test/config-only PRs skip it and
# single-package PRs stay under ~2 minutes. The full matrix lives in
# nightly.yml; see CLAUDE.md §5.3 + docs/MUTATION_REPORT.md for the
# ratchet workflow.
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Detect changed packages
id: changed
# Override GH Actions' default `bash -eo pipefail` because grep
# exits non-zero when the pattern matches nothing, which is the
# expected case for docs/test/config-only PRs.
shell: bash {0}
run: |
# Compare the PR head against the merge-base with origin/main.
# On a push to main the base still resolves (merge-base with self
# is HEAD) — the diff is empty, so the Stryker step is skipped.
git fetch origin main --depth=1 || true
if git merge-base origin/main HEAD >/dev/null 2>&1; then
BASE=$(git merge-base origin/main HEAD)
else
BASE=HEAD~1
fi
changed=$(git diff --name-only "$BASE" HEAD \
| grep -oE '^packages/[^/]+/src/' \
| sort -u \
| sed 's|packages/||;s|/src/||' \
| tr '\n' ' ')
echo "packages=$changed" >> "$GITHUB_OUTPUT"
echo "Changed packages: ${changed:-<none>}"
- name: Run Stryker on changed packages
if: steps.changed.outputs.packages != ''
run: |
for pkg in ${{ steps.changed.outputs.packages }}; do
if [ -f "packages/$pkg/stryker.conf.json" ]; then
echo "::group::mutation test — $pkg"
bun run --cwd "packages/$pkg" mutation
echo "::endgroup::"
else
echo "skip: packages/$pkg has no stryker.conf.json"
fi
done
- name: Upload mutation reports on failure
if: failure() && steps.changed.outputs.packages != ''
uses: actions/upload-artifact@v4
with:
name: mutation-gate-reports
path: packages/*/reports/mutation/
retention-days: 7
if-no-files-found: ignore