Skip to content

Commit 4176c4c

Browse files
committed
feat: add stdin suggestion to reporter for spawned tasks
Add StdinSuggestion enum to LeafExecutionReporter trait so reporters can suggest whether child processes should inherit stdin or use /dev/null. PlainReporter always suggests inherited stdin (single synthetic execution). LabeledReporter suggests inherited only when the graph has exactly one spawn leaf (computed via count_spawn_leaves at build time). The actual stdin is inherited only when BOTH conditions hold: - Reporter suggests Inherited - Task has no cache metadata (caching disabled) This prevents non-deterministic user input from corrupting cached output while allowing interactive stdin for single uncached tasks. Includes 15 unit tests for stdin suggestion logic and 3 E2E snapshot tests verifying stdin inheritance/null behavior end-to-end.
1 parent 0340b6c commit 4176c4c

13 files changed

Lines changed: 472 additions & 5 deletions

File tree

crates/vite_task/src/session/execute/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod fingerprint;
22
pub mod spawn;
33

4-
use std::sync::Arc;
4+
use std::{process::Stdio, sync::Arc};
55

66
use futures_util::FutureExt;
77
use petgraph::{algo::toposort, stable_graph::StableGraph};
@@ -23,7 +23,7 @@ use super::{
2323
},
2424
reporter::{
2525
ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, LeafExecutionPath,
26-
LeafExecutionReporter,
26+
LeafExecutionReporter, StdinSuggestion,
2727
},
2828
};
2929
use crate::{Session, session::execute::spawn::SpawnTrackResult};
@@ -252,6 +252,18 @@ pub async fn execute_spawn(
252252
let mut track_result_with_cache_metadata =
253253
cache_metadata.map(|cache_metadata| (SpawnTrackResult::default(), cache_metadata));
254254

255+
// Determine the child process's stdin mode based on:
256+
// - The reporter's suggestion (inherited only when appropriate, e.g., single task)
257+
// - Whether caching is disabled (inherited stdin would make output non-deterministic,
258+
// breaking cache semantics)
259+
let stdin = if leaf_reporter.stdin_suggestion() == StdinSuggestion::Inherited
260+
&& cache_metadata.is_none()
261+
{
262+
Stdio::inherit()
263+
} else {
264+
Stdio::null()
265+
};
266+
255267
// Execute command with tracking, streaming output in real-time via the reporter
256268
#[expect(
257269
clippy::large_futures,
@@ -260,6 +272,7 @@ pub async fn execute_spawn(
260272
let result = match spawn_with_tracking(
261273
&spawn_execution.spawn_command,
262274
cache_base_path,
275+
stdin,
263276
|kind, content| {
264277
leaf_reporter.output(
265278
match kind {

crates/vite_task/src/session/execute/spawn.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub struct SpawnTrackResult {
6262
/// Returns the execution result including captured outputs, exit status,
6363
/// and tracked file accesses.
6464
///
65+
/// - `stdin` controls the child process's stdin (typically `Stdio::null()` or `Stdio::inherit()`).
6566
/// - `on_output` is called in real-time as stdout/stderr data arrives.
6667
/// - `track_result` if provided, will be populated with captured outputs and path accesses for caching. If `None`, tracking is disabled.
6768
#[expect(
@@ -71,6 +72,7 @@ pub struct SpawnTrackResult {
7172
pub async fn spawn_with_tracking<F>(
7273
spawn_command: &SpawnCommand,
7374
workspace_root: &AbsolutePath,
75+
stdin: Stdio,
7476
mut on_output: F,
7577
track_result: Option<&mut SpawnTrackResult>,
7678
) -> anyhow::Result<SpawnResult>
@@ -90,7 +92,7 @@ where
9092
cmd.args(spawn_command.args.iter().map(vite_str::Str::as_str));
9193
cmd.envs(spawn_command.all_envs.iter());
9294
cmd.current_dir(&*spawn_command.cwd);
93-
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
95+
cmd.stdin(stdin).stdout(Stdio::piped()).stderr(Stdio::piped());
9496

9597
let mut tracking_state = if let Some(track_result) = track_result {
9698
// track_result is Some. Spawn with tracking enabled

0 commit comments

Comments
 (0)