Body: three bugs in the rotate/angle path (#1679) #1574
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: Build & Test | |
| # Runs lint + test on every push/PR — no path-filtered shim partition. | |
| # The previous two-workflow setup (`main.yml` + `main-docs.yml`) was | |
| # racy on mixed PRs (PRs touching both `.md` and code): GitHub Actions | |
| # evaluates `paths` / `paths-ignore` against the full PR diff, so a | |
| # mixed PR triggered BOTH workflows, they shared `concurrency.group`, | |
| # and the faster docs-shim cancelled the real CI run while still | |
| # reporting green checks. Docs-only PRs pay ~2 minutes of CI cost as | |
| # the trade-off; cheaper than silently merging a lint failure. | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| types: [opened, synchronize] | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Setup node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: pnpm/action-setup@v5 | |
| - name: Get pnpm store directory | |
| run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: ${{ runner.os }}-pnpm-store- | |
| - run: pnpm i | |
| - run: pnpm lint | |
| - run: pnpm biome check | |
| - run: pnpm build | |
| test: | |
| needs: lint | |
| runs-on: ubuntu-latest | |
| container: | |
| # must match the workspace's playwright version (root devDependencies) | |
| image: mcr.microsoft.com/playwright:v1.62.1-noble | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Setup node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: pnpm/action-setup@v5 | |
| - name: Get pnpm store directory | |
| run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: ${{ runner.os }}-pnpm-store- | |
| - run: pnpm i | |
| # Vitest 4.1.11 runs each worker as one long-lived orchestrator page and | |
| # dispatches every spec file over a single websocket. Its ws close handler | |
| # destroys the session and rejects the pending `createTesters`, so if that | |
| # socket drops the whole run dies — the in-page client does try to | |
| # reconnect, but the session is already gone. Underneath, the browser | |
| # intermittently severs a renderer's network-service channels: every | |
| # websocket for that page dies at once, the server sees a graceful 1001 | |
| # while the page sees 1006, and no process crashes. | |
| # | |
| # Measured at 4 deaths in 21 local runs, and it cost three attempts to | |
| # land a PR that changed nothing but Markdown. Not our code: no test ever | |
| # fails, and the spec it names is just whichever was in flight. Launching | |
| # the full Chromium build fixes it locally (20 runs clean) but does | |
| # nothing here (0 of 4), so this retries instead. | |
| # | |
| # The condition is deliberately narrow — the page must have been lost AND | |
| # no test may have failed. A real failure prints "N failed" in the summary | |
| # and exits without a retry. | |
| - name: Test (retries once if vitest loses its browser page) | |
| # the container has no default bash, so GitHub would run this under | |
| # dash, which has no `pipefail` — and without it the exit status of | |
| # `pnpm test` is masked by `tee` | |
| shell: bash | |
| run: | | |
| set -o pipefail | |
| for attempt in 1 2; do | |
| if pnpm test 2>&1 | tee "test-$attempt.log"; then | |
| exit 0 | |
| fi | |
| if ! grep -q "Browser connection was closed" "test-$attempt.log" \ | |
| || grep -qE "Test Files.*[0-9]+ failed" "test-$attempt.log"; then | |
| echo "::error::test failed for a real reason, not the known browser flake" | |
| exit 1 | |
| fi | |
| echo "::warning::vitest lost its browser page (upstream flake) — attempt $attempt" | |
| done | |
| echo "::error::vitest lost its browser page on both attempts" | |
| exit 1 | |
| - run: pnpm -F @melonjs/matter-adapter test | |
| - run: pnpm -F @melonjs/planck-adapter test | |
| - run: pnpm -F @melonjs/debug-plugin test | |
| # Windows build — only on master push, not on PRs | |
| windows: | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Setup node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: pnpm/action-setup@v5 | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: ${{ runner.os }}-pnpm-store- | |
| - run: pnpm i | |
| - run: pnpm lint | |
| - run: pnpm build |