-
Notifications
You must be signed in to change notification settings - Fork 1
Migrate subprocess spawns to running-process + regression linter #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| name: Lint subprocess spawns | ||
|
|
||
| # Regression guard for FastLED/fbuild#141: every subprocess fbuild | ||
| # starts must flow through the fbuild-core::subprocess wrappers (which | ||
| # are backed by running-process-core). Direct std::process::Command / | ||
| # tokio::process::Command spawns are only allowed when annotated with | ||
| # an // allow-direct-spawn: <reason> marker. | ||
| # | ||
| # Keeps pipe-deadlock and containment-drift bugs from creeping back in. | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| pull_request: | ||
| branches: [main] | ||
|
|
||
| env: | ||
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | ||
|
|
||
| jobs: | ||
| lint-subprocess: | ||
| name: Lint subprocess spawns | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: astral-sh/setup-uv@v3 | ||
| - name: Check no unannotated direct Command::new spawns | ||
| run: uv run python ci/find_direct_subprocess.py --fail |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,26 +2,38 @@ | |
| # /// script | ||
| # requires-python = ">=3.10" | ||
| # /// | ||
| """Find direct std::process / tokio::process spawn sites in fbuild crates. | ||
| """Linter: forbid direct `std::process::Command::new` / `tokio::process::Command::new` | ||
| outside of documented hold-outs. | ||
|
|
||
| Goal: every subprocess that fbuild starts should go through | ||
| `running-process` (via the wrappers in `fbuild-core::subprocess` and | ||
| `fbuild-core::containment`). This script enumerates every remaining | ||
| direct `Command::new(...)` site so they can be migrated and eliminated | ||
| one PR at a time. | ||
| Every subprocess fbuild starts must go through the | ||
| `fbuild-core::subprocess` wrappers (which are themselves backed by | ||
| [`running-process`](https://github.com/zackees/running-process) so | ||
| that containment, concurrent pipe draining, and Windows-specific env | ||
| handling are implemented once and cannot drift. | ||
|
|
||
| Tracked by FastLED/fbuild#141. | ||
|
|
||
| A site is allowlisted by placing this marker on the same line or on | ||
| the line immediately before the `Command::new(`: | ||
|
|
||
| // allow-direct-spawn: <one-line reason> | ||
|
|
||
| When this script reports zero non-allowlisted sites across the whole | ||
| workspace, delete it (and the marker comments) and rely on | ||
| `running-process` exclusively. Tracked by FastLED/fbuild#<issue>. | ||
| Intentional hold-outs currently allowed: | ||
| - Daemon spawns from CLI/Python/tests (daemon must outlive parent). | ||
| - zccache daemon bootstrap (independent lifecycle). | ||
| - containment module's own regression tests. | ||
| - Integration test harnesses that spawn binaries under test. | ||
| - tokio async streaming emulator handlers (QEMU, avr8js/node) where | ||
| NativeProcess's blocking API is unsuitable. | ||
| - tokio parallel async fan-out in the CLI (IWYU, clang-tidy) inside a | ||
| process that has no daemon containment group. | ||
|
|
||
| Run in CI with `--fail` so any new direct spawn without a marker | ||
| breaks the build. | ||
|
|
||
| Usage: | ||
| uv run python ci/find_direct_subprocess.py # report | ||
| uv run python ci/find_direct_subprocess.py --fail # exit 1 if >0 | ||
| uv run python ci/find_direct_subprocess.py --fail # exit 1 if any | ||
| uv run python ci/find_direct_subprocess.py --json # machine output | ||
|
Comment on lines
+31
to
37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Harden the scanner before making it build-breaking. With 🤖 Prompt for AI Agents |
||
| """ | ||
|
|
||
|
|
@@ -125,7 +137,13 @@ def render_text(hits: list[Hit]) -> str: | |
| lines.append(f" allowlisted: {len(allowed)}") | ||
| if pending: | ||
| lines.append("") | ||
| lines.append("To migrate (no allow-direct-spawn marker):") | ||
| lines.append( | ||
| "NEW direct spawns without an `allow-direct-spawn: <reason>` marker:" | ||
| ) | ||
| lines.append( | ||
| " (route via fbuild_core::subprocess::{run_command,run_command_passthrough}" | ||
| ) | ||
| lines.append(" or annotate with a one-line reason — see FastLED/fbuild#141)") | ||
| for h in pending: | ||
| rel = h.path.relative_to(REPO_ROOT) | ||
| lines.append(f" {rel}:{h.line_no}: {h.text.strip()}") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Doeszackees/setup-soldr@v0installuv, or should GitHub Actions workflows explicitly addastral-sh/setup-uvbefore runninguv run ...?💡 Result:
No, zackees/setup-soldr@v0 does not install uv. The action installs the soldr binary, provisions Rust via rustup (bootstrapping it if needed), sets up cache roots for Soldr/Cargo/rustup, and puts soldr on PATH. There is no mention of uv (the Python package manager) in its functionality or scripts. The repository zackees/setup-soldr has not been created or released as of 2026-04-24; it is planned for future extraction from zackees/soldr, with
@v0as the planned beta tag. Currently, use the in-repo action from zackees/soldr@ (pin by SHA or tag). To run uv run ... in GitHub Actions, explicitly add astral-sh/setup-uv before using uv, as setup-soldr (even when available) handles Rust/Soldr, not Python tooling.Citations:
🏁 Script executed:
Repository: FastLED/fbuild
Length of output: 1131
Add
astral-sh/setup-uvbefore the linter step.Line 33 runs
uv run ...but the job never provisionsuv. Thezackees/setup-soldr@v0action handles Rust tooling only, not Python package managers. Addastral-sh/setup-uv@v3(aslint-subprocess.ymldoes) before line 32 to fix the workflow failure.🤖 Prompt for AI Agents