Skip to content

Support vitest 5 - #86

Open
GuillaumeLagrange wants to merge 7 commits into
mainfrom
cod-2931-prepare-compatibility-with-vitest-5
Open

GuillaumeLagrange wants to merge 7 commits into
mainfrom
cod-2931-prepare-compatibility-with-vitest-5

Conversation

@GuillaumeLagrange

@GuillaumeLagrange GuillaumeLagrange commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

TL;DR

@codspeed/vitest-plugin now supports Vitest 5 as well as 3 and 4. The plugin detects which Vitest is installed and hooks into it the right way. Users on Vitest 3/4 see no change.

What changes for users

  • vitest peer range is now ^3.2 || ^4 || ^5.

  • On Vitest 5, benchmarks are written with Vitest's new bench fixture, and CodSpeed picks them up as-is:

    test("fibo 15", async ({ bench }) => {
      await bench.compare(
        bench("recursive", () => recursiveFibonacci(15)),
        bench("iterative", () => iterativeFibonacci(15)),
      );
    });

    Each bench() in a bench.compare() group is reported as its own benchmark: file.bench.ts::fibo 15::recursive.

  • Without CodSpeed, the plugin does nothing and Vitest runs benchmarks normally.

How it works

Vitest 5 removed the benchmark runner the plugin used to extend. Benchmarks now run through a benchmark.provider module instead.

  • Vitest 3/4: same custom runner as before, moved under src/legacy/.
  • Vitest 5: CodSpeed registers itself as the benchmark provider (src/v5/provider.ts). It runs each benchmark once under instrumentation in simulation mode, or drives tinybench and records walltime results in walltime mode.
  • src/vitestBackend.ts picks one of the two based on the installed Vitest version; code shared by both lives in src/instrument.ts.
  • globalSetup now tolerates running twice, since Vitest 5 runs it once per project and clones a separate benchmark project.

Also in this PR

  • fix(core): getGitDir now finds the repository root when .git is a file (git worktrees, submodules). Before, every plugin failed with "Could not find a git repository" when run from a worktree. Inside a submodule, benchmark URIs are now relative to the submodule. Also drops the find-up dependency.
  • New with-vitest-v4 and with-vitest-v5 examples, so CI covers every supported major.
  • README shows the Vitest 5 fixture API.
  • CLAUDE.md documents how to exercise a plugin in the three CodSpeed modes.

Testing

Ran locally:

  • pnpm turbo run build lint typecheck format test test/integ passes.
  • with-vitest-v3, with-vitest-v4 and with-vitest-v5 examples, plus the plugin's own benches, in fallback, simulation and walltime modes.

