Skip to content

test(vite-tests): reuse the shared root vite checkout#10325

Merged
graphite-app[bot] merged 1 commit into
mainfrom
07-17-test_vite-tests_reuse_the_shared_root_vite_checkout
Jul 17, 2026
Merged

test(vite-tests): reuse the shared root vite checkout#10325
graphite-app[bot] merged 1 commit into
mainfrom
07-17-test_vite-tests_reuse_the_shared_root_vite_checkout

Conversation

@shulaoda

@shulaoda shulaoda commented Jul 16, 2026

Copy link
Copy Markdown
Member

Follow-up to the review comments on #10318 and #10319: both test projects should be set up from the single vite/ checkout at the workspace root, via the just setup-vite checkout step.

Change

packages/vite-tests/run.ts no longer clones vitejs/vite from GitHub on its own. It now:

  1. calls ensureViteCheckout() from scripts/src/setup-vite/checkout.ts (the checkout step of just setup-vite), which guarantees the root vite/ checkout exists and is at the latest rolldown-canary rebased onto the latest main, exactly what test(test-dev-server): drop the vite submodule, track rolldown-canary #10319 set up for the dev-server tests.
  2. clones that checkout locally into ./repo and runs Vite's test suite there. The local clone shares objects via hardlinks, so no extra network download. It stays a throwaway copy because this suite must edit tracked files (rewrite the pnpm overrides to point rolldown at the workspace package, which also rewrites the lockfile on install), while vite/ itself must stay unpatched: the dev-server setup installs it with --frozen-lockfile and builds it with Vite's own pinned rolldown, so the two harnesses would corrupt each other's state if they shared one working copy.

Both harnesses therefore run on exactly the same Vite code: one checkout, one rebase result, no chance of the two suites drifting apart because rolldown-canary or main moved between two independent clones.

Per the review discussion on #10319, an existing checkout is kept up to date as well: when it is clean and on rolldown-canary (the managed state), every setup fetches and re-derives the latest rolldown-canary rebased onto main (kept as-is when the fetch fails, e.g. offline). A checkout taken over by the developer (dirty, or switched to another branch) is used exactly as-is, with a notice, so local experiments inside vite/ are never trampled and can still be tested through both harnesses.

Also restores the checkout.ts include in packages/vite-tests/tsconfig.json and updates the docs accordingly.

Verification

  • Local smoke run: run.ts picks up the shared checkout, clones it locally, and proceeds through install, build, and into the test suites.
  • All three checkout states exercised live: a clean checkout on rolldown-canary was updated to the latest upstream state; a dirty checkout and a detached HEAD were left as-is with a notice.
  • just lint fully green.

shulaoda commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

How to use the Graphite Merge Queue

Add the label graphite: merge-when-ready to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@shulaoda
shulaoda marked this pull request as ready for review July 16, 2026 16:45
@shulaoda
shulaoda requested a review from sapphi-red as a code owner July 16, 2026 16:45
@shulaoda
shulaoda force-pushed the 07-17-test_vite-tests_reuse_the_shared_root_vite_checkout branch from 5830016 to 9dc7939 Compare July 17, 2026 03:47
@h-a-n-a

h-a-n-a commented Jul 17, 2026

Copy link
Copy Markdown
Member

There is a staleness window in how run.ts reuses the shared checkout.

packages/vite-tests/run.ts calls ensureViteCheckout(), which can move vite/ to a new commit — but nothing rebuilds the dev-server side afterwards. loadVite() in test-dev-server only checks that vite/packages/vite/dist exists, not that it matches the current checkout. Whenever upstream rolldown-canary or main moved since the last setup (the normal case), this happens:

just setup-vite          → vite/ at commit A, dist built from A     ✔ consistent
run vite-tests           → ensureViteCheckout() moves vite/ to B
                           dist is still built from A
next browser-test run    → loadVite() finds dist → silently tests A

So a vite-tests run can silently invalidate the dev-server test results.

Let's make the setup follow one rule instead:

  • just setup-vite is the only entry point that touches vite/. It sets the commit (latest rolldown-canary rebased onto main) and finishes the whole setup — install, vite build, rolldown link — in one pass, for both test projects.
  • Scripts in test-dev-server and vite-tests never do setup themselves. They use the prepared checkout as-is and go straight to testing. run.ts should drop the ensureViteCheckout() call and just clone vite/; when vite/ is missing, fail with a "run just setup-vite first" hint, the same way loadVite() already does. (The checkout.ts import and the tsconfig include can then be reverted again.)

