diff --git a/CHANGELOG.md b/CHANGELOG.md index 05973e2b..3e8ee306 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +- **Fixed** Failures while forwarding output from a started task process no longer incorrectly say the process failed to spawn ([#506](https://github.com/voidzero-dev/vite-task/issues/506)). - **Fixed** An issue where Bun tasks on macOS did not rerun when files they read, wrote, or listed changed ([#532](https://github.com/voidzero-dev/vite-task/issues/532), [#542](https://github.com/voidzero-dev/vite-task/pull/542)). - **Improved** Windows file-access tracking now uses sparse temporary backing files where supported, avoiding upfront allocation of the full backing file on disk ([#524](https://github.com/voidzero-dev/vite-task/pull/524)). - **Fixed** Automatic file-access tracking on Linux now works in containers and Kubernetes runners with limited `/dev/shm` space ([#353](https://github.com/voidzero-dev/vite-task/issues/353), [#523](https://github.com/voidzero-dev/vite-task/pull/523)). diff --git a/crates/vite_task/src/session/event.rs b/crates/vite_task/src/session/event.rs index 030000f5..3cdfb873 100644 --- a/crates/vite_task/src/session/event.rs +++ b/crates/vite_task/src/session/event.rs @@ -41,6 +41,10 @@ pub enum ExecutionError { #[error("Failed to spawn process")] Spawn(#[source] anyhow::Error), + /// The child process started, but the runner failed while forwarding its output. + #[error("Failed to forward task process output")] + ForwardTaskProcessOutput(#[source] anyhow::Error), + /// The child process started, but the runner failed while waiting for it to exit. #[error("Failed to wait for task process to exit")] WaitForTaskProcessExit(#[source] anyhow::Error), diff --git a/crates/vite_task/src/session/execute/mod.rs b/crates/vite_task/src/session/execute/mod.rs index 9f5438de..1813051e 100644 --- a/crates/vite_task/src/session/execute/mod.rs +++ b/crates/vite_task/src/session/execute/mod.rs @@ -598,7 +598,7 @@ async fn run_child( reason = "pipe_stdio streams child I/O and creates a large future" )] let r = pipe_stdio(stdout, stderr, sinks, fast_fail_token.clone()).await; - r.map_err(|err| ExecutionError::Spawn(err.into())) + r.map_err(|err| ExecutionError::ForwardTaskProcessOutput(err.into())) } else { Ok(()) }; diff --git a/crates/vite_task/src/session/reporter/summary.rs b/crates/vite_task/src/session/reporter/summary.rs index 76961ad0..b6ce1184 100644 --- a/crates/vite_task/src/session/reporter/summary.rs +++ b/crates/vite_task/src/session/reporter/summary.rs @@ -121,7 +121,7 @@ pub enum SpawnOutcome { /// No `infra_error` field: cache operations are skipped on non-zero exit. Failed { exit_code: NonZeroI32 }, - /// Could not start the process (e.g., command not found). + /// Execution failed without a usable process exit status. SpawnError(SavedExecutionError), } @@ -152,6 +152,7 @@ pub enum SavedCacheMissReason { pub enum SavedExecutionError { Cache { kind: SavedCacheErrorKind, message: Str }, Spawn { message: Str }, + ForwardTaskProcessOutput { message: Str }, WaitForTaskProcessExit { message: Str }, PostRunFingerprint { message: Str }, IpcServerBind { message: Str }, @@ -239,6 +240,9 @@ impl SavedExecutionError { ExecutionError::Spawn(source) => { Self::Spawn { message: vite_str::format!("{source:#}") } } + ExecutionError::ForwardTaskProcessOutput(source) => { + Self::ForwardTaskProcessOutput { message: vite_str::format!("{source:#}") } + } ExecutionError::WaitForTaskProcessExit(source) => { Self::WaitForTaskProcessExit { message: vite_str::format!("{source:#}") } } @@ -264,6 +268,9 @@ impl SavedExecutionError { Self::Spawn { message } => { vite_str::format!("Failed to spawn process: {message}") } + Self::ForwardTaskProcessOutput { message } => { + vite_str::format!("Failed to forward task process output: {message}") + } Self::WaitForTaskProcessExit { message } => { vite_str::format!("Failed to wait for task process to exit: {message}") } @@ -916,3 +923,27 @@ fn format_input_modified_notice(buf: &mut Vec, task_names: &[Str]) { let _ = write!(buf, " not cached because they modified their inputs."); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn output_forwarding_error_has_distinct_message() { + let error = ExecutionError::ForwardTaskProcessOutput(anyhow::anyhow!( + "Resource temporarily unavailable (os error 11)" + )); + + let saved = SavedExecutionError::from_execution_error(&error); + + assert!(matches!( + &saved, + SavedExecutionError::ForwardTaskProcessOutput { message } + if message.as_str() == "Resource temporarily unavailable (os error 11)" + )); + assert_eq!( + saved.display_message().as_str(), + "Failed to forward task process output: Resource temporarily unavailable (os error 11)" + ); + } +}