Known limitations

  • The Vitest version is detected from the current working directory. If the Vitest that actually runs differs from the one resolved there (e.g. running a project's vitest binary with --root from another directory), the wrong integration is picked and nothing gets measured, silently. Vitest has no documented way for plugins to read its version early enough; a follow-up could resolve it from the running binary and fail loudly on a mismatch.
  • On Vitest 5, the per-benchmark [CodSpeed] Checked … lines only show with --reporter=verbose.
  • The Vitest 5 simulation path doesn't call mongoMeasurement.start/stop around benchmarks, unlike the Vitest 3/4 runner.

Refs COD-2931

@GuillaumeLagrange GuillaumeLagrange changed the title Cod 2931 prepare compatibility with vitest 5 Support vitest 5 Jun 29, 2026
Comment thread packages/vitest-plugin/src/v5/setup.ts Outdated
@GuillaumeLagrange
GuillaumeLagrange force-pushed the cod-2931-prepare-compatibility-with-vitest-5 branch 5 times, most recently from 25ef927 to e04f0da Compare July 1, 2026 08:59
@codspeed

codspeed Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 4 benchmarks

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 4 improved benchmarks
❌ 4 regressed benchmarks
✅ 177 untouched benchmarks
🆕 79 new benchmarks
⏩ 53 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Simulation switch 1 204.5 µs 689.9 µs -70.37%
❌ Memory wait 500ms 15.5 KB 21.5 KB -27.99%
❌ Simulation iterative fibo 20 26.9 µs 30.7 µs -12.36%
❌ WallTime test_recursive_cached_fibo_10 2.3 µs 2.6 µs -12.09%
⚡ Simulation recursive fibo 10 1,372.1 µs 299.9 µs ×4.6
⚡ Simulation recursive fibo 15 636.9 µs 352.1 µs +80.88%
⚡ WallTime switch 1 84 ns 72 ns +16.67%
⚡ WallTime test_iterative_fibo_10 120 ns 108 ns +11.11%
🆕 WallTime iterative fibo 15 N/A 672 ns N/A
🆕 WallTime iterative fibo 20 N/A 672 ns N/A
🆕 WallTime recursive fibo 15 N/A 20.4 µs N/A
🆕 WallTime recursive fibo 20 N/A 219.2 µs N/A
🆕 WallTime iterative N/A 552 ns N/A
🆕 WallTime recursive N/A 20.2 µs N/A
🆕 WallTime iterative N/A 564 ns N/A
🆕 WallTime recursive N/A 218.9 µs N/A
🆕 WallTime fibo 10 N/A 2.3 µs N/A
🆕 WallTime fibo 15 N/A 20.3 µs N/A
🆕 WallTime long body N/A 267.2 µs N/A
🆕 WallTime short body N/A 1.5 µs N/A
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing cod-2931-prepare-compatibility-with-vitest-5 (9007e6e) with main (3258048)

Open in CodSpeed

Footnotes

  1. 53 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@GuillaumeLagrange
GuillaumeLagrange force-pushed the cod-2931-prepare-compatibility-with-vitest-5 branch 2 times, most recently from f511dee to c3a356b Compare July 1, 2026 12:57
@greptile-apps

greptile-apps Bot commented Jul 19, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[High impact] Rewrites the vitest plugin to support version 5.

This is close, but the backend fallback should be fixed before merging.

Fix All in Claude CodeFindings

  1. P1 Fallback Picks Wrong Backend ▶
Fix with agent prompt
### Issue 1
packages/vitest-plugin/src/vitestBackend.ts:41
When Vitest cannot be resolved from `process.cwd()`, this still falls back to the v5 backend. A supported Vitest 3 or 4 project can hit this when the run starts outside the package root or from a workspace layout where `createRequire(join(process.cwd(), "package.json"))` cannot resolve that package's `vitest/package.json`. The plugin then wires `benchmark.provider` instead of the legacy runner, so CodSpeed does not install the Vitest 3/4 benchmark runner and the run can execute without CodSpeed instrumentation.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR adds Vitest 5 support to the Vitest plugin. The main changes are:

  • A new Vitest 5 benchmark provider.
  • Legacy Vitest 3/4 runner code moved under legacy.
  • Updated plugin config selection by Vitest major version.
  • New Vitest 4 and Vitest 5 examples.
  • Updated benchmark fixtures, docs, and package versions.

Reviews (2) · Last reviewed commit: "docs(vitest-plugin): show the vitest 5 b..." · Reviewed by Greptile

Comment thread packages/vitest-plugin/src/globalSetup.ts Outdated
@HiDeoo HiDeoo mentioned this pull request Sep 3, 2026
2 of 3 tasks
@GuillaumeLagrange
GuillaumeLagrange force-pushed the cod-2931-prepare-compatibility-with-vitest-5 branch from eec7ec7 to eb2042e Compare September 4, 2026 16:46
@florian-lefebvre

Copy link
Copy Markdown

Hi @GuillaumeLagrange, what's the status of this PR? We would need it for Astro

@GuillaumeLagrange

GuillaumeLagrange commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @GuillaumeLagrange, what's the status of this PR? We would need it for Astro

Hey! The support for the benchmark provider has been merged and released upstream by vitest, we plan to merge and release this PR early this week! Don't hesitate to continue pinging me to get updates, and sorry about the delay

@GuillaumeLagrange
GuillaumeLagrange force-pushed the cod-2931-prepare-compatibility-with-vitest-5 branch 2 times, most recently from d6abe82 to 9007e6e Compare September 30, 2026 12:58
@JavierGOrdonnez

Copy link
Copy Markdown

Hi @GuillaumeLagrange, what's the status of this PR? I would need it for various projects. Thanks!

GuillaumeLagrange and others added 7 commits October 12, 2026 15:01
`getGitDir` only accepted a `.git` directory, but in a git worktree or a
submodule `.git` is a file pointing at the real git dir. Every benchmark
URI lookup then threw "Could not find a git repository", so running any
plugin under CodSpeed from a worktree failed.

Accept a `.git` entry of either kind. Inside a submodule, URIs are now
relative to the submodule root instead of the parent repository, which
matches `git rev-parse --show-toplevel`.

Walk up the directories directly instead of going through `find-up`,
which was only used here and is ESM-only, and drop the dependency.

Co-Authored-By: Claude <noreply@anthropic.com>
The unit tests load `@codspeed/core` from its build, which bundles its
dependencies, so `find-up` and its dependencies were never loaded from
`node_modules`. Core no longer depends on them either. Only `stack-trace`
still needs the ESM transform.

Co-Authored-By: Claude <noreply@anthropic.com>
A plugin behaves differently depending on whether CodSpeed drives the run,
and each mode takes a different path through the plugin, so all three have
to be run when developing or reviewing one. Write down the commands and the
expected output per mode, and ignore the local `.codspeed` result directory
those runs produce.

Co-Authored-By: Claude <noreply@anthropic.com>
Vitest 5 removed the dedicated `NodeBenchmarkRunner` and the `vitest/runners`
/ `vitest/suite` entrypoints. Benchmarks are now declared through a `bench`
test-context fixture and executed by a `benchmark.provider`: a module Vitest
hands the registered functions, their options and the declaring test, and
whose results it treats as authoritative.

Detect the installed Vitest generation and select the integration behind a
`VitestBackend` abstraction so the rest of the plugin never inspects the
version:
- v3/4 keep the custom benchmark runner per instrument mode. Their Vitest
  lookups move behind `legacy/compat`, which owns the types of the removed
  benchmark backend so the package type-checks against Vitest 5.
- v5 registers CodSpeed as the benchmark provider, which runs the analysis
  and walltime modes off the registrations it receives.

On v5, benchmark URIs carry the registration name after the test path, so a
test declaring several benchmarks through `bench.compare()` reports one
benchmark per registration.

Gate the injection on the instrument mode: Vitest 5 clones its benchmark
project after the Vite config hooks ran, so a benchmark run can no longer be
detected from the incoming config, and CodSpeed only ever drives benchmark
runs. Without CodSpeed the plugin injects nothing and Vitest runs the
benchmarks through its own tinybench provider.

Vitest 5 also runs `globalSetup` once per project, including the cloned
benchmark project, so make setup and teardown idempotent instead of failing
the run on the second teardown.

Bump the plugin's own dev dependency to Vitest 5 and move its benches to the
fixture API, reading imported bindings into a local before the measured loop
so the module-runner getters stay out of the samples.

Refs COD-2931
Co-Authored-By: Claude <noreply@anthropic.com>
Now that the plugin's own dev dependency tracks Vitest 5, add a dedicated
Vitest 4 example so the legacy (v3/4) benchmark seam keeps explicit coverage
alongside the existing with-vitest-v3 example. Mirrors that example, pinning
vitest ^4.1.9.

Refs COD-2931
Co-Authored-By: Claude <noreply@anthropic.com>
Benchmark the plugin against Vitest 5 in CI the way the v3 and v4 examples
do for their majors, using the `bench` fixture and `bench.compare()`.

Refs COD-2931
Co-Authored-By: Claude <noreply@anthropic.com>
Benchmarks are declared through the `bench` test-context fixture on Vitest 5;
keep the top-level `bench()` form as a note for Vitest 3 and 4. Drop the
fallback log line from the sample output, which the plugin no longer prints.

Refs COD-2931
Co-Authored-By: Claude <noreply@anthropic.com>
@GuillaumeLagrange
GuillaumeLagrange force-pushed the cod-2931-prepare-compatibility-with-vitest-5 branch from 9007e6e to 986310d Compare October 12, 2026 13:01
@GuillaumeLagrange
GuillaumeLagrange marked this pull request as ready for review October 12, 2026 13:02
* When the version cannot be detected we assume the latest supported major.
*/
export function resolveVitestBackend(): VitestBackend {
const major = getVitestMajorVersion() ?? 5;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Fallback Picks Wrong Backend

When Vitest cannot be resolved from process.cwd(), this still falls back to the v5 backend. A supported Vitest 3 or 4 project can hit this when the run starts outside the package root or from a workspace layout where createRequire(join(process.cwd(), "package.json")) cannot resolve that package's vitest/package.json. The plugin then wires benchmark.provider instead of the legacy runner, so CodSpeed does not install the Vitest 3/4 benchmark runner and the run can execute without CodSpeed instrumentation.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/vitest-plugin/src/vitestBackend.ts
Line: 41

Comment:
**Fallback Picks Wrong Backend**

When Vitest cannot be resolved from `process.cwd()`, this still falls back to the v5 backend. A supported Vitest 3 or 4 project can hit this when the run starts outside the package root or from a workspace layout where `createRequire(join(process.cwd(), "package.json"))` cannot resolve that package's `vitest/package.json`. The plugin then wires `benchmark.provider` instead of the legacy runner, so CodSpeed does not install the Vitest 3/4 benchmark runner and the run can execute without CodSpeed instrumentation.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

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.

4 participants