chore: update pnpm to v12 #864
Workflow file for this run
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: | |
| # Every job here reads the repository and writes nothing back, so the token is | |
| # narrowed once at the top rather than per job. The repository default is | |
| # already `read`, which makes this a guard against that setting being widened | |
| # later rather than a change in what the jobs can do today. | |
| permissions: | |
| contents: read | |
| # Clean adoption resolves a fresh dependency graph outside the checkout. Keep | |
| # its installer independent of whichever npm release ships with the Node runner. | |
| env: | |
| CLEAN_ADOPTION_NPM_VERSION: 11.6.4 | |
| jobs: | |
| check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Build the documentation site and check its Markdown integrations | |
| run: pnpm docs:check | |
| - name: Check the drawing-game source snippets | |
| run: pnpm example:drawing-game:snippets:check | |
| - run: pnpm typecheck | |
| - run: pnpm lint | |
| - run: pnpm format:check | |
| test: | |
| name: test (${{ matrix.os }}, node ${{ matrix.node }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| # One version failing should not hide the others. | |
| fail-fast: false | |
| matrix: | |
| # The versions still in maintenance. Node 20 left it in April 2026, which | |
| # is why it is not here; that pnpm 11 cannot install on it either is a | |
| # consequence, not the reason, so raising pnpm does not raise this list. | |
| # What the published package supports is a separate question, answered by | |
| # `engines.node` and guarded by the `node-floor` job below. | |
| os: [ubuntu-latest] | |
| node: [22, 24] | |
| # Every Node version on Linux, and one job each for the other two systems | |
| # rather than a full cross product, which would be six jobs to answer a | |
| # question two can. smocket ships as a devDependency and runs on | |
| # contributors' machines rather than on a server, so an operating system | |
| # the dual run has never been executed on is a gap in the central claim, | |
| # not a convenience. `lts/*` tracks the current LTS so this does not need | |
| # editing every October; it is a toolchain choice and deliberately not | |
| # tied to `engines.node`, which a consumer's own runner honors instead. | |
| include: | |
| - os: windows-latest | |
| node: lts/* | |
| - os: macOS-latest | |
| node: lts/* | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Run the suite against real socket.io | |
| run: pnpm test:real | |
| # The mock suite hard-gates like any other check: a mock regression fails | |
| # it, and with it the badge. | |
| - name: Run the suite against smocket | |
| run: pnpm test:mock | |
| # The example is documentation that executes, so it rots the moment nothing | |
| # runs it. This builds `dist/` and runs the program, which fails the job if | |
| # the example stops working against the package it demonstrates. | |
| - name: Run the chat room example | |
| run: pnpm example:chat-room | |
| - name: Compare the drawing game against both Node targets | |
| run: pnpm example:drawing-game:test | |
| browser: | |
| name: browser (chromium) | |
| needs: package | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Install the clean-adoption npm runner | |
| run: npm install --global "npm@$CLEAN_ADOPTION_NPM_VERSION" | |
| - name: Download the verified release candidate | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }} | |
| path: .release-candidate | |
| - name: Install Chromium for Playwright | |
| run: pnpm exec playwright install --with-deps chromium | |
| # Only the mock target has a counterpart in a page, so this asks a narrower | |
| # question than the dual run. Does the mock behave in a browser the way it | |
| # behaves in Node. #139 is what happens without it. | |
| - name: Run the mock target in a browser | |
| run: pnpm test:browser | |
| - name: Prove one SharedWorker lobby across three Chromium tabs | |
| run: pnpm test:shared-worker | |
| - name: Verify production SharedWorker tab lifecycle | |
| run: xvfb-run --auto-servernum pnpm test:shared-worker:lifecycle | |
| - name: Reject unexpected SharedWorker page errors | |
| run: xvfb-run --auto-servernum pnpm test:shared-worker:errors | |
| - name: Compare SharedWorker with a real Socket.IO sidecar | |
| run: pnpm test:shared-worker:parity | |
| - name: Run the documented SharedWorker lobby | |
| run: pnpm example:shared-worker | |
| - name: Run the drawing game across three pages and both targets | |
| run: pnpm example:drawing-game:verify | |
| - name: Run candidate packages in Chromium | |
| run: pnpm consumer:client:candidate -- --manifest .release-candidate/release-candidate.json --browser | |
| node-floor: | |
| name: declared node floor | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| # Install and build on a version the toolchain runs on. pnpm 11 needs | |
| # 22.13, so this half cannot move down and does not need to: what it | |
| # produces is `dist/`, and `dist/` is what the two steps below run. | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Install the Node 20 compatibility runner | |
| run: pnpm --dir compat/node20 install --frozen-lockfile | |
| - run: pnpm build | |
| - run: pnpm --filter smocket-client build | |
| # Lower tier: the exact floor `engines.node` declares. Nothing installed | |
| # is invoked here, not even pnpm, because pnpm 11 would not start on this | |
| # version either. `scripts/smoke.mjs` imports `node:assert` and `dist/` | |
| # and nothing else, so whatever Node can run the package can run it. It | |
| # drives one room broadcast rather than only importing the module, so a | |
| # `>=20` that delivers nothing fails here instead of shipping. | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 20.0.0 | |
| - run: node scripts/smoke.mjs | |
| - run: node --test packages/smocket-client/test/runtime.test.mjs packages/smocket-client/test/runtime.test.cjs | |
| # Upper tier: the whole mock suite against `dist/` on Node 20.13.0. The | |
| # exact 20.0.0 floor can collect this suite, but its fake timer cleanup | |
| # does not complete. The smoke checks above cover that exact runtime, | |
| # while this tier keeps the broader package behavior on Node 20. | |
| # | |
| # The root suite uses Vitest 5, which requires Node 22.12 or newer. This | |
| # tier invokes Vitest 4 from `compat/node20` instead, which keeps the | |
| # runner in a dedicated lockfile without executing unsupported Vitest 5 | |
| # code. | |
| # The `node_modules` installed above is reused as is. Node 20 resolves | |
| # pnpm's links without a reinstall or a separate artifact. | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 20.13.0 | |
| - name: Reject a missing SharedWorker artifact with the Node 20 runner | |
| run: node scripts/check-shared-worker-dist-gate.mjs | |
| env: | |
| SMOCKET_DIST_VITEST: compat/node20/node_modules/vitest/vitest.mjs | |
| - run: node compat/node20/node_modules/vitest/vitest.mjs run --config vitest.dist.config.ts | |
| compat: | |
| name: real target (socket.io ${{ matrix.socketio }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| # Exercise the oracle across its supported range, not one pinned version. | |
| socketio: ['4.7', '4.8'] | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Pin socket.io ${{ matrix.socketio }} | |
| run: pnpm add --workspace-root -D socket.io@${{ matrix.socketio }} socket.io-client@${{ matrix.socketio }} | |
| - name: Typecheck against socket.io ${{ matrix.socketio }} | |
| run: pnpm typecheck | |
| - name: Run the suite against real socket.io ${{ matrix.socketio }} | |
| run: pnpm test:real | |
| conformance: | |
| name: conformance report | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # docs/conformance.md is generated from a dual run, so it is only true as | |
| # long as it matches the suite. This runs the same generation and fails if | |
| # the committed file has drifted, which is what keeps the report evidence | |
| # rather than a claim someone forgot to update. It runs both targets again | |
| # rather than reusing the `test` job, because the report needs the two | |
| # results side by side and that job reports them separately per platform. | |
| - name: Check the conformance report is current | |
| run: pnpm check:conformance | |
| public-surface: | |
| name: public surface ledger | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # This owns upstream declaration and classification drift only. The packed | |
| # manifest, dependency policy, and import scanner remain in `package`. | |
| - name: Check the reviewed upstream public surface | |
| run: pnpm check:public-surface | |
| - name: Reject classifications that reference closed issues | |
| run: pnpm check:public-surface-issues | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| published-type-version: | |
| name: published type version | |
| if: github.event_name == 'pull_request' | |
| needs: package | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| - name: Detect synchronized package version changes | |
| id: versions | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: node scripts/check-published-types.mjs detect --base "$BASE_SHA" >> "$GITHUB_OUTPUT" | |
| - if: steps.versions.outputs.changed == 'true' | |
| uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - if: steps.versions.outputs.changed == 'true' | |
| run: pnpm install --frozen-lockfile | |
| - if: steps.versions.outputs.changed == 'true' | |
| name: Download the synchronized release candidate | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }} | |
| path: .release-candidate | |
| - if: steps.versions.outputs.changed == 'true' | |
| name: Enforce the published public-type version boundary | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: | | |
| pnpm check:published-types check \ | |
| --base "$BASE_SHA" \ | |
| --manifest .release-candidate/release-candidate.json | |
| coverage: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # Coverage of smocket's own code, which only the mock target exercises; it | |
| # gates on the thresholds in vitest.config.ts. | |
| - name: Coverage against smocket | |
| run: pnpm coverage | |
| # The gate above is the check that matters. This upload only feeds the | |
| # Codecov report, and it needs the CODECOV_TOKEN secret even on a public | |
| # repository, since a tokenless upload is rejected. It never fails the job, | |
| # so a Codecov outage or a missing token costs the report and not the run. | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7 | |
| with: | |
| files: ./coverage/lcov.info | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| fail_ci_if_error: false | |
| package: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| persist-credentials: false | |
| - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Install the clean-adoption npm runner | |
| run: npm install --global "npm@$CLEAN_ADOPTION_NPM_VERSION" | |
| - name: Build one immutable two-package release candidate | |
| run: pnpm release:candidate | |
| - name: Reject external imports in the built root package | |
| run: pnpm assert:no-imports | |
| # Package policy, Publint, Are The Types Wrong, and both independent | |
| # consumers receive the exact tarballs named by this digest manifest. | |
| - name: Verify every package and candidate consumer against one artifact set | |
| run: pnpm check:release-candidate | |
| - name: Preserve the verified candidate for later read-only jobs | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: release-candidate-${{ github.event.pull_request.head.sha || github.sha }} | |
| path: .release-candidate | |
| if-no-files-found: error | |
| include-hidden-files: true | |
| retention-days: 7 |