Skip to content

Commit 37d75fb

Browse files
committed
cargo-rail: stable plan/test caching + runner/profile pinning + docs
1 parent 6104c38 commit 37d75fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+6223
-74
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ rayon = "1.11.0"
4747
winnow = "0.7.14"
4848
chrono = "0.4.42"
4949
glob = "0.3.3"
50+
syn = { version = "2.0.106", features = ["full", "parsing", "extra-traits"] }
51+
quote = "1.0.40"
5052

5153
[dev-dependencies]
5254
anyhow = "1.0.100"

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ infrastructure = [".github/**", "scripts/**", "*.sh"]
190190

191191
Full reference: [docs/config.md](docs/config.md)
192192

193+
Agent integration: [docs/agent-integration.md](docs/agent-integration.md)
194+
193195
---
194196

195197
## Real-World Results
@@ -271,7 +273,14 @@ Works via `cargo metadata`, which respects `.cargo/config.toml`.
271273
<details>
272274
<summary><strong>Does this replace Bazel/Buck2 for Rust teams?</strong></summary>
273275

274-
For pure Rust workspaces, yes... it can. `cargo-rail` provides graph-aware testing, dependency unification, and crate extraction without learning a new build system. If you're using Bazel/Buck2 *only* for Rust (not polyglot builds), cargo-rail gives you the key benefits — affected analysis, hermetic builds via lockfiles, crate distribution — while staying in Cargo's ecosystem. I'm exploring the best way to build a proper cache feature (local will come first; remote will follow), as well.
276+
For pure Rust workspaces, yes... it can. `cargo-rail` provides graph-aware testing, dependency unification, and crate extraction without learning a new build system. If you're using Bazel/Buck2 *only* for Rust (not polyglot builds), cargo-rail gives you the key benefits — affected analysis, lockfile/toolchain-aware reuse, and crate distribution — while staying in Cargo's ecosystem.
277+
278+
Today:
279+
- `cargo rail test` runs the minimal affected set and includes a conservative local cache for reusing successful test results (with explicit hit/miss reasons).
280+
- You can pin determinism-sensitive choices like the test runner via `--runner` or `[test].runner` in `rail.toml`.
281+
282+
Next:
283+
- Policy-gated remote cache storage (Phase 4.3) to reuse across CI runners.
275284
</details>
276285

277286
<details>

docs/agent-integration.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Agent Integration (Stable Interfaces)
2+
3+
cargo-rail is designed to be consumed by automation and AI agents without scraping logs.
4+
5+
## Output contract (important)
6+
7+
- **stdout** is reserved for command results (e.g. JSON).
8+
- **stderr** is reserved for progress, warnings, and human explanations.
9+
10+
See `docs/output.md`.
11+
12+
## Machine interfaces
13+
14+
Use these outputs for tooling:
15+
16+
- `--format json` (or global `--json`) for structured output.
17+
- Treat JSON as an API: all machine outputs include:
18+
- `schema` (string, e.g. `cargo-rail/context`)
19+
- `schema_version` (integer)
20+
21+
Compatibility rules and determinism expectations are defined in `docs/json-schemas.md`.
22+
23+
## Recommended flow (no log scraping)
24+
25+
### 1) Export context (ground truth)
26+
27+
Generate a single workspace context artifact:
28+
29+
```bash
30+
cargo rail context export --format json
31+
```
32+
33+
This writes `target/cargo-rail/context.json` and prints the JSON.
34+
35+
Use this artifact for:
36+
- workspace members list
37+
- toolchain/config/targets
38+
- workspace-member dependency edges
39+
- ownership roots summary
40+
- risk signals (proc-macro/build.rs/links)
41+
42+
### 2) Ask targeted questions via `query`
43+
44+
Use `query` when you need fast answers in stable formats:
45+
46+
```bash
47+
cargo rail query owner <path> --format json
48+
cargo rail query deps <crate> --format json
49+
cargo rail query rdeps <crate> --format json
50+
cargo rail query path <from> <to> --format dot
51+
```
52+
53+
Notes:
54+
- `owner` is the canonical “file → crate” mapping without heuristic log parsing.
55+
- `deps` / `rdeps` operate on workspace-member edges only (fast, stable).
56+
- `dot` is useful for graph visualization and tool ingestion where appropriate.
57+
58+
### 3) Compute impact and actions (CI/agents)
59+
60+
For change-driven workflows, prefer:
61+
62+
```bash
63+
cargo rail affected --format json
64+
```
65+
66+
Then use `query` to explain/visualize relationships as needed.
67+
68+
### 4) Plan executable tasks (stable, explainable)
69+
70+
When you need a deterministic “what should run?” artifact, use `plan`:
71+
72+
```bash
73+
cargo rail plan test --format json
74+
```
75+
76+
Notes:
77+
- `plan` emits stable task IDs and a machine-readable reason set for each task.
78+
- For deterministic snapshots across machines/runners, pin runner selection:
79+
- `cargo rail plan test --runner cargo-test --format json`
80+
- or configure `[test].runner = "cargo-test"` in `rail.toml`.
81+
82+
## Consumer guidelines
83+
84+
- Ignore unknown fields (forward compatible).
85+
- Treat unknown/missing `schema`/`schema_version` as unsupported.
86+
- Prefer `--format json` over parsing text output.

docs/architecture.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,45 @@ Why layered? Layer 1 is fast and testable. Layer 2 adds graph awareness. Layer 3
161161

162162
---
163163

164+
## Caching & Hermeticity (current state)
165+
166+
cargo-rail is intentionally **not** a separate build system. It aims to make Cargo runs:
167+
- smaller (run less work for most diffs),
168+
- more deterministic (explicit runner/profile choices),
169+
- and more cacheable (auditable reuse decisions).
170+
171+
### Local plan-result cache (Phase 4.2)
172+
173+
`cargo rail test` includes a conservative local cache that can reuse prior **successful** test results when inputs match.
174+
175+
Cache key = stable composition of:
176+
- A task identifier (stable hash of the runner command + selected packages + runner args).
177+
- A capsule (toolchain + configured targets + small env set + workspace manifest hash).
178+
- Safe inputs (base/head git SHAs + changed-paths hash + runner identity + flags like ignore-bin-crates).
179+
180+
The cache is intentionally conservative:
181+
- Disabled when there are uncommitted tracked changes.
182+
- Disabled when `Cargo.lock` is missing.
183+
- Disabled in `--all` mode.
184+
185+
Every run reports `cache: hit/miss/disabled (reason…)`.
186+
187+
### Hermeticity (what we can and can’t claim today)
188+
189+
cargo-rail does not claim fully hermetic builds yet. Today it can help teams get closer by:
190+
- Encouraging lockfile-driven dependency resolution (`Cargo.lock`).
191+
- Capturing toolchain intent (`rust-toolchain.toml`) and configured targets in the cache capsule.
192+
- Surfacing “risk” signals that often break hermeticity (proc-macros, build scripts, native `links` crates).
193+
194+
However, true hermeticity also depends on:
195+
- system libraries and toolchains (e.g., native dependencies, linker state),
196+
- environment variables outside the capsule,
197+
- and CI runner images.
198+
199+
Phase 4.3+ extends reuse beyond a single machine by adding policy-gated remote cache storage.
200+
201+
---
202+
164203
## Unify Pipeline
165204

166205
```

0 commit comments

Comments
 (0)