turborepo
f4a33de1 - perf: Verify managed tools at setup instead of every run (#14911)

Commit
8 days ago
perf: Verify managed tools at setup instead of every run (#14911) ### Description `turbo exec` and `turbo setup` re-read every installed managed-tool file on every run. In a repository with Go, Node, pnpm, Python, and uv installed (615 MB, 19.5k files), `turbo exec -- node -v` took 17.7 s and a no-op `turbo setup` took 30 s. This PR moves byte verification to setup: - `turbo run` and `turbo exec` use a new `Verification::Shallow` check. It checks the manifest, the generation, the shims, the exported executables, and the user-owned setup record that binds the manifest. It never reads tool trees. - `turbo setup --check` and setup's offline repeat re-hash every byte (`Verification::Full`). `turbo setup --force` repairs from verified artifacts. When setup publishes a new generation, it re-hashes each tool it reuses and downloads a fresh copy if the bytes do not match. - The stat-stamp cache (`stamps.json`, `Verification::Stamped`, `windows_stat`) is deleted. A metadata-only change, such as an extended attribute that bumps ctime, made a stamp stale forever, so every later check re-hashed that tool. - On Unix, setup makes every published tool file read-only before it records the tree hash. Directories stay writable, so `rm -rf .turbo` and `git clean -fdx` still work. - `ManagedTools::inspect` no longer revalidates right after `with_current` already did. Every consumer revalidates at its use boundary. - On aarch64 macOS, `sha2` uses the ARMv8 SHA instructions (`asm` feature). Other targets are unchanged. The trust model for `run` and `exec` now matches the shell hook. Bytes are verified when setup installs them. A same-user process that edits an installed file in place is not detected until `turbo setup --check`. The same is true today for `node_modules/.bin` and for tools that version managers install. | Command (release build) | Before | After | | --- | --- | --- | | `turbo exec -- node -v` | 17.7 s | 23.5 ms (raw `node -v`: 11.8 ms) | | `turbo setup`, nothing to do | 29.4 to 30.7 s | 1.13 s | ### Testing Instructions - `cargo test -p turborepo-tool-install -p turborepo-setup`, `cargo test -p turborepo-cli --lib`, and `cargo test -p turbo --test setup`. - Manual smoke test in a repository with `futureFlags.experimentalSetup` and Go, Node, pnpm, Python, and uv in `turbo.lock`: 1. `turbo --skip-infer setup --force`. All files under the new generation's `tools/` are read-only and every directory is writable. 2. `turbo --skip-infer setup` twice. All tools report `reused`, and `pnpm install`, `uv sync`, and `go mod download` succeed. 3. `turbo --skip-infer exec -- node -v`, `go version`, `uv run python -c "print(1)"`, and `pnpm -v` succeed. 4. `turbo --skip-infer setup --check` succeeds. 5. Remove the `node` shim from the generation's `bin/`. `turbo exec -- node -v` fails with "managed tools are damaged or unsafe".
Author
Parents
Loading