Skip to content

build: install with pnpm and check, lint, format and run tasks with Vite+ - #753

Merged
ian-pascoe merged 11 commits into
mainfrom
build/vite-plus-pnpm
Nov 13, 2026
Merged

ian-pascoe merged 11 commits into
mainfrom
build/vite-plus-pnpm

Conversation

@ian-pascoe

@ian-pascoe ian-pascoe commented Nov 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

The repo moves from Bun and Turborepo to pnpm and Vite+ (ADR-0055). The Container stops preinstalling Bun (ADR-0004's fifth revision).

-bun.lock, bunfig.toml (trustedDependencies, patchedDependencies in package.json)
+pnpm-lock.yaml, pnpm-workspace.yaml (allowBuilds, patchedDependencies, overrides, linkWorkspacePackages, dedupePeers)
-turbo.json, apps/web/turbo.json            # transit node, hand-listed inputs
+<pkg>/vite.config.ts → run.tasks           # packages/config/src/tasks.ts: typecheck, test; cached by the files they read
-.oxlintrc.json ×16, .oxfmtrc.json, tsrslint link
+vite.config.ts (root): lint (+ per-package lint.overrides), fmt, staged
+oxlint-tsgolint → link:./tools/tsrs-lint-shim  # type-aware lint runs on tsrs's `tsrs-lint`
-.husky/ + lint-staged
+.vite-hooks/ + vp staged
-oven-sh/setup-bun + turbo cache pruning
+voidzero-dev/setup-vp + a per-part Vite Task cache (cleared past 1 GiB)
 656 test files: `vitest` → `vite-plus/test` imports (vp migrate)
pnpm run check
  vp check                 # format, lint, type-aware lint (tsrs-lint), once at the root
  vp run -r typecheck      # effect-tsgo tsrs per package (Effect diagnostics), cached
  vp run -r test           # vitest run per package, cached

Dependency updates

Everything moved to its latest version that pnpm's day-old minimum release age allows, except where noted.

  • npm:
    • effect 4.1.4, pi 1.5.2, alchemy beta.86, @cloudflare/vitest-plugin 1.8.0 (workerd 1.20261110), isomorphic-git 1.44.13, @effect/tsgo 0.68.1, tsrs 0.25, and the unpinned rest.
    • @cloudflare/computer 0.11.1, not 0.11.2: 0.11.2 is under a day old.
    • The patches for pi-durable, @cloudflare/vitest-plugin and computer are ported unchanged.
    • alchemy's patch: upstream now retries a new Worker's deployments read (alchemy#3000), but for only about 51 s. The patch keeps our five-minute retryDeploymentsRead in its place (First Preview deploy of a new PR stage fails with WorkerNotFound (needs 1–2 reruns) #615).
  • Code changes the updates forced:
    • chord 1.5.1 moved Context, Draft and JsonValue off its root, so imports now come from /context, /delta and /json.
    • pi-ai now knows claude-fable-5-2, so it joins the 400k context-window cap list (it was capped before, as a templated model). The test fixture's uncatalogued model is now Fable 5.3.
    • workerd 1.20261110 tells a stream it was cancelled right away, so the fake MCP bridge no longer writes to a cancelled stream.
  • Container image:
    • computerd 0.11.1, kept in step with computer. Its FUSE driver is unchanged since 0.9.0.
    • mise v2026.11.7, the current ubuntu:26.04 digest, git 2.56.1, gh 2.104.0, Node 26.13.1, pnpm 12.18.0 and uv 0.13.8.
  • GitHub Actions: already on their latest (checkout@v7, cache@v6, setup-vp@v1.22.0).
  • Held:
    • vite-plus stays at 1.4.0 and Vitest at 5.0.5. Rechecked with vite-plus 1.6.0, Vitest 5.1.0 and plugin 1.8.0: the same three workerd tests still fail.
    • rolldown stays at alchemy's own pin, 1.2.16.
  • Not yet verified locally: the full test suite after the computer bump. Lint, format and typecheck passed; CI runs the suite.

Evidence

  • Before: bun run check passed on main (93ba45a).

  • After (local, macOS):

    • pnpm exec vp check: no format, lint or type errors in 1,886 files.
    • vp run -r typecheck: 16/16 packages.
    • vp run -r test: 16/16 packages, every workerd project included.
    • @cloudpid/web#build, and @cloudpid/server#startup (599 KiB, 47.8 ms).
    • git-install:check: npm's production install of the root loads /cloudpid.
    • Hooks: both commits went through .vite-hooks/ (vp staged, commitlint).
  • Type-aware lint, whole-repo vp lint with type-check, two runs each, macOS arm64:

    Backend Wall CPU Peak memory
    Vite+'s bundled tsgolint 7.0.2004 16 s 48 s 3.6 GB
    tsrs 0.24 tsrs-lint (this PR) 7–8 s 15 s 0.9–1.0 GB

    A probe file still reports typescript(TS2322) and no-floating-promises.

  • Caching: a rerun of vp run -r typecheck replays all 16 tasks in 0.9 s. An edit to packages/protocol/src/index.ts reruns exactly the 9 tasks that read it.

Decisions

  • vite-plus is pinned to 1.4.0, the last release on Vitest 5.0.5. 1.5 and 1.6 bundle Vitest 5.1, and the workerd tests fail under it (dependencies.md).
  • The test task is vitest run, not vp test. vp run runs a vp test inside the vp that started it, with that copy's Vitest. A non-project vp, such as mise's npm:vite-plus, then gives @cloudflare/vitest-plugin a second Vitest, and the workerd projects fail with reading 'config'.
  • Type-aware lint runs on tsrs's own linter, tsrs-lint (tsrs 0.24), instead of Vite+'s bundled tsgolint. Vite+ sets OXLINT_TSGOLINT_PATH itself, so a pnpm override points oxlint-tsgolint at tools/tsrs-lint-shim, whose bin/tsgolint.js runs the tsrs package's tsrs-lint bin in-process. tsrs here is the linter only; the typecheck is still effect-tsgo tsrs.
    vp lint
      OXLINT_TSGOLINT_PATH = resolve("oxlint-tsgolint/bin/tsgolint")   # Vite+ sets it itself
        oxlint-tsgolint → link:./tools/tsrs-lint-shim                  # pnpm-workspace.yaml override
          bin/tsgolint.js → the `tsrs` package's `tsrs-lint` bin, in-process
    
    • The shim has no package.json on purpose. With one, the effect-tsgo patch step in prepare mistakes it for Vite+'s oxlint-tsgolint and fails the install.
    • The shim-free route waits. effect-tsgo --tsrs-lint vp lint (@effect/tsgo 0.68+) needs oxlint 1.91+, so a Vite+ past 1.4.0, which waits on the Vitest 5.1 workerd issue.
  • Three files are reformatted. Vite+ 1.4.0 bundles oxfmt 0.74, older than the repo's 0.76.
  • One rule is suppressed in hooks-serve.test.ts. oxlint 1.89 reports a false no-invalid-fetch-options there.
  • macOS needs two workarounds. A cached task's coreutils run as uutils', so:
    • The GNU-tool probes in 3 test files check --version for (GNU …).
    • apps/sandbox-image's test is uncached.
  • pnpm settings:
    • dedupePeers and an exact ws override remove duplicate @cloudflare/computer and alchemy copies that failed typecheck.
    • disallowWorkspaceCycles makes pnpm enforce the no-cycle property that mcp-apps.md had credited to Turborepo.
  • apps/web/tsconfig.json regains its paths for React types. They were dropped by the Bun move, and the Container's global virtual store needs them again.
  • The Container keeps generic support for users' repos: the .bun scan exclusion, TURBO_CACHE_DIR and the **/.turbo ignore.
  • no-module-mocking also matches vi imported from vite-plus/test.
  • The docs-only CI job now does a full install before vp fmt --check.

Review

Both axes passed (Standards and Spec, on head 76be304) after two fix rounds. Advisory findings left as is:

  • The GNU probe is written in three packages that share no test-helper dependency.
  • The 1.4.0 and 5.0.5 pins repeat across files. dependencies.md says they move together.
  • The per-package vite.config.ts files are identical, as AGENTS.md's "copy from a sibling" rule intends.

Merge Danger

Door: two-way. A revert restores Bun, though every checkout would then need bun install again. Developers need to change one habit: run Vite+ as pnpm exec vp or through pnpm run, never with mise's npm:vite-plus vp.

Blast Radius: tooling. This covers CI, hooks, deploy jobs and the Container image's toolchains.

  • Type-aware lint backend. If a Vite+ upgrade looks for its backend elsewhere, vp lint fails loudly with Error running tsgolint (dependencies.md has the check). On Windows Vite+ looks for tsgolint.exe or .cmd, so the shim doesn't run there; macOS, Linux, CI and the Container are covered. tsrs is pinned at 0.24 (0.25 was under pnpm's minimum release age). Removing the override and tsrs puts back Vite+'s tsgolint. The first prod and preview deploys after merge rebuild the web app once, because the WebBuild step's inputs changed (vite.config.ts and the lockfile).

Plan

Migrate the repo to Vite+ with pnpm instead of Bun, with the owner's decisions:

  1. Replace Turborepo with vp run.
  2. Replace oxlint and oxfmt with vp check.
  3. Move Husky and lint-staged to vp staged and .vite-hooks.
  4. Let vp migrate rewrite Vitest imports to vite-plus/test.
  5. Move the Container back to pnpm.
  6. Land it from a worktree.
  7. Run Vite+'s type-aware lint on tsrs's official tsrs-lint (first a stacked follow-up, build: run Vite+'s type-aware lint on tsrs's own linter #754, then folded into this PR).
  8. Update all dependencies (npm, Docker, GitHub Actions) in the same PR.

…ite+

- pnpm-workspace.yaml and pnpm-lock.yaml replace bun.lock and bunfig.toml.
- vite-plus 1.4.0 (Vitest 5.0.5): one root vite.config.ts for lint, format
  and staged files; vp check replaces per-package oxlint and oxfmt, and
  tsgolint replaces tsrslint.
- Vite Task replaces Turborepo: each package's typecheck and test tasks
  (packages/config/src/tasks.ts), cached by the files they read.
- .vite-hooks and vp staged replace Husky and lint-staged.
- CI sets up with setup-vp and caches the Vite Task cache per part.
- The Container no longer preinstalls Bun (ADR-0004's fifth revision).
- ADR-0055; ADR-0028 partly superseded.
- no-module-mocking also matches vi from vite-plus/test.
- The test cache keys MODEL_PROXY_API_KEY and CHANGES_BENCH too.
- pnpm refuses workspace cycles; ws pin documented.
- The deploy job uses the setup action without a cache.
- Docs: apps/web's vite-plus, sandbox-image's uncached test, allowBuilds.
@ian-pascoe

Copy link
Copy Markdown
Owner Author

Review report for head 76be30420a94bb83855c7ae961f5c9e8288a6fcd (code-review against origin/main 93ba45a, Standards and Spec axes).

  • Round 1: Spec found no-module-mocking missing vite-plus/test's vi (fixed); Standards found doc/code mismatches (AGENTS.md exceptions, ws pin row, ADR allowBuilds wording, an unenforced cycle claim, unkeyed CHANGES_BENCH/MODEL_PROXY_API_KEY, a duplicated setup-vp block, setup.sh's redundant flag): all fixed in dec0a0f.
  • Round 2: container.md's Setup Scripts sentence and a broken ws table row: fixed in 76be304. Both axes: no blockers.

Dismissed (advisory, reasons in the PR body → Decisions/Review): the three GNU probes stay separate; the version pins repeat across files; the identical per-package vite.config.ts files follow AGENTS.md's copy-from-a-sibling rule; scope additions (dedupePeers, ws override, disallowWorkspaceCycles, apps/web React paths, macOS uutils workarounds, oxfmt reformat, one oxlint suppression) are each needed for the migration to pass.

@ian-pascoe

Copy link
Copy Markdown
Owner Author

Review report for head d86126ea2cdb125e3207ae2f1151d8ee298254b3: adds one CI fix on top of the reviewed 76be304 (the non-server Tests part's filter matched nothing and passed without running a test; now --fail-if-no-match --filter '@cloudpid/*' --filter '!@cloudpid/server'). Spec axis: no blockers.

@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Preview deployed

URL: https://cloudpid-server-pr-753.ian-g-pascoe.workers.dev

Built from 345d4a2 (stage pr-753, behind Access). It is destroyed when the
pull request is closed.


This comment updates on each push.

vp lint runs the bin/tsgolint of its own oxlint-tsgolint, so a pnpm
override makes that package tools/tsrslint-shim, which runs
@maschwenk/tsrslint's binary. A whole-repo vp lint takes 9-10 s and
2 GB at most, against 16 s and 3.6 GB on Vite+'s tsgolint.
tsrs 0.21 ships tsgolint's port as tsrs-lint, so the shim loads the
tsrs package's linter in place of @maschwenk/tsrslint. A whole-repo
vp lint takes 7-8 s and 1 GB at most.
npm: effect 4.1.4, pi 1.5.2 (chord's root foundations move to /context, /delta and /json), alchemy beta.86,
@cloudflare/vitest-plugin 1.8.0 (workerd 1.20261110), isomorphic-git 1.44.13, @effect/tsgo 0.68.1, tsrs 0.25,
and the rest; patches ported.
Image: mise v2026.11.7, ubuntu:26.04's current digest, git 2.56.1, gh 2.104.0, Node 26.13.1, pnpm 12.18.0,
uv 0.13.8.
The remount patch is ported unchanged; computer's change-log tables, sync span names and computerd's FUSE driver
are as in 0.9.0. Records that the Vitest 5.1 hold still fails with vite-plus 1.6 and @cloudflare/vitest-plugin 1.8.
@ian-pascoe
ian-pascoe merged commit c767cde into main Nov 13, 2026
16 checks passed
@ian-pascoe
ian-pascoe deleted the build/vite-plus-pnpm branch November 13, 2026 12:05

This branch was successfully deployed

1 active deployment
preview — ee05d5d1 Deployed Nov 13, 2026 by ian-pascoe via Preview #1394
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant