Skip to content

build(deps)!: require Effect 4.0.0 and Vitest 5 - #22

Merged
LordCoughmann merged 5 commits into
mainfrom
chore/deps-sweep
Oct 13, 2026
Merged

LordCoughmann merged 5 commits into
mainfrom
chore/deps-sweep

Conversation

@LordCoughmann

Copy link
Copy Markdown
Owner

Effect 4.0.0 (stable) + Vitest 5, plus tooling and a CI-gate fix

Effect

  • effect, @effect/platform-node, @effect/platform-bun and @effect/vitest move to the stable 4.0.0 line.
  • 32 imports migrated off the effect/unstable/* export paths that 4.0.0 removed: http, http-api, process, cli.
  • Docs, READMEs and the "Effect v4 RC required" notices drop the now-stale RC wording.

Peer range (consumer-visible)

  • The catalog pinned the family to an exact 4.0.0; because catalog: feeds both the devDependency and the peerDependency, every package published effect: "4.0.0" exactly. Widened to ^4.0.0 so consumers can take any 4.x patch.
  • The lockfile resolves 4.0.3 — the newest release outside the repo's 24h release-age window. 4.0.4 was published ~5h ago; resolving it would make pnpm install --frozen-lockfile fail with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION.

Vitest 5

  • vitest 4.1.11 → 5.0.4, @vitest/coverage-v8 → 5.0.4, @cloudflare/vitest-plugin 1.1.13 → 1.4.0 (first plugin release supporting Vitest 5). This finally satisfies @effect/vitest's vitest >=5 peer.
  • fsModuleCache: false in the four workerd configs — Vitest 5 enables the filesystem module cache by default and plugin 1.4.0 cannot read those host-FS entries from workerd, so every workerd test file failed before running. Revert once [vitest-plugin] Fix filesystem module caching cloudflare/workers-sdk#16163 ships (tracked in CONTRIBUTING.md).

fix(test-runner) — worth reviewing closely

runSubcommand only converted the aggregated per-runtime result into an exit code inside if (spec.forceExit), and only integration sets that flag. Every other subcommand recorded { ok: false }, printed x FAIL, then returned normally, so NodeRuntime.runMain exited 0. A deliberately failing unit test produced 1 failed | 32 passed (33) and exit code 0; a smoke run with a broken runtime reported 4/5 passed and exit 0. CI's pnpm test:unit step was one of them. Failures now propagate for every subcommand.

Tooling

  • alchemy examples → 2.0.0-beta.81 (beta.80+ is the first line with stable-only ^4.0.0 Effect peer ranges; beta.82/83 resolve @distilled.cloud/*@1.0.0-rc.15, published <24h ago, which the release-age policy rejects during lockfile verification).
  • @mpsuesser/oxlint-plugin-effect → 0.6.0 (first release built against stable effect@4.0.0) and oxlint → 1.87.0. The 16 generic anti-slop rules 0.5.0 enabled are deliberately not adopted — they produce 1410 findings across 139 files; they are disabled in oxlint.config.ts with the rationale.

Verification

  • pnpm install --frozen-lockfile — passes (this was failing on an earlier draft of the alchemy bump)
  • pnpm verify — green: CDP codegen freshness x3, check (lint/fmt/fallow/tsgo/package-versions), build, unit 444, smoke 5/5 (node, workerd, workerd-nocompat, bun, deno), examples 12/12, docs 90 blocks / 653 links
  • integration node ✓ and workerd ✓

Note on the changelog

The peer-range widening is a root-only build(deps) commit; release-please attributes entries by package path, so it may not appear. Flagging it here since it changes the published peer contract.

Effect moves from 4.0.0-rc.115 to the stable 4.0.0 release, with
@effect/platform-node, @effect/platform-bun and @effect/vitest in lockstep.

Migrate off the `effect/unstable/*` export paths that 4.0.0 removed
(32 imports across 27 files): unstable/http -> effect/http,
unstable/httpapi -> effect/http-api, unstable/process -> effect/process
and unstable/cli -> effect/cli. Docs, READMEs and the "Effect v4 RC
required" notices drop the now-stale RC wording.

Vitest moves 4.1.11 -> 5.0.4 with @vitest/coverage-v8 5.0.4 (its peer
matches the vitest version exactly) and @cloudflare/vitest-plugin
1.1.13 -> 1.4.0, the first plugin release supporting Vitest 5. That
finally satisfies @effect/vitest's `vitest >=5` peer.

Vitest 5 enables `fsModuleCache` by default, and plugin 1.4.0 cannot
read those host-FS cache entries from workerd, so every workerd test
file failed before running. Set `fsModuleCache: false` in the four
workerd configs until cloudflare/workers-sdk#16163 ships; the removal
follow-up is recorded in CONTRIBUTING.md.

BREAKING CHANGE: consumers must migrate to Effect 4.0.0.
@mpsuesser/oxlint-plugin-effect moves 0.4.3 -> 0.6.0 and oxlint 1.83.0 ->
1.87.0.

0.6.0 is the first plugin release built against stable effect@4.0.0, which
is the stack the previous commit moved to. Its fixes include detecting
Config.String/Config.NonEmptyString secrets and no longer demanding schema
type aliases for schema checks, filters, equivalences and formatters.

0.5.0 had also enabled 16 generic "anti-slop" rules ported from
dmmulroy/anti-slop, taking both presets from 57 to 73 rules. Those are not
adopted here: on this codebase they produce 1410 findings across 139
files, 73% of them require-safety-comment-for-type-assertion. They are
disabled in oxlint.config.ts with the rationale, so this upgrade keeps the
current lint policy while picking up the 0.6.0 fixes. The 57 pre-existing
rules pass clean on 0.6.0 with no changes.

deno.lock is regenerated by the deno smoke run.
alchemy moves 2.0.0-beta.79 -> 2.0.0-beta.81 in both cf-workers-alchemy
examples, in the catalog, and in the release-age exclusions.

beta.80 is the first alchemy line to declare stable-only Effect peer ranges:
effect, @effect/vitest, @effect/platform-bun, @effect/platform-node and
@effect/sql-* all become ^4.0.0. The rc-era copies of @effect/sql-d1,
@effect/sql-sqlite-do and @effect/vitest stop resolving, and nothing
resolves 4.0.0-rc.115 any more.

beta.81 rather than the latest (beta.83) because beta.82/83 resolve
@distilled.cloud/*@1.0.0-rc.15, published 2026-10-12T19:2x -- inside the
24h window the repo's supply-chain policy enforces. Lockfile verification
rejects it, and the release-age exclusions do not exempt verification even
though pnpm writes them itself, so a committed lockfile containing rc.15
fails 'pnpm install --frozen-lockfile' -- the command CI runs. beta.81
resolves @distilled.cloud/*@1.0.0-rc.13, published 2026-10-02.

'pnpm install --frozen-lockfile' passes and the examples typecheck 12/12.
The next sweep can go straight to alchemy's latest once rc.15 ages out.
`runSubcommand` only turned the aggregated per-runtime result into an exit
code inside `if (spec.forceExit)`, and only `integration` sets that flag:
it exists to work around the vitest-plugin/miniflare cleanup hang, not to
signal failure. Every other subcommand recorded `{ ok: false }` into
`results`, printed "x FAIL", and then returned normally, so
`NodeRuntime.runMain` exited 0.

The effect was that `pnpm test:unit` and `pnpm test:smoke` could not fail a
build. A deliberately failing unit test produced "1 failed | 32 passed
(33)" and exit code 0; a smoke run with a broken runtime reported
"4/5 passed" and exit code 0. `pnpm verify` and CI both include those
steps, so those gates were decorative.

Propagate failures for every subcommand, keeping `forceExit` as the hang
workaround. Verified: a failing unit run now exits 1 while a passing run
still exits 0, and smoke exits 1 when a runtime fails.
The catalog pinned effect, @effect/platform-node, @effect/platform-bun and
@effect/vitest to exactly 4.0.0. Because 'catalog:' feeds both the
devDependency and the peerDependency, every package published an exact
'effect: "4.0.0"' peer -- an RC-era habit, from when the 4.0.0-rc.* line was
still moving. It forces consumers onto a single patch release.

Widen the catalog to ^4.0.0 so consumers can take any 4.x patch. The
lockfile resolves the family to 4.0.3, the newest release older than the
24h window the repo's supply-chain policy enforces. 4.0.4 exists but was
published ~5h ago, and resolving it would make
'pnpm install --frozen-lockfile' -- the command CI runs -- fail with
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION until it ages out. 4.0.3 also
satisfies the @effect/sql-* packages alchemy resolves, which want ^4.0.3,
clearing the last effect-related peer warning.

The published peer stays "4.0.0 or above"; only the tested version moves.
A later in-range update can float the family to 4.0.4 once it clears the
policy window.
@LordCoughmann
LordCoughmann merged commit b5bacbf into main Oct 13, 2026
2 checks passed
@LordCoughmann
LordCoughmann deleted the chore/deps-sweep branch October 13, 2026 12:13
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