mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 06:24:41 +01:00
docs(pregate): Rust test attributes, workspace membership and rejected crate names; changelog for the port review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
c918ad2be4
commit
3d0976fd89
2 files changed
+9
-7
No files matched your search
+6
-4
@@ -2,22 +2,24 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
**Pregate gives touched Rust files a test lane, and runs a nested pnpm or vitest package with its own runner (#3344).** In a mixed Cargo and JavaScript repo, every touched `.rs` file failed `lanes` with "has no test lane", so /ship could not get a receipt, and a nested package's vitest tests ran under `bun test` from the repo root (about 98 false failures in the reporter's repo). Ported from #3346 by vilano93, whose two commits carry the feature; our commits on top quote the crate name and make the new fixtures hermetic.
|
||||
**Pregate gives touched Rust files a test lane, and runs a nested pnpm or vitest package with its own runner (#3344).** In a mixed Cargo and JavaScript repo, every touched `.rs` file failed `lanes` with "has no test lane", so /ship could not get a receipt, and a nested package's vitest tests ran under `bun test` from the repo root (about 98 false failures in the reporter's repo). Ported from #3346 by vilano93, whose two commits carry the feature; our commits on top close four findings from a security-focused review of the port and make the new fixtures hermetic.
|
||||
|
||||
### Fixed
|
||||
- **`lib/pregate/rust.ts`** (new, vilano93): a crate is the nearest Cargo.toml with `[package]`. Its `.rs` files under `tests/` or holding a `#[cfg(test)]` are tests, and every `.rs` file of a crate and its Cargo.toml select that crate's tests and those of every crate depending on it. Manifests are parsed as TOML, so renamed, inherited, dotted, table-form and target-specific dependencies all count, and a crate runs from the workspace it is a member of under Cargo's rules (members, exclude, `package.workspace`). Nothing runs cargo to build the graph.
|
||||
- **`lib/pregate/checks/lanes.ts`** (vilano93): selected Rust tests run per crate as `cargo test -p <name>` from the workspace root and are judged on the summed `test result:` lines; zero tests is ZERO-RUN and a missing cargo is incomplete. A JS/TS test owned by a nested package.json that declares vitest or jest runs from that package through the package manager its `packageManager` field or nearest lockfile names (`pnpm exec`, `yarn`, `bun x`, else `npx`).
|
||||
- **`lib/pregate/checks/lanes.ts`**: the crate name comes from the repo's Cargo.toml and reaches the lane's shell, so it is now quoted like every file and cwd. Before, a crate named `evil;touch pwned` ran `touch pwned` in the workspace (the lane only runs with `--allow-repo-commands`, under which the repo's tests run anyway, but no other input reached the shell unquoted).
|
||||
- **`lib/pregate/checks/lanes.ts`**: the crate name comes from the repo's Cargo.toml and reaches the lane's shell. Before, a crate named `evil;touch pwned` ran `touch pwned` in the workspace, and a name containing `{files}` spliced the file list into the command. A name outside Cargo's grammar (letters, digits, `_`, `-`) now gets no runner, so its files are unclaimed and the lane is incomplete, as Cargo would refuse the manifest anyway; a valid name is quoted like every file and cwd. The lane only runs with `--allow-repo-commands`, under which the repo's tests run anyway, but no other repo input reached the shell unquoted.
|
||||
- **`lib/pregate/rust.ts`**: Cargo `members` globs are matched per path component by a small linear matcher. The first cut used the policy glob matcher, which matched `[ab]` literally (a member listed that way lost its inherited workspace dependencies, so its tests were never selected) and backtracked for seconds on a hostile glob.
|
||||
- **`lib/pregate/rust.ts`**: a plain `#[test]` or `#[tokio::test]` function in `src/` makes the file a test, so a dependent crate tested that way runs when its dependency changes. The `#[cfg(...)]` scan is length-bounded, so a file of unclosed attributes no longer takes seconds.
|
||||
- **`lib/pregate/init-draft.ts`** (vilano93): `init` notes that Rust tests run per crate.
|
||||
|
||||
### Tests
|
||||
- `test/pregate-rust.test.ts` (new, vilano93) covers the crate model, the dependency forms, workspace membership, the cargo summary parser and three end-to-end lane runs. A new case runs a crate named `evil;touch pwned-by-crate-name` and checks that nothing is created and cargo receives the name as one argument; it fails before the quoting fix.
|
||||
- `test/pregate-rust.test.ts` (new, vilano93) covers the crate model, the dependency forms, workspace membership, the cargo summary parser and three end-to-end lane runs. New cases: crates named `evil;touch pwned-by-crate-name` and `evil{files}` never reach the shell (nothing is created, both are unclaimed) while `naïve_crate-2` still runs quoted; a `crates/[ab]` and a `nested/**/leaf` member inherit workspace dependencies; a plain `#[test]` dependent is selected; and a hostile members glob plus 20,000 unclosed `#[cfg(` finish quickly. Each failed (or hung) before its fix.
|
||||
- The cargo stand-in now wins PATH lookup everywhere. On windows-free-shard (5) two end-to-end cases failed deterministically because the shim PATH was joined with `:` (Git Bash never saw it) and the runner's real cargo ran against the fixture. On hosts where Bun and cargo share a directory, the lane puts Bun's directory first and the real cargo won the same way. The shim PATH now uses the platform delimiter, adds `cargo.cmd` for Windows lookup, and on POSIX the lane's bash puts the shim first again through `BASH_ENV`.
|
||||
- `test/pregate-selection.test.ts` (vilano93) covers nested pnpm/yarn/vitest/jest packages. Its `pnpm` stand-in gets the same `BASH_ENV` fix: on a host with a real pnpm beside Bun, the end-to-end case installed vitest from the network and came back incomplete.
|
||||
|
||||
### Gate integrity
|
||||
- No threshold, budget, timeout, trial count or case kind changed. Pregate's lanes now map and run tests for `.rs` files that previously failed closed with "no test lane", and nested vitest/jest packages run under their own runner instead of `bun test`. A `.rs` file outside any crate, a crate with no tests, and a missing cargo or package manager still fail closed or stay incomplete; the tests above cover each.
|
||||
- No new dependency (Cargo.toml is parsed with Bun's built-in TOML parser), no network access, no workflow change.
|
||||
- No new dependency (Cargo.toml is parsed with Bun's built-in TOML parser), no network call in pregate itself, no workflow change. As with the root runner detection on main (`npx vitest run`), a nested package's detected runner (`npx`, `bun x`) may fetch a missing tool when it runs under `--allow-repo-commands`.
|
||||
|
||||
## [1.91.186.0] - 2026-10-24
|
||||
|
||||
|
||||
+3
-3
@@ -59,7 +59,7 @@ the byte-pinned `/ship` renders in `test/fixtures/golden/`).
|
||||
|
||||
| Key | Meaning |
|
||||
|---|---|
|
||||
| `runner` | the local test command with `{files}` (gstack: `bun test {files}`); unset, it is detected (bun, vitest, jest, pytest, `node --test`, and `flutter test`/`dart test` per Dart package root, through fvm when that package or an ancestor pins it with `.fvmrc` or `.fvm/fvm_config.json` and fvm is on PATH; `cargo test -p <name>` per Rust crate, run from the nearest ancestor Cargo.toml that declares `[workspace]`, else the crate directory; a JS/TS test whose nearest package.json is a nested package declaring vitest or jest (a dependency or its `test` script) runs from that package, with package-relative paths, through the package manager its `packageManager` field or the nearest lockfile up to the repo root names: `pnpm exec`, `yarn`, `bun x`, else `npx`; every other JS/TS test keeps the root detection); nothing detected, a Dart SDK, cargo or package manager missing from PATH, a `.dart` file with no `pubspec.yaml` above it, or a `.rs` file outside any crate is `incomplete` (the runnable groups still run, so a real failure still fails) |
|
||||
| `runner` | the local test command with `{files}` (gstack: `bun test {files}`); unset, it is detected (bun, vitest, jest, pytest, `node --test`, and `flutter test`/`dart test` per Dart package root, through fvm when that package or an ancestor pins it with `.fvmrc` or `.fvm/fvm_config.json` and fvm is on PATH; `cargo test -p <name>` per Rust crate, run from the root of the workspace the crate is a member of (Cargo's `members` globs, `exclude` and `package.workspace`), else the crate directory; a JS/TS test whose nearest package.json is a nested package declaring vitest or jest (a dependency or its `test` script) runs from that package, with package-relative paths, through the package manager its `packageManager` field or the nearest lockfile up to the repo root names: `pnpm exec`, `yarn`, `bun x`, else `npx`; every other JS/TS test keeps the root detection); nothing detected, a Dart SDK, cargo or package manager missing from PATH, a `.dart` file with no `pubspec.yaml` above it, a `.rs` file outside any crate, or one in a crate whose name Cargo would reject (anything but letters, digits, `_` and `-`), is `incomplete` (the runnable groups still run, so a real failure still fails) |
|
||||
| `dependencies` | glob → test files for subprocess targets, runtime reads and generated inputs the import graph cannot see; `[]` declares "no lane needed" (docs, licences) |
|
||||
| `empty_lanes` | extra globs for the docs/no-tests empty lane. Any Markdown file already qualifies with no pin file when no test depends on it (the same import graph as other files: a quoted path, a `join()` of path segments, an import, or a `dependencies` entry). reStructuredText and AsciiDoc count as Markdown here. README, CHANGELOG, CONTRIBUTING, LICENSE, AGENTS and CLAUDE qualify even without `.md`, and so does licence text under any vendored name (`roboto-LICENSE.txt`, `LICENSE-MIT`, `licenses/*.txt`). Source code and files under a test directory never qualify. A test that reads the file still selects that test |
|
||||
| `selection` | `workflow.yml/job` → a command printing the lane's file list, for matrices a planner computes (gstack: `scripts/test-free-shards.ts --list`) |
|
||||
@@ -136,8 +136,8 @@ Two stages with separate clocks, both printed:
|
||||
`"**/test_driver/**": []`) under `dependencies` and let CI run them; Dart files, device tests
|
||||
included, are source code, so a `dependencies` `[]` declaration clears them and `empty_lanes`
|
||||
does not); in a Rust crate (the nearest Cargo.toml with a `[package]` name) a `.rs` file is a
|
||||
test when it sits under `<crate>/tests/` or holds a `#[cfg(test)]` (any cfg predicate naming
|
||||
`test`), and every `.rs` file of the crate and its Cargo.toml select the crate's tests and
|
||||
test when it sits under `<crate>/tests/`, holds a `#[cfg(test)]` (any cfg predicate naming
|
||||
`test`) or a test attribute (`#[test]`, `#[tokio::test]`), and every `.rs` file of the crate and its Cargo.toml select the crate's tests and
|
||||
those of every crate whose manifest depends on it, directly or through other crates (cargo
|
||||
runs a crate's tests, not a file, so the lane is the crate; a crate with no tests still has
|
||||
no lane, and a workspace-only Cargo.toml or Cargo.lock needs a `dependencies` entry),
|
||||
|
||||
Reference in new issue
Block a user