With that rule the checkout and the built dist can never drift apart: the only command that moves the commit also rebuilds everything right after.

For CI this means the vite-tests jobs get a setup step before run.ts, like the dev-server workflow already has.

@h-a-n-a h-a-n-a left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approved with minor changes in comment section above

@graphite-app

graphite-app Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Merge activity

Follow-up to the review comments on #10318 and #10319: both test projects should be set up from the single `vite/` checkout at the workspace root, via the `just setup-vite` checkout step.

## Change

`packages/vite-tests/run.ts` no longer clones vitejs/vite from GitHub on its own. It now:

1. calls `ensureViteCheckout()` from `scripts/src/setup-vite/checkout.ts` (the checkout step of `just setup-vite`), which guarantees the root `vite/` checkout exists and is at the latest `rolldown-canary` rebased onto the latest `main`, exactly what #10319 set up for the dev-server tests.
2. clones that checkout locally into `./repo` and runs Vite's test suite there. The local clone shares objects via hardlinks, so no extra network download. It stays a throwaway copy because this suite must edit tracked files (rewrite the pnpm overrides to point `rolldown` at the workspace package, which also rewrites the lockfile on install), while `vite/` itself must stay unpatched: the dev-server setup installs it with `--frozen-lockfile` and builds it with Vite's own pinned rolldown, so the two harnesses would corrupt each other's state if they shared one working copy.

Both harnesses therefore run on exactly the same Vite code: one checkout, one rebase result, no chance of the two suites drifting apart because `rolldown-canary` or `main` moved between two independent clones.

Per the review discussion on #10319, an existing checkout is kept up to date as well: when it is clean and on `rolldown-canary` (the managed state), every setup fetches and re-derives the latest `rolldown-canary` rebased onto `main` (kept as-is when the fetch fails, e.g. offline). A checkout taken over by the developer (dirty, or switched to another branch) is used exactly as-is, with a notice, so local experiments inside `vite/` are never trampled and can still be tested through both harnesses.

Also restores the `checkout.ts` include in `packages/vite-tests/tsconfig.json` and updates the docs accordingly.

## Verification

- Local smoke run: `run.ts` picks up the shared checkout, clones it locally, and proceeds through install, build, and into the test suites.
- All three checkout states exercised live: a clean checkout on `rolldown-canary` was updated to the latest upstream state; a dirty checkout and a detached HEAD were left as-is with a notice.
- `just lint` fully green.
@graphite-app
graphite-app Bot force-pushed the 07-16-test_test-dev-server_drop_the_vite_submodule_track_rolldown-canary branch from d4411c9 to da36734 Compare July 17, 2026 04:25
@graphite-app
graphite-app Bot force-pushed the 07-17-test_vite-tests_reuse_the_shared_root_vite_checkout branch from 9dc7939 to b9a3919 Compare July 17, 2026 04:26
Base automatically changed from 07-16-test_test-dev-server_drop_the_vite_submodule_track_rolldown-canary to main July 17, 2026 04:29
@graphite-app
graphite-app Bot merged commit b9a3919 into main Jul 17, 2026
29 of 30 checks passed
@graphite-app
graphite-app Bot deleted the 07-17-test_vite-tests_reuse_the_shared_root_vite_checkout branch July 17, 2026 04:30

@hyfdev hyfdev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Post-merge flag: if this review had landed before merge, the verdict would have been Request changes on one local correctness issue with the shared-checkout design.

packages/vite-tests/run.ts calls ensureViteCheckout(), which on a managed clean rolldown-canary checkout fetches and rebases vite/ HEAD, but never rebuilds vite/packages/vite/dist. The browser suite only checks that the dist file exists, so after a local vite-tests run the two harnesses can diverge: vite-tests on source B, browser suite still loading dist from A. That breaks the "both harnesses run on the same Vite code" invariant this PR states for the local sequential workflow. CI is fine because each job starts without a prior checkout.

Keeping auto-update only in the full just setup-vite path (checkout + install + build + link), and having run.ts ensure the checkout exists without moving HEAD, is one possible fix. Making any HEAD move force a rebuild before either harness proceeds is another.

I also left two non-blocking notes on the update path (local commits wiped by checkout -B, and failed-rebase sticky "as-is").

// checkout must stay unpatched. The clone shares objects via hardlinks, so
// no network is needed beyond the checkout itself.
printTitle('# Ensuring the vite checkout...');
ensureViteCheckout();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This call can advance a managed vite/ HEAD without rebuilding vite/packages/vite/dist.

ensureViteCheckout() (via updateViteCheckout) does fetch + checkout -B rolldown-canary origin/rolldown-canary + rebase origin/main when the tree is clean and on rolldown-canary. This suite then clones that source into ./repo and builds there, so vite-tests themselves are fine. The browser suite, however, only checks that vite/packages/vite/dist/node/index.js exists (loadVite in packages/test-dev-server/src/vite-server.ts) and never compares it to HEAD.

Local sequence:

  1. just setup-vitevite/ @ A, dist built from A
  2. vp run --filter vite-tests testvite/ moved to B, dist still from A
  3. browser suite → loads dist A while the shared checkout source is B

That is a silent harness divergence for the sequential local workflow this PR documents. CI jobs are separate and always hit the missing-checkout path, so they do not exercise this.

This would have blocked merge. Auto-updating only inside the full just setup-vite path (so every HEAD move is followed by install + build + link), or failing loudly when dist does not match HEAD, are possible directions.

console.log('[setup-vite] fetch failed, using the existing checkout as-is');
return;
}
run('git checkout -B rolldown-canary origin/rolldown-canary', viteDir);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

git checkout -B rolldown-canary origin/rolldown-canary resets the branch tip. A clean local tree that is on rolldown-canary with committed-but-unpushed work is treated as managed and those commits are discarded (recoverable only via reflog).

"Taken over" today means dirty working tree or not on the branch name. Local canary experiments that were committed but not pushed are not protected. Documenting that managed checkouts are reset to origin/rolldown-canary, or also treating unpushed commits as takeover, would make the contract explicit.

This does not block this approval.

return;
}
run('git checkout -B rolldown-canary origin/rolldown-canary', viteDir);
run('git rebase origin/main', viteDir);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this rebase fails (conflict, or no committer identity), execSync throws and the process exits with a rebase-in-progress or conflicted tree. The next ensureViteCheckout sees a non-empty git status --porcelain and takes the "using it as-is" branch, so a one-shot failure becomes a sticky broken checkout that later setups treat as intentional developer takeover.

Aborting a failed rebase (or refusing to proceed when a rebase is in progress) would keep the failure recoverable. This does not block this approval.

graphite-app Bot pushed a commit that referenced this pull request Jul 17, 2026
#10332)

Fixes the staleness window pointed out in #10325 (comment): `run.ts` called `ensureViteCheckout()`, which can move `vite/` to a new commit, but nothing rebuilds the dev-server side afterwards. `loadVite()` in test-dev-server only checks that `vite/packages/vite/dist` exists, not that it matches the checkout, so a vite-tests run could silently invalidate the dev-server test results.

## Change

**`just setup-vite`** **is the only entry point that touches** **`vite/`.** It sets the commit (the latest `rolldown-canary` rebased onto the latest `main`) and finishes the whole setup (install, vite build, rolldown link) in one pass, so the checkout and the built vite dist can never drift apart.

**`packages/vite-tests/run.ts`** **does no setup anymore.** It clones the prepared `vite/` checkout locally and goes straight to testing; when the checkout is missing it fails with a "run `just setup-vite` first" hint, like `loadVite()` already does. The `checkout.ts` import and the tsconfig include are reverted.

On CI, the vite-test jobs gain a setup-vite step before `run.ts`, like the dev-server workflow already has.

## Verification

- Missing checkout: `run.ts` fails with the "run `just setup-vite` first" hint.
- Normal path: `run.ts` clones the prepared checkout and proceeds through install, build, and into the test suites.
- `ci.yml` parses, both vite-test jobs have the setup step, and `just lint` is fully green.

<!--
- What is this PR solving? Write a clear and concise description.
- Reference the issues it solves (e.g. `fixes #123`).
- What other alternatives have you explored?
- Are there any parts you think require more attention from reviewers?

Also, please make sure you do the following:

- Read the Contributing Guidelines at https://rolldown.rs/contribution-guide/.
- Check that there isn't already a PR that solves the problem the same way. If you find a duplicate, please help us review it.
- Update the corresponding documentation if needed.
- Include relevant tests that fail without this PR but pass with it. If the tests are not included, explain why.

Thank you for contributing to Rolldown!
-->
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.

3 participants