Update changelog and features #70
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 | |
| # Merge gate for three.ws. Real money rides on this code, so every PR and every | |
| # push to main must clear the checks below before it can land. Jobs run in | |
| # parallel; the slowest (unit tests) gates the rest. | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| # A newer push to the same branch/PR cancels the in-flight run — no point | |
| # spending CI minutes on a commit that's already superseded. | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| # eslint exits non-zero on any error. Pre-existing warnings are allowed | |
| # for now; the bar is "no new errors". Tighten with --max-warnings once | |
| # the warning backlog is burned down. | |
| - run: npx eslint . | |
| test: | |
| name: Unit tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| - run: npx vitest run | |
| guards: | |
| name: Source guards | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| # Fail if `npx vercel build` ever clobbered an api/*.js source file with | |
| # an esbuild bundle (a documented footgun in this repo). | |
| - run: node scripts/check-api-not-bundled.mjs | |
| # Every JS-rendered <img> must declare loading= so off-fold feed/grid | |
| # images defer their fetch+decode. Keeps scroll perf from regressing as | |
| # new components ship. Bulk-fix: node scripts/codemod-lazy-images.mjs | |
| - run: npm run check:images | |
| # Regenerates and validates the public changelog/page index; the script | |
| # fails the build on a malformed changelog entry. Run as a validation | |
| # gate only — the generated changelog.json is not byte-deterministic, so | |
| # a committed-artifact diff check would be flaky and is intentionally | |
| # omitted until the generator emits stable output. | |
| - run: npm run build:pages | |
| typecheck: | |
| name: Typecheck | |
| runs-on: ubuntu-latest | |
| # `npm run typecheck` (tsc over jsconfig.json) is clean as of 2026-06-21, so | |
| # this is now a hard merge gate: a new type error blocks the PR. The JSDoc | |
| # backlog it used to wait on has been burned down — keep it clean by fixing | |
| # the types, not by restoring continue-on-error. | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run typecheck | |
| pages: | |
| name: Page health | |
| runs-on: ubuntu-latest | |
| # scripts/test-pages.mjs spawns its own vite server and drives Chromium over | |
| # every public route, failing on thrown errors, real console errors, dead | |
| # requests, or broken hero images before they ship (npm run test:pages). | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| restore-keys: playwright-${{ runner.os }}- | |
| - run: npx playwright install --with-deps chromium | |
| - run: npm run test:pages | |
| e2e: | |
| name: E2E (Playwright) | |
| runs-on: ubuntu-latest | |
| # The browser-driven specs (playwright.config.js boots `npm run dev` as its | |
| # webServer). retries:1 in the config absorbs a single transient blip; a | |
| # spec that fails twice is a real regression and blocks the PR. | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - run: npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| restore-keys: playwright-${{ runner.os }}- | |
| - run: npx playwright install --with-deps chromium | |
| - run: npx playwright test |