diff --git a/crates/vite_task/src/cli/mod.rs b/crates/vite_task/src/cli/mod.rs index 7e6a76d4..bdb21736 100644 --- a/crates/vite_task/src/cli/mod.rs +++ b/crates/vite_task/src/cli/mod.rs @@ -17,6 +17,7 @@ pub enum CacheSubcommand { /// Extracted as a separate struct so they can be cheaply `Copy`-ed /// before `RunCommand` is consumed. #[derive(Debug, Clone, Copy, clap::Args)] +#[expect(clippy::struct_excessive_bools, reason = "CLI flags are naturally boolean")] pub struct RunFlags { /// Run tasks found in all packages in the workspace, in topological order based on package dependencies. #[clap(default_value = "false", short, long)] @@ -29,23 +30,43 @@ pub struct RunFlags { /// Do not run dependencies specified in `dependsOn` fields. #[clap(default_value = "false", long)] pub ignore_depends_on: bool, + + /// Show full detailed summary after execution. + #[clap(default_value = "false", short = 'v', long)] + pub verbose: bool, } -/// Arguments for the `run` subcommand. +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Public CLI types (clap-parsed) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/// Arguments for the `run` subcommand as parsed by clap. +/// +/// Contains the `--last-details` flag which is resolved into a separate +/// `ResolvedCommand::RunLastDetails` variant internally. #[derive(Debug, clap::Args)] pub struct RunCommand { /// `packageName#taskName` or `taskName`. If omitted, lists all available tasks. - pub task_specifier: Option, + pub(crate) task_specifier: Option, #[clap(flatten)] - pub flags: RunFlags, + pub(crate) flags: RunFlags, /// Additional arguments to pass to the tasks #[clap(trailing_var_arg = true, allow_hyphen_values = true)] - pub additional_args: Vec, + pub(crate) additional_args: Vec, + + /// Display the detailed summary of the last run. + #[clap(long, exclusive = true)] + pub(crate) last_details: bool, } -/// vite task CLI subcommands +/// vite task CLI subcommands as parsed by clap. +/// +/// vite task CLI subcommands as parsed by clap. +/// +/// Pass directly to `Session::main` or `HandledCommand::ViteTaskCommand`. +/// The `--last-details` flag on the `run` subcommand is resolved internally. #[derive(Debug, Parser)] pub enum Command { /// Run tasks @@ -57,6 +78,68 @@ pub enum Command { }, } +impl Command { + /// Resolve the clap-parsed command into the dispatched [`ResolvedCommand`] enum. + /// + /// When `--last-details` is set on the `run` subcommand, this produces + /// [`ResolvedCommand::RunLastDetails`] instead of [`ResolvedCommand::Run`], + /// making the exclusivity enforced at the type level. + #[must_use] + pub(crate) fn into_resolved(self) -> ResolvedCommand { + match self { + Self::Run(run) if run.last_details => ResolvedCommand::RunLastDetails, + Self::Run(run) => ResolvedCommand::Run(run.into_resolved()), + Self::Cache { subcmd } => ResolvedCommand::Cache { subcmd }, + } + } +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Internal resolved types (used for dispatch — `--last-details` is a separate variant) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/// Resolved CLI command for internal dispatch. +/// +/// Unlike [`Command`], this enum makes `--last-details` a separate variant +/// ([`ResolvedCommand::RunLastDetails`]) so that it is exclusive at the type level — +/// there is no way to combine it with task execution fields. +#[derive(Debug)] +pub enum ResolvedCommand { + /// Run tasks with the given parameters. + Run(ResolvedRunCommand), + /// Display the saved detailed summary of the last run (`--last-details`). + RunLastDetails, + /// Manage the task cache. + Cache { subcmd: CacheSubcommand }, +} + +/// Resolved arguments for executing tasks. +/// +/// Does not contain `last_details` — that case is represented by +/// [`ResolvedCommand::RunLastDetails`] instead. +#[derive(Debug)] +pub struct ResolvedRunCommand { + /// `packageName#taskName` or `taskName`. If omitted, lists all available tasks. + pub task_specifier: Option, + + pub flags: RunFlags, + + /// Additional arguments to pass to the tasks. + pub additional_args: Vec, +} + +impl RunCommand { + /// Convert to the resolved run command, stripping the `last_details` flag. + #[must_use] + pub(crate) fn into_resolved(self) -> ResolvedRunCommand { + ResolvedRunCommand { + task_specifier: self.task_specifier, + flags: self.flags, + additional_args: self.additional_args, + } + } +} + #[derive(thiserror::Error, Debug)] pub enum CLITaskQueryError { #[error("no task specifier provided")] @@ -69,7 +152,7 @@ pub enum CLITaskQueryError { PackageNameSpecifiedWithRecursive { package_name: Str, task_name: Str }, } -impl RunCommand { +impl ResolvedRunCommand { /// Convert to `QueryPlanRequest`, or return an error if invalid. /// /// # Errors @@ -82,7 +165,7 @@ impl RunCommand { ) -> Result { let Self { task_specifier, - flags: RunFlags { recursive, transitive, ignore_depends_on }, + flags: RunFlags { recursive, transitive, ignore_depends_on, .. }, additional_args, } = self; diff --git a/crates/vite_task/src/session/cache/display.rs b/crates/vite_task/src/session/cache/display.rs index 0db234db..7bf46c96 100644 --- a/crates/vite_task/src/session/cache/display.rs +++ b/crates/vite_task/src/session/cache/display.rs @@ -4,14 +4,18 @@ //! Coloring is handled by the reporter to respect `NO_COLOR` environment variable. use rustc_hash::FxHashSet; +use serde::{Deserialize, Serialize}; use vite_str::Str; use vite_task_plan::cache_metadata::SpawnFingerprint; use super::{CacheMiss, FingerprintMismatch}; -use crate::session::event::{CacheDisabledReason, CacheStatus}; +use crate::session::event::CacheStatus; -/// Describes a single atomic change between two spawn fingerprints -enum SpawnFingerprintChange { +/// Describes a single atomic change between two spawn fingerprints. +/// +/// Used both for live cache status display and for persisted summary data. +#[derive(Serialize, Deserialize)] +pub enum SpawnFingerprintChange { // Environment variable changes /// Environment variable added EnvAdded { key: Str, value: Str }, @@ -43,8 +47,40 @@ enum SpawnFingerprintChange { FingerprintIgnoreRemoved { pattern: Str }, } -/// Compare two spawn fingerprints and return all changes -fn detect_spawn_fingerprint_changes( +/// Format a single spawn fingerprint change as human-readable text. +/// +/// Used by both the live cache status display and the persisted summary rendering. +pub fn format_spawn_change(change: &SpawnFingerprintChange) -> Str { + match change { + SpawnFingerprintChange::EnvAdded { key, value } => { + vite_str::format!("env {key}={value} added") + } + SpawnFingerprintChange::EnvRemoved { key, value } => { + vite_str::format!("env {key}={value} removed") + } + SpawnFingerprintChange::EnvValueChanged { key, old_value, new_value } => { + vite_str::format!("env {key} value changed from '{old_value}' to '{new_value}'") + } + SpawnFingerprintChange::PassThroughEnvAdded { name } => { + vite_str::format!("pass-through env '{name}' added") + } + SpawnFingerprintChange::PassThroughEnvRemoved { name } => { + vite_str::format!("pass-through env '{name}' removed") + } + SpawnFingerprintChange::ProgramChanged => Str::from("program changed"), + SpawnFingerprintChange::ArgsChanged => Str::from("args changed"), + SpawnFingerprintChange::CwdChanged => Str::from("working directory changed"), + SpawnFingerprintChange::FingerprintIgnoreAdded { pattern } => { + vite_str::format!("fingerprint ignore '{pattern}' added") + } + SpawnFingerprintChange::FingerprintIgnoreRemoved { pattern } => { + vite_str::format!("fingerprint ignore '{pattern}' removed") + } + } +} + +/// Compare two spawn fingerprints and return all changes. +pub fn detect_spawn_fingerprint_changes( old: &SpawnFingerprint, new: &SpawnFingerprint, ) -> Vec { @@ -180,105 +216,6 @@ pub fn format_cache_status_inline(cache_status: &CacheStatus) -> Option { }; Some(vite_str::format!("✗ cache miss: {reason}, executing")) } - CacheStatus::Disabled(reason) => { - // Show inline message for disabled cache - let message = match reason { - CacheDisabledReason::InProcessExecution => "cache disabled: built-in command", - CacheDisabledReason::NoCacheMetadata => "cache disabled: no cache config", - }; - Some(vite_str::format!("⊘ {message}")) - } - } -} - -/// Format cache status for summary display (post-execution). -/// -/// Returns a formatted string showing detailed cache information. -/// - Cache Hit: Shows saved time -/// - Cache Miss (NotFound): Indicates first-time execution -/// - Cache Miss (with mismatch): Shows specific reason with details -/// - Cache Disabled: Shows user-friendly reason message -/// -/// Note: Returns plain text without styling. The reporter applies colors. -pub fn format_cache_status_summary(cache_status: &CacheStatus) -> Str { - match cache_status { - CacheStatus::Hit { replayed_duration } => { - // Show saved time for cache hits - vite_str::format!("→ Cache hit - output replayed - {replayed_duration:.2?} saved") - } - CacheStatus::Miss(CacheMiss::NotFound) => { - // First time running this task - no previous cache entry - Str::from("→ Cache miss: no previous cache entry found") - } - CacheStatus::Miss(CacheMiss::FingerprintMismatch(mismatch)) => { - // Show specific reason why cache was invalidated - match mismatch { - FingerprintMismatch::SpawnFingerprintMismatch { old, new } => { - let changes = detect_spawn_fingerprint_changes(old, new); - let formatted: Vec = changes - .iter() - .map(|c| match c { - SpawnFingerprintChange::EnvAdded { key, value } => { - vite_str::format!("env {key}={value} added") - } - SpawnFingerprintChange::EnvRemoved { key, value } => { - vite_str::format!("env {key}={value} removed") - } - SpawnFingerprintChange::EnvValueChanged { - key, - old_value, - new_value, - } => { - vite_str::format!( - "env {key} value changed from '{old_value}' to '{new_value}'" - ) - } - SpawnFingerprintChange::PassThroughEnvAdded { name } => { - vite_str::format!("pass-through env '{name}' added") - } - SpawnFingerprintChange::PassThroughEnvRemoved { name } => { - vite_str::format!("pass-through env '{name}' removed") - } - SpawnFingerprintChange::ProgramChanged => Str::from("program changed"), - SpawnFingerprintChange::ArgsChanged => Str::from("args changed"), - SpawnFingerprintChange::CwdChanged => { - Str::from("working directory changed") - } - SpawnFingerprintChange::FingerprintIgnoreAdded { pattern } => { - vite_str::format!("fingerprint ignore '{pattern}' added") - } - SpawnFingerprintChange::FingerprintIgnoreRemoved { pattern } => { - vite_str::format!("fingerprint ignore '{pattern}' removed") - } - }) - .collect(); - - if formatted.is_empty() { - Str::from("→ Cache miss: configuration changed") - } else { - let joined = - formatted.iter().map(Str::as_str).collect::>().join("; "); - vite_str::format!("→ Cache miss: {joined}") - } - } - FingerprintMismatch::PostRunFingerprintMismatch(diff) => { - // Post-run mismatch has specific path information - use crate::session::execute::fingerprint::PostRunFingerprintMismatch; - match diff { - PostRunFingerprintMismatch::InputContentChanged { path } => { - vite_str::format!("→ Cache miss: content of input '{path}' changed") - } - } - } - } - } - CacheStatus::Disabled(reason) => { - // Display user-friendly message for each disabled reason - let message = match reason { - CacheDisabledReason::InProcessExecution => "Cache disabled for built-in command", - CacheDisabledReason::NoCacheMetadata => "Cache disabled in task configuration", - }; - vite_str::format!("→ {message}") - } + CacheStatus::Disabled(_) => Some(Str::from("⊘ cache disabled")), } } diff --git a/crates/vite_task/src/session/cache/mod.rs b/crates/vite_task/src/session/cache/mod.rs index c9bf5381..e9ff6093 100644 --- a/crates/vite_task/src/session/cache/mod.rs +++ b/crates/vite_task/src/session/cache/mod.rs @@ -6,7 +6,8 @@ use std::{fmt::Display, fs::File, io::Write, sync::Arc, time::Duration}; use bincode::{Decode, Encode, decode_from_slice, encode_to_vec}; // Re-export display functions for convenience -pub use display::{format_cache_status_inline, format_cache_status_summary}; +pub use display::format_cache_status_inline; +pub use display::{SpawnFingerprintChange, detect_spawn_fingerprint_changes, format_spawn_change}; use rusqlite::{Connection, OptionalExtension as _, config::DbConfig}; use serde::{Deserialize, Serialize}; use tokio::sync::Mutex; diff --git a/crates/vite_task/src/session/mod.rs b/crates/vite_task/src/session/mod.rs index 17c5d7e3..eb0c2b52 100644 --- a/crates/vite_task/src/session/mod.rs +++ b/crates/vite_task/src/session/mod.rs @@ -10,7 +10,10 @@ use cache::ExecutionCache; pub use cache::{CacheMiss, FingerprintMismatch}; use once_cell::sync::OnceCell; pub use reporter::ExitStatus; -use reporter::LabeledReporterBuilder; +use reporter::{ + LabeledReporterBuilder, + summary::{LastRunSummary, ReadSummaryError, format_full_summary}, +}; use rustc_hash::FxHashMap; use vite_path::{AbsolutePath, AbsolutePathBuf}; use vite_select::SelectItem; @@ -26,7 +29,7 @@ use vite_task_plan::{ }; use vite_workspace::{WorkspaceRoot, find_workspace_root}; -use crate::cli::{CacheSubcommand, Command, RunCommand, RunFlags}; +use crate::cli::{CacheSubcommand, Command, ResolvedCommand, RunCommand, RunFlags}; #[derive(Debug)] enum LazyTaskGraph<'a> { @@ -97,11 +100,13 @@ impl vite_task_plan::PlanRequestParser for PlanRequestParser<'_> { ) -> anyhow::Result> { match self.command_handler.handle_command(command).await? { HandledCommand::Synthesized(synthetic) => Ok(Some(PlanRequest::Synthetic(synthetic))), - HandledCommand::ViteTaskCommand(cli_command) => match cli_command { - Command::Cache { .. } => Ok(Some(PlanRequest::Synthetic( - command.to_synthetic_plan_request(UserCacheConfig::disabled()), - ))), - Command::Run(run_command) => { + HandledCommand::ViteTaskCommand(cli_command) => match cli_command.into_resolved() { + ResolvedCommand::Cache { .. } | ResolvedCommand::RunLastDetails => { + Ok(Some(PlanRequest::Synthetic( + command.to_synthetic_plan_request(UserCacheConfig::disabled()), + ))) + } + ResolvedCommand::Run(run_command) => { match run_command.into_query_plan_request(&command.cwd) { Ok(query_plan_request) => Ok(Some(PlanRequest::Query(query_plan_request))), Err(crate::cli::CLITaskQueryError::MissingTaskSpecifier) => { @@ -222,19 +227,21 @@ impl<'a> Session<'a> { reason = "session is single-threaded, futures do not need to be Send" )] pub async fn main(mut self, command: Command) -> anyhow::Result { - match command { - Command::Cache { ref subcmd } => self.handle_cache_command(subcmd), - Command::Run(run_command) => { + match command.into_resolved() { + ResolvedCommand::Cache { ref subcmd } => self.handle_cache_command(subcmd), + ResolvedCommand::RunLastDetails => self.show_last_run_details(), + ResolvedCommand::Run(run_command) => { let cwd = Arc::clone(&self.cwd); let is_interactive = std::io::stdin().is_terminal() && std::io::stdout().is_terminal(); // Save task name and flags before consuming run_command let task_name = run_command.task_specifier.as_ref().map(|s| s.task_name.clone()); + let show_details = run_command.flags.verbose; let flags = run_command.flags; let additional_args = run_command.additional_args.clone(); - match self.plan_from_cli_run(cwd, run_command).await { + match self.plan_from_cli_run_resolved(cwd, run_command).await { Ok(ref graph) if graph.node_count() == 0 => { // No tasks matched the query — show task selector / "did you mean" self.handle_no_task( @@ -249,6 +256,8 @@ impl<'a> Session<'a> { let builder = LabeledReporterBuilder::new( self.workspace_path(), Box::new(tokio::io::stdout()), + show_details, + Some(self.make_summary_writer()), ); Ok(self .execute_graph(graph, Box::new(builder)) @@ -389,13 +398,22 @@ impl<'a> Session<'a> { // Interactive: run the selected task let selected_label = &select_items[selected_index].label; let task_specifier = TaskSpecifier::parse_raw(selected_label); - let run_command = - RunCommand { task_specifier: Some(task_specifier), flags, additional_args }; + let show_details = flags.verbose; + let run_command = RunCommand { + task_specifier: Some(task_specifier), + flags, + additional_args, + last_details: false, + }; let cwd = Arc::clone(&self.cwd); let graph = self.plan_from_cli_run(cwd, run_command).await?; - let builder = - LabeledReporterBuilder::new(self.workspace_path(), Box::new(tokio::io::stdout())); + let builder = LabeledReporterBuilder::new( + self.workspace_path(), + Box::new(tokio::io::stdout()), + show_details, + Some(self.make_summary_writer()), + ); Ok(self.execute_graph(graph, Box::new(builder)).await.err().unwrap_or(ExitStatus::SUCCESS)) } @@ -414,6 +432,57 @@ impl<'a> Session<'a> { Arc::clone(&self.workspace_path) } + /// Path to the `last-summary.json` file inside the cache directory. + fn summary_file_path(&self) -> AbsolutePathBuf { + self.cache_path.join("last-summary.json") + } + + /// Create a callback that persists the summary to `last-summary.json`. + /// + /// The returned closure captures the file path and handles errors internally + /// (logging failures without propagating). + fn make_summary_writer(&self) -> Box { + let path = self.summary_file_path(); + Box::new(move |summary: &LastRunSummary| { + if let Err(err) = summary.write_atomic(&path) { + tracing::warn!("Failed to write summary to {path:?}: {err}"); + } + }) + } + + /// Display the saved summary from the last run (`--last-details`). + #[expect( + clippy::print_stderr, + reason = "--last-details error messages are user-facing diagnostics, not debug output" + )] + fn show_last_run_details(&self) -> anyhow::Result { + let path = self.summary_file_path(); + match LastRunSummary::read_from_path(&path) { + Ok(Some(summary)) => { + let buf = format_full_summary(&summary); + { + use std::io::Write; + let mut stdout = std::io::stdout().lock(); + stdout.write_all(&buf)?; + stdout.flush()?; + } + Ok(ExitStatus(summary.exit_code)) + } + Ok(None) => { + eprintln!("No previous run summary found. Run a task first to generate a summary."); + Ok(ExitStatus::FAILURE) + } + Err(ReadSummaryError::IncompatibleVersion) => { + eprintln!( + "Summary data was saved by a different version of vite-task and cannot be read. \ + Run a task to generate a new summary." + ); + Ok(ExitStatus::FAILURE) + } + Err(ReadSummaryError::Io(err)) => Err(err.into()), + } + } + pub const fn task_graph(&self) -> Option<&TaskGraph> { match &self.lazy_task_graph { LazyTaskGraph::Initialized(graph) => Some(graph.task_graph()), @@ -514,6 +583,19 @@ impl<'a> Session<'a> { &mut self, cwd: Arc, command: RunCommand, + ) -> Result { + self.plan_from_cli_run_resolved(cwd, command.into_resolved()).await + } + + /// Internal: plans execution from a resolved run command. + #[expect( + clippy::future_not_send, + reason = "session is single-threaded, futures do not need to be Send" + )] + async fn plan_from_cli_run_resolved( + &mut self, + cwd: Arc, + command: crate::cli::ResolvedRunCommand, ) -> Result { let query_plan_request = match command.into_query_plan_request(&cwd) { Ok(query_plan_request) => query_plan_request, diff --git a/crates/vite_task/src/session/reporter/labeled.rs b/crates/vite_task/src/session/reporter/labeled.rs index 9101a40d..e901764a 100644 --- a/crates/vite_task/src/session/reporter/labeled.rs +++ b/crates/vite_task/src/session/reporter/labeled.rs @@ -6,44 +6,27 @@ //! Tracks statistics across multiple leaf executions, prints command lines with cache //! status indicators, and renders a summary with per-task details at the end. -use std::{cell::RefCell, process::ExitStatus as StdExitStatus, rc::Rc, sync::Arc, time::Duration}; +use std::{cell::RefCell, process::ExitStatus as StdExitStatus, rc::Rc, sync::Arc}; -use owo_colors::Style; use tokio::io::{AsyncWrite, AsyncWriteExt as _}; use vite_path::AbsolutePath; use vite_str::Str; use vite_task_plan::{ExecutionItemDisplay, LeafExecutionKind}; use super::{ - CACHE_MISS_STYLE, COMMAND_STYLE, ColorizeExt, ExitStatus, GraphExecutionReporter, - GraphExecutionReporterBuilder, LeafExecutionReporter, StdioConfig, StdioSuggestion, - format_command_display, format_command_with_cache_status, format_error_message, + ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, LeafExecutionReporter, + StdioConfig, StdioSuggestion, format_command_with_cache_status, format_error_message, }; use crate::session::{ - cache::format_cache_status_summary, - event::{CacheStatus, CacheUpdateStatus, ExecutionError, exit_status_to_code}, + event::{CacheStatus, CacheUpdateStatus, ExecutionError}, + reporter::summary::{ + LastRunSummary, SavedExecutionError, SpawnOutcome, TaskResult, TaskSummary, + format_compact_summary, format_full_summary, + }, }; -/// Information tracked for each leaf execution, used in the final summary. -#[derive(Debug)] -struct ExecutionInfo { - display: ExecutionItemDisplay, - /// Cache status, determined at `start()`. - cache_status: CacheStatus, - /// Exit status from the process. `None` means no process was spawned (cache hit or in-process). - exit_status: Option, - /// Error message, set on error. - error_message: Option, -} - -/// Running statistics updated as leaf executions complete. -#[derive(Default)] -struct ExecutionStats { - cache_hits: usize, - cache_misses: usize, - cache_disabled: usize, - failed: usize, -} +/// Callback type for persisting the summary (e.g., writing `last-summary.json`). +type WriteSummaryFn = Box; /// Mutable state shared between [`LabeledGraphReporter`] and its [`LabeledLeafReporter`] instances /// via `Rc>`. @@ -51,8 +34,7 @@ struct ExecutionStats { /// This is safe because execution is single-threaded and sequential — only one leaf /// reporter is active at a time. struct SharedReporterState { - executions: Vec, - stats: ExecutionStats, + tasks: Vec, } /// Builder for the labeled graph reporter. @@ -62,18 +44,21 @@ struct SharedReporterState { /// /// # Output Modes /// -/// ## Normal Mode (default) -/// - Prints command lines with cache status indicators during execution -/// - Shows full summary with Statistics and Task Details at the end +/// ## Compact Summary (default) +/// - Single task + not cache hit → no summary at all +/// - Single task + cache hit → thin line + "[vp run] cache hit, {duration} saved." +/// - Multi-task → thin line + one-liner with stats /// -/// ## Simplified Summary for Single Tasks -/// - When a single task with display info is executed: -/// - Skips full summary (no Statistics/Task Details sections) -/// - Shows only cache status inline -/// - Results in clean output showing just the command's stdout/stderr +/// ## Full Summary (`--verbose`) +/// - Shows full Statistics, Performance, and Task Details sections pub struct LabeledReporterBuilder { workspace_path: Arc, writer: Box, + /// Whether to render the full detailed summary (`--verbose` flag). + show_details: bool, + /// Callback to persist the summary (e.g., write `last-summary.json`). + /// `None` when persistence is not needed (e.g., nested script execution, tests). + write_summary: Option, } impl LabeledReporterBuilder { @@ -81,8 +66,15 @@ impl LabeledReporterBuilder { /// /// - `workspace_path`: The workspace root, used to compute relative cwds in display. /// - `writer`: Async writer for reporter display output. - pub fn new(workspace_path: Arc, writer: Box) -> Self { - Self { workspace_path, writer } + /// - `show_details`: Whether to render the full detailed summary. + /// - `write_summary`: Callback to persist the summary, or `None` to skip. + pub fn new( + workspace_path: Arc, + writer: Box, + show_details: bool, + write_summary: Option, + ) -> Self { + Self { workspace_path, writer, show_details, write_summary } } } @@ -90,12 +82,11 @@ impl GraphExecutionReporterBuilder for LabeledReporterBuilder { fn build(self: Box) -> Box { let writer = Rc::new(RefCell::new(self.writer)); Box::new(LabeledGraphReporter { - shared: Rc::new(RefCell::new(SharedReporterState { - executions: Vec::new(), - stats: ExecutionStats::default(), - })), + shared: Rc::new(RefCell::new(SharedReporterState { tasks: Vec::new() })), writer, workspace_path: self.workspace_path, + show_details: self.show_details, + write_summary: self.write_summary, }) } } @@ -108,6 +99,8 @@ pub struct LabeledGraphReporter { shared: Rc>, writer: Rc>>, workspace_path: Arc, + show_details: bool, + write_summary: Option, } #[async_trait::async_trait(?Send)] @@ -135,60 +128,72 @@ impl GraphExecutionReporter for LabeledGraphReporter { display, workspace_path: Arc::clone(&self.workspace_path), stdio_suggestion, - started: false, + cache_status: None, }) } async fn finish(self: Box) -> Result<(), ExitStatus> { - // Borrow shared state synchronously to build the summary buffer and compute - // the exit result. The borrow is dropped before any async writes. - let (summary_buf, result) = { - let shared = self.shared.borrow(); - - let summary_buf = - format_summary(&shared.executions, &shared.stats, &self.workspace_path); - - // Determine exit code based on failed tasks and infrastructure errors: - // - Infrastructure errors (cache lookup, spawn failure) have error_message set - // but no meaningful exit_status. - // - Process failures have a non-zero exit_status. - // - // Rules: - // 1. No failures at all → Ok(()) - // 2. Exactly one process failure, no infra errors → use that task's exit code - // 3. Any infra errors, or multiple failures → Err(1) - let has_infra_errors = - shared.executions.iter().any(|exec| exec.error_message.is_some()); - - let failed_exit_codes: Vec = shared - .executions - .iter() - .filter_map(|exec| exec.exit_status.as_ref()) - .filter(|status| !status.success()) - .map(|status| exit_status_to_code(*status)) - .collect(); - - let result = match (has_infra_errors, failed_exit_codes.as_slice()) { - (false, []) => Ok(()), - (false, [code]) => { - // Return the single failed task's exit code (clamped to u8 range) - #[expect( - clippy::cast_sign_loss, - reason = "value is clamped to 1..=255, always positive" - )] - Err(ExitStatus((*code).clamp(1, 255) as u8)) + // Take tasks from shared state — all leaf reporters have been dropped by now. + let tasks = { + let mut shared = self.shared.borrow_mut(); + std::mem::take(&mut shared.tasks) + }; + + // Compute exit status from the collected task results. + let has_infra_errors = tasks.iter().any(|t| t.result.error().is_some()); + + let failed_exit_codes: Vec = tasks + .iter() + .filter_map(|t| match &t.result { + TaskResult::Spawned { outcome: SpawnOutcome::Failed { exit_code }, .. } => { + Some(exit_code.get()) } - _ => Err(ExitStatus::FAILURE), - }; + _ => None, + }) + .collect(); - (summary_buf, result) + let result = match (has_infra_errors, failed_exit_codes.as_slice()) { + (false, []) => Ok(()), + (false, [code]) => + { + #[expect( + clippy::cast_sign_loss, + reason = "value is clamped to 1..=255, always positive" + )] + Err(ExitStatus((*code).clamp(1, 255) as u8)) + } + _ => Err(ExitStatus::FAILURE), + }; + + let exit_code = match &result { + Ok(()) => 0u8, + Err(status) => status.0, }; - // shared borrow dropped here - // Write the summary buffer asynchronously + // Build summary from collected tasks. + let summary = LastRunSummary { tasks, exit_code }; + + // Render summary based on mode. + let summary_buf = if self.show_details { + format_full_summary(&summary) + } else { + format_compact_summary(&summary) + }; + + // Persist summary via callback (best-effort, callback handles errors). + if let Some(write_summary) = self.write_summary { + write_summary(&summary); + } + + // Write the summary buffer asynchronously. + // Always flush the writer — even when the summary is empty, a preceding + // spawned process may have written to the same fd via Stdio::inherit() + // and the data must be flushed before the caller reads the output. { let mut writer = self.writer.borrow_mut(); - let _ = writer.write_all(&summary_buf).await; + if !summary_buf.is_empty() { + let _ = writer.write_all(&summary_buf).await; + } let _ = writer.flush().await; } @@ -198,8 +203,8 @@ impl GraphExecutionReporter for LabeledGraphReporter { /// Leaf-level reporter created by [`LabeledGraphReporter::new_leaf_execution`]. /// -/// Writes display output in real-time to the shared async writer and updates shared -/// stats/errors via `Rc>`. +/// Writes display output in real-time to the shared async writer and builds +/// [`TaskSummary`] entries that are pushed to [`SharedReporterState`] on completion. struct LabeledLeafReporter { shared: Rc>, writer: Rc>>, @@ -208,9 +213,9 @@ struct LabeledLeafReporter { workspace_path: Arc, /// Stdio suggestion precomputed from this leaf's graph path. stdio_suggestion: StdioSuggestion, - /// Whether `start()` has been called. Used to determine if stats should be updated - /// in `finish()` and whether to push an `ExecutionInfo` entry. - started: bool, + /// Cache status, set at `start()` time. `None` means `start()` was never called + /// (e.g., cache lookup failure). Consumed in `finish()` to build [`TaskSummary`]. + cache_status: Option, } #[async_trait::async_trait(?Send)] @@ -221,36 +226,12 @@ struct LabeledLeafReporter { )] impl LeafExecutionReporter for LabeledLeafReporter { async fn start(&mut self, cache_status: CacheStatus) -> StdioConfig { - self.started = true; + // Format command line with cache status before storing it. + let line = + format_command_with_cache_status(&self.display, &self.workspace_path, &cache_status); - // Update shared state synchronously, then drop the borrow before any async writes. - { - let mut shared = self.shared.borrow_mut(); - - // Update statistics based on cache status - match &cache_status { - CacheStatus::Hit { .. } => shared.stats.cache_hits += 1, - CacheStatus::Miss(_) => shared.stats.cache_misses += 1, - CacheStatus::Disabled(_) => shared.stats.cache_disabled += 1, - } + self.cache_status = Some(cache_status); - // Store execution info for the summary - shared.executions.push(ExecutionInfo { - display: self.display.clone(), - cache_status, - exit_status: None, - error_message: None, - }); - } - // shared borrow dropped here - - // Format command line with cache status (sync), then write asynchronously. - // The shared borrow to read cache_status is brief and dropped before the await. - let line = { - let shared = self.shared.borrow(); - let cache_status = &shared.executions.last().unwrap().cache_status; - format_command_with_cache_status(&self.display, &self.workspace_path, cache_status) - }; let mut writer = self.writer.borrow_mut(); let _ = writer.write_all(line.as_bytes()).await; let _ = writer.flush().await; @@ -268,287 +249,56 @@ impl LeafExecutionReporter for LabeledLeafReporter { _cache_update_status: CacheUpdateStatus, error: Option, ) { - // Format error message up front (before borrowing shared state) - let error_message: Option = + // Convert error before consuming it (need the original for display formatting). + let saved_error = error.as_ref().map(SavedExecutionError::from_execution_error); + let error_display: Option = error.map(|e| vite_str::format!("{:#}", anyhow::Error::from(e))); - let has_error = error_message.is_some(); - // Update shared state synchronously, then drop the borrow before any async writes. - { - let mut shared = self.shared.borrow_mut(); + // Destructure self to avoid partial-move issues with Box. + let Self { shared, writer, display, workspace_path, cache_status, .. } = *self; + let started = cache_status.is_some(); - // Handle errors — update execution info and stats. - // Error message is formatted using anyhow's `{:#}` formatter - // (joins cause chain with `: ` separators). - if let Some(ref message) = error_message { - // Update the execution info if start() was called (an entry was pushed). - // Without the `self.started` guard, `last_mut()` would return a - // *different* execution's entry, corrupting its error_message. - if self.started - && let Some(exec) = shared.executions.last_mut() - { - exec.error_message = Some(message.clone()); - } - - shared.stats.failed += 1; - } + // Build TaskSummary and push to shared state if start() was called. + if let Some(cache_status) = cache_status { + let cwd_relative = if let Ok(Some(rel)) = display.cwd.strip_prefix(&workspace_path) { + Str::from(rel.as_str()) + } else { + Str::default() + }; - // Update failure statistics for non-zero exit status (not an error, just a failed task) - // None means success (cache hit or in-process), Some checks the actual exit status - if !has_error && status.is_some_and(|s| !s.success()) { - shared.stats.failed += 1; - } + let task_summary = TaskSummary { + package_name: display.task_display.package_name.clone(), + task_name: display.task_display.task_name.clone(), + command: display.command.clone(), + cwd: cwd_relative, + result: TaskResult::from_execution(&cache_status, status, saved_error.as_ref()), + }; - // Update execution info with exit status (if start() was called and an entry exists) - if self.started - && let Some(exec) = shared.executions.last_mut() - { - exec.exit_status = status; - } + shared.borrow_mut().tasks.push(task_summary); } - // shared borrow dropped here - // Build all display output into a buffer (sync), then write once asynchronously. + // Build all display output into a buffer, then write once asynchronously. let mut buf = Vec::new(); - if let Some(ref message) = error_message { + if let Some(ref message) = error_display { buf.extend_from_slice(format_error_message(message).as_bytes()); } // Add a trailing newline after each task's output for readability. // Skip if start() was never called (e.g. cache lookup failure) — there's // no task output to separate. - if self.started { + if started { buf.push(b'\n'); } if !buf.is_empty() { - let mut writer = self.writer.borrow_mut(); + let mut writer = writer.borrow_mut(); let _ = writer.write_all(&buf).await; let _ = writer.flush().await; } } } -// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -// Summary printing -// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -/// Format the full execution summary into a byte buffer. -/// -/// Called by [`LabeledGraphReporter::finish`] after all tasks have executed. -/// The caller writes the returned buffer to the async writer. -/// -/// Building the summary synchronously into a `Vec` buffer avoids holding -/// `RefCell` borrows across async write points, and ensures atomic output. -#[expect( - clippy::too_many_lines, - reason = "summary formatting is inherently verbose with many write calls" -)] -fn format_summary( - executions: &[ExecutionInfo], - stats: &ExecutionStats, - workspace_path: &AbsolutePath, -) -> Vec { - use std::io::Write; - let mut buf = Vec::new(); - - let total = executions.len(); - let cache_hits = stats.cache_hits; - let cache_misses = stats.cache_misses; - let cache_disabled = stats.cache_disabled; - let failed = stats.failed; - - // Print summary header with decorative line - // Note: leaf finish already adds a trailing newline after each task's output - // Add an extra blank line before the summary for visual separation - let _ = writeln!(buf); - let _ = writeln!( - buf, - "{}", - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) - ); - let _ = writeln!( - buf, - "{}", - " Vite+ Task Runner • Execution Summary".style(Style::new().bold().bright_white()) - ); - let _ = writeln!( - buf, - "{}", - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) - ); - let _ = writeln!(buf); - - // Print statistics - let cache_disabled_str = if cache_disabled > 0 { - Str::from( - vite_str::format!("• {cache_disabled} cache disabled") - .style(Style::new().bright_black()) - .to_string(), - ) - } else { - Str::default() - }; - - let failed_str = if failed > 0 { - Str::from(vite_str::format!("• {failed} failed").style(Style::new().red()).to_string()) - } else { - Str::default() - }; - - // Build statistics line, only including non-empty parts - let _ = write!( - buf, - "{} {} {} {}", - "Statistics:".style(Style::new().bold()), - vite_str::format!(" {total} tasks").style(Style::new().bright_white()), - vite_str::format!("• {cache_hits} cache hits").style(Style::new().green()), - vite_str::format!("• {cache_misses} cache misses").style(CACHE_MISS_STYLE), - ); - if !cache_disabled_str.is_empty() { - let _ = write!(buf, " {cache_disabled_str}"); - } - if !failed_str.is_empty() { - let _ = write!(buf, " {failed_str}"); - } - let _ = writeln!(buf); - - // Calculate cache hit rate - let cache_rate = if total > 0 { - #[expect( - clippy::cast_possible_truncation, - reason = "percentage is always 0..=100, fits in u32" - )] - #[expect(clippy::cast_sign_loss, reason = "percentage is always non-negative")] - #[expect( - clippy::cast_precision_loss, - reason = "acceptable precision loss for display percentage" - )] - { - (f64::from(cache_hits as u32) / total as f64 * 100.0) as u32 - } - } else { - 0 - }; - - // Calculate total time saved from cache hits - let total_saved: Duration = executions - .iter() - .filter_map(|exec| { - if let CacheStatus::Hit { replayed_duration } = &exec.cache_status { - Some(*replayed_duration) - } else { - None - } - }) - .sum(); - - let _ = write!( - buf, - "{} {} cache hit rate", - "Performance:".style(Style::new().bold()), - format_args!("{cache_rate}%").style(if cache_rate >= 75 { - Style::new().green().bold() - } else if cache_rate >= 50 { - CACHE_MISS_STYLE - } else { - Style::new().red() - }) - ); - - if total_saved > Duration::ZERO { - let _ = - write!(buf, ", {:.2?} saved in total", total_saved.style(Style::new().green().bold())); - } - let _ = writeln!(buf); - let _ = writeln!(buf); - - // Detailed task results - let _ = writeln!(buf, "{}", "Task Details:".style(Style::new().bold())); - let _ = writeln!( - buf, - "{}", - "────────────────────────────────────────────────".style(Style::new().bright_black()) - ); - - for (idx, exec) in executions.iter().enumerate() { - let display = &exec.display; - - let task_display = &display.task_display; - - // Task name and index - let _ = write!( - buf, - " {} {}", - vite_str::format!("[{}]", idx + 1).style(Style::new().bright_black()), - task_display.to_string().style(Style::new().bright_white().bold()) - ); - - // Command with cwd prefix - let command_display = format_command_display(display, workspace_path); - let _ = write!(buf, ": {}", command_display.style(COMMAND_STYLE)); - - // Execution result icon - // None means success (cache hit or in-process), Some checks actual status - match &exec.exit_status { - None => { - let _ = write!(buf, " {}", "✓".style(Style::new().green().bold())); - } - Some(exit_status) if exit_status.success() => { - let _ = write!(buf, " {}", "✓".style(Style::new().green().bold())); - } - Some(exit_status) => { - let code = exit_status_to_code(*exit_status); - let _ = write!( - buf, - " {} {}", - "✗".style(Style::new().red().bold()), - vite_str::format!("(exit code: {code})").style(Style::new().red()) - ); - } - } - let _ = writeln!(buf); - - // Cache status details — use display module for plain text, apply styling here - let cache_summary = format_cache_status_summary(&exec.cache_status); - let styled_summary = match &exec.cache_status { - CacheStatus::Hit { .. } => cache_summary.style(Style::new().green()), - CacheStatus::Miss(_) => cache_summary.style(CACHE_MISS_STYLE), - CacheStatus::Disabled(_) => cache_summary.style(Style::new().bright_black()), - }; - let _ = writeln!(buf, " {styled_summary}"); - - // Error message if present - if let Some(ref error_msg) = exec.error_message { - let _ = writeln!( - buf, - " {} {}", - "✗ Error:".style(Style::new().red().bold()), - error_msg.style(Style::new().red()) - ); - } - - // Add spacing between tasks except for the last one - if idx < executions.len() - 1 { - let _ = writeln!( - buf, - " {}", - "·······················································" - .style(Style::new().bright_black()) - ); - } - } - - let _ = writeln!( - buf, - "{}", - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) - ); - - buf -} - #[cfg(test)] mod tests { use vite_task_plan::ExecutionItemKind; @@ -576,8 +326,12 @@ mod tests { leaf_kind: &LeafExecutionKind, all_ancestors_single_node: bool, ) -> Box { - let builder = - Box::new(LabeledReporterBuilder::new(test_path(), Box::new(tokio::io::sink()))); + let builder = Box::new(LabeledReporterBuilder::new( + test_path(), + Box::new(tokio::io::sink()), + false, + None, + )); let mut reporter = builder.build(); reporter.new_leaf_execution(display, leaf_kind, all_ancestors_single_node) } diff --git a/crates/vite_task/src/session/reporter/mod.rs b/crates/vite_task/src/session/reporter/mod.rs index 7c8d2974..58c4ed63 100644 --- a/crates/vite_task/src/session/reporter/mod.rs +++ b/crates/vite_task/src/session/reporter/mod.rs @@ -22,6 +22,7 @@ mod labeled; mod plain; +pub mod summary; // Re-export the concrete implementations so callers can use `reporter::PlainReporter` // and `reporter::LabeledReporterBuilder` without navigating into child modules. diff --git a/crates/vite_task/src/session/reporter/summary.rs b/crates/vite_task/src/session/reporter/summary.rs new file mode 100644 index 00000000..8178bd2b --- /dev/null +++ b/crates/vite_task/src/session/reporter/summary.rs @@ -0,0 +1,718 @@ +//! Structured summary types for persisting and rendering execution results. +//! +//! The [`LastRunSummary`] is built after every graph execution and: +//! 1. Saved atomically to `cache_path/last-summary.json` for `vp run --last-details`. +//! 2. Rendered immediately — either as a compact one-liner or a full detailed summary. +//! +//! Both the live reporter and the `--last-details` display use the same rendering +//! functions, ensuring consistent output. + +use std::{io::Write, num::NonZeroI32, time::Duration}; + +use owo_colors::Style; +use serde::{Deserialize, Serialize}; +use vite_path::AbsolutePath; +use vite_str::Str; + +use super::{CACHE_MISS_STYLE, COMMAND_STYLE, ColorizeExt}; +use crate::session::{ + cache::{ + CacheMiss, FingerprintMismatch, SpawnFingerprintChange, detect_spawn_fingerprint_changes, + format_spawn_change, + }, + event::{CacheDisabledReason, CacheErrorKind, CacheStatus, ExecutionError}, +}; + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Structured types (Serialize + Deserialize for JSON persistence) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/// Saved summary of a task runner execution. +/// +/// Persisted as `last-summary.json` in the cache directory. +#[derive(Serialize, Deserialize)] +pub struct LastRunSummary { + pub tasks: Vec, + pub exit_code: u8, +} + +/// Summary for a single task execution. +/// +/// All fields are structured data — no pre-formatted display strings. +/// Formatting (including color decisions) happens at render time. +#[derive(Serialize, Deserialize)] +pub struct TaskSummary { + pub package_name: Str, + pub task_name: Str, + /// Raw command text (e.g., "vitest run"). + pub command: Str, + /// Working directory relative to workspace root (e.g., "packages/lib"). + /// Empty string when the cwd is the workspace root. + pub cwd: Str, + /// Combined cache status and execution outcome. + pub result: TaskResult, +} + +/// The complete result of a task execution. +/// +/// Encodes both the cache status and execution outcome in a single enum, +/// making invalid combinations unrepresentable. +#[derive(Serialize, Deserialize)] +pub enum TaskResult { + /// Cache hit — output was replayed from cache. Always successful. + CacheHit { saved_duration_ms: u64 }, + + /// In-process execution (built-in command like echo). Always successful. + InProcess, + + /// A process was spawned. + Spawned { + /// Why the process was spawned (cache miss or cache disabled). + cache_status: SpawnedCacheStatus, + outcome: SpawnOutcome, + }, +} + +/// Cache status for tasks that required spawning a process. +/// +/// Only two cache statuses lead to spawning: +/// - `Miss`: cache lookup found no match or a mismatch. +/// - `Disabled`: no cache configuration for this task. +/// +/// `Hit` and `InProcessExecution` are handled by [`TaskResult::CacheHit`] +/// and [`TaskResult::InProcess`] respectively. +#[derive(Serialize, Deserialize)] +pub enum SpawnedCacheStatus { + Miss(SavedCacheMissReason), + /// No cache configuration for this task. + Disabled, +} + +/// Outcome of a spawned process. +#[derive(Serialize, Deserialize)] +pub enum SpawnOutcome { + /// Process exited successfully (exit code 0). + /// May have a post-execution infrastructure error (cache update or fingerprint failed). + /// These only run after exit 0, so this field only exists on the success path. + Success { infra_error: Option }, + + /// Process exited with non-zero status. + /// [`NonZeroI32`] enforces that exit code 0 is unrepresentable here. + /// 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). + SpawnError(SavedExecutionError), +} + +/// Why a cache miss occurred. +#[derive(Serialize, Deserialize)] +pub enum SavedCacheMissReason { + /// No previous cache entry for this task. + NotFound, + /// Spawn fingerprint changed (command, envs, cwd, etc.). + SpawnFingerprintChanged(Vec), + /// Content of an input file changed. + InputContentChanged { path: Str }, +} + +/// An execution error, serializable for persistence. +/// +/// The `message` field contains the raw inner error text (from `anyhow::Error`). +/// The error prefix (e.g., "Cache update failed") is derived from the variant +/// at render time. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SavedExecutionError { + Cache { kind: SavedCacheErrorKind, message: Str }, + Spawn { message: Str }, + PostRunFingerprint { message: Str }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SavedCacheErrorKind { + Lookup, + Update, +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Computed stats (derived from tasks, not persisted) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +struct SummaryStats { + total: usize, + cache_hits: usize, + cache_misses: usize, + cache_disabled: usize, + failed: usize, + total_saved: Duration, +} + +impl SummaryStats { + fn compute(tasks: &[TaskSummary]) -> Self { + let mut stats = Self { + total: tasks.len(), + cache_hits: 0, + cache_misses: 0, + cache_disabled: 0, + failed: 0, + total_saved: Duration::ZERO, + }; + + for task in tasks { + match &task.result { + TaskResult::CacheHit { saved_duration_ms } => { + stats.cache_hits += 1; + stats.total_saved += Duration::from_millis(*saved_duration_ms); + } + TaskResult::InProcess => { + stats.cache_disabled += 1; + } + TaskResult::Spawned { cache_status, outcome } => { + match cache_status { + SpawnedCacheStatus::Miss(_) => stats.cache_misses += 1, + SpawnedCacheStatus::Disabled => stats.cache_disabled += 1, + } + match outcome { + SpawnOutcome::Success { infra_error: Some(_) } + | SpawnOutcome::Failed { .. } + | SpawnOutcome::SpawnError(_) => stats.failed += 1, + SpawnOutcome::Success { infra_error: None } => {} + } + } + } + } + + stats + } +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Conversion from live execution data +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +impl SavedExecutionError { + /// Convert a live [`ExecutionError`] into a serializable error. + pub fn from_execution_error(error: &ExecutionError) -> Self { + match error { + ExecutionError::Cache { kind, source } => Self::Cache { + kind: match kind { + CacheErrorKind::Lookup => SavedCacheErrorKind::Lookup, + CacheErrorKind::Update => SavedCacheErrorKind::Update, + }, + message: vite_str::format!("{source:#}"), + }, + ExecutionError::Spawn(source) => { + Self::Spawn { message: vite_str::format!("{source:#}") } + } + ExecutionError::PostRunFingerprint(source) => { + Self::PostRunFingerprint { message: vite_str::format!("{source:#}") } + } + } + } + + /// Format the full error message for display. + fn display_message(&self) -> Str { + match self { + Self::Cache { kind, message } => { + let kind_str = match kind { + SavedCacheErrorKind::Lookup => "lookup", + SavedCacheErrorKind::Update => "update", + }; + vite_str::format!("Cache {kind_str} failed: {message}") + } + Self::Spawn { message } => { + vite_str::format!("Failed to spawn process: {message}") + } + Self::PostRunFingerprint { message } => { + vite_str::format!("Failed to create post-run fingerprint: {message}") + } + } + } +} + +impl SavedCacheMissReason { + fn from_cache_miss(cache_miss: &CacheMiss) -> Self { + match cache_miss { + CacheMiss::NotFound => Self::NotFound, + CacheMiss::FingerprintMismatch(mismatch) => match mismatch { + FingerprintMismatch::SpawnFingerprintMismatch { old, new } => { + Self::SpawnFingerprintChanged(detect_spawn_fingerprint_changes(old, new)) + } + FingerprintMismatch::PostRunFingerprintMismatch(diff) => { + use crate::session::execute::fingerprint::PostRunFingerprintMismatch; + match diff { + PostRunFingerprintMismatch::InputContentChanged { path } => { + Self::InputContentChanged { path: Str::from(path.as_str()) } + } + } + } + }, + } + } +} + +impl TaskResult { + /// Build a [`TaskResult`] from live execution data. + /// + /// `cache_status`: the cache status determined at `start()` time. + /// `exit_status`: the process exit status, or `None` for cache hit / in-process. + /// `saved_error`: an optional pre-converted execution error. + pub fn from_execution( + cache_status: &CacheStatus, + exit_status: Option, + saved_error: Option<&SavedExecutionError>, + ) -> Self { + match cache_status { + CacheStatus::Hit { replayed_duration } => { + Self::CacheHit { saved_duration_ms: duration_to_ms(*replayed_duration) } + } + CacheStatus::Disabled(CacheDisabledReason::InProcessExecution) => Self::InProcess, + CacheStatus::Disabled(CacheDisabledReason::NoCacheMetadata) => Self::Spawned { + cache_status: SpawnedCacheStatus::Disabled, + outcome: spawn_outcome_from_execution(exit_status, saved_error), + }, + CacheStatus::Miss(cache_miss) => Self::Spawned { + cache_status: SpawnedCacheStatus::Miss(SavedCacheMissReason::from_cache_miss( + cache_miss, + )), + outcome: spawn_outcome_from_execution(exit_status, saved_error), + }, + } + } +} + +/// Build a [`SpawnOutcome`] from process exit status and optional pre-converted error. +fn spawn_outcome_from_execution( + exit_status: Option, + saved_error: Option<&SavedExecutionError>, +) -> SpawnOutcome { + match (exit_status, saved_error) { + // Spawn error — process never ran + (None, Some(err)) => SpawnOutcome::SpawnError(err.clone()), + // Process exited successfully, possible infra error + (Some(status), _) if status.success() => { + SpawnOutcome::Success { infra_error: saved_error.cloned() } + } + // Process exited with non-zero code + (Some(status), _) => { + let code = crate::session::event::exit_status_to_code(status); + SpawnOutcome::Failed { + // exit_status_to_code returns 1..=255 for failed processes (see its + // implementation: always positive, non-zero for non-success status). + // NonZeroI32::new returns None only for 0, which cannot happen here. + exit_code: NonZeroI32::new(code).unwrap_or(NonZeroI32::MIN), + } + } + // No exit status, no error — this is the cache hit / in-process path, + // handled by TaskResult::CacheHit / InProcess before reaching here. + // If we somehow get here, treat as success. + (None, None) => SpawnOutcome::Success { infra_error: None }, + } +} + +#[expect( + clippy::cast_possible_truncation, + reason = "value is clamped to u64::MAX before casting, so no data loss" +)] +fn duration_to_ms(d: Duration) -> u64 { + d.as_millis().min(u128::from(u64::MAX)) as u64 +} + +impl LastRunSummary { + // ── Persistence ────────────────────────────────────────────────────── + + /// Write the summary as JSON atomically (write to `.tmp`, then rename). + /// + /// Errors are returned to the caller (the reporter logs them without propagating). + #[expect( + clippy::disallowed_types, + reason = "PathBuf is needed to construct a temporary path by appending .tmp suffix; \ + AbsolutePathBuf cannot be constructed without validation" + )] + pub fn write_atomic(&self, path: &AbsolutePath) -> std::io::Result<()> { + let json = serde_json::to_vec(self).map_err(std::io::Error::other)?; + + let mut tmp_os = path.as_path().as_os_str().to_owned(); + tmp_os.push(".tmp"); + let tmp_path = std::path::PathBuf::from(tmp_os); + std::fs::write(&tmp_path, &json)?; + std::fs::rename(&tmp_path, path)?; + Ok(()) + } + + /// Read a summary from a JSON file. + /// + /// Returns `Ok(None)` if the file does not exist. + /// Returns `Err` on parse or IO errors (caller provides version mismatch message). + pub fn read_from_path(path: &AbsolutePath) -> Result, ReadSummaryError> { + let bytes = match std::fs::read(path) { + Ok(bytes) => bytes, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(err) => return Err(ReadSummaryError::Io(err)), + }; + let summary = + serde_json::from_slice(&bytes).map_err(|_| ReadSummaryError::IncompatibleVersion)?; + Ok(Some(summary)) + } +} + +/// Error type for [`LastRunSummary::read_from_path`]. +pub enum ReadSummaryError { + Io(std::io::Error), + /// The JSON could not be parsed — likely saved by a different version. + IncompatibleVersion, +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Display helpers for TaskResult +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +impl TaskSummary { + /// Format the task display name (e.g., "package#task" or "task"). + fn format_task_display(&self) -> Str { + if self.package_name.is_empty() { + self.task_name.clone() + } else { + vite_str::format!("{}#{}", self.package_name, self.task_name) + } + } + + /// Format the command with cwd prefix (e.g., "~/packages/lib$ vitest run"). + fn format_command_display(&self) -> Str { + if self.cwd.is_empty() { + vite_str::format!("$ {}", self.command) + } else { + vite_str::format!("~/{cwd}$ {cmd}", cwd = self.cwd, cmd = self.command) + } + } +} + +impl TaskResult { + /// Whether this task succeeded (used for exit icon rendering). + const fn is_success(&self) -> bool { + match self { + Self::CacheHit { .. } | Self::InProcess => true, + Self::Spawned { outcome, .. } => matches!(outcome, SpawnOutcome::Success { .. }), + } + } + + /// Format the cache status detail line for the full summary. + /// + /// Examples: + /// - "→ Cache hit - output replayed - 102.96ms saved" + /// - "→ Cache miss: no previous cache entry found" + /// - "→ Cache disabled in task configuration" + fn format_cache_detail(&self) -> Str { + match self { + Self::CacheHit { saved_duration_ms } => { + let d = Duration::from_millis(*saved_duration_ms); + vite_str::format!("→ Cache hit - output replayed - {d:.2?} saved") + } + Self::InProcess => Str::from("→ Cache disabled for built-in command"), + Self::Spawned { cache_status, .. } => match cache_status { + SpawnedCacheStatus::Disabled => Str::from("→ Cache disabled in task configuration"), + SpawnedCacheStatus::Miss(reason) => match reason { + SavedCacheMissReason::NotFound => { + Str::from("→ Cache miss: no previous cache entry found") + } + SavedCacheMissReason::SpawnFingerprintChanged(changes) => { + let formatted: Vec = changes.iter().map(format_spawn_change).collect(); + if formatted.is_empty() { + Str::from("→ Cache miss: configuration changed") + } else { + let joined = + formatted.iter().map(Str::as_str).collect::>().join("; "); + vite_str::format!("→ Cache miss: {joined}") + } + } + SavedCacheMissReason::InputContentChanged { path } => { + vite_str::format!("→ Cache miss: content of input '{path}' changed") + } + }, + }, + } + } + + /// The [`Style`] for the cache detail line. + const fn cache_detail_style(&self) -> Style { + match self { + Self::CacheHit { .. } => Style::new().green(), + Self::InProcess => Style::new().bright_black(), + Self::Spawned { cache_status: SpawnedCacheStatus::Disabled, .. } => { + Style::new().bright_black() + } + Self::Spawned { cache_status: SpawnedCacheStatus::Miss(_), .. } => CACHE_MISS_STYLE, + } + } + + /// Optional error associated with this result. + pub const fn error(&self) -> Option<&SavedExecutionError> { + match self { + Self::CacheHit { .. } | Self::InProcess => None, + Self::Spawned { outcome, .. } => match outcome { + SpawnOutcome::Success { infra_error } => infra_error.as_ref(), + SpawnOutcome::Failed { .. } => None, + SpawnOutcome::SpawnError(err) => Some(err), + }, + } + } +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Full summary rendering (--verbose and --last-details) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/// Render the full detailed execution summary. +/// +/// Used by both `--verbose` (live) and `--last-details` (from file). +#[expect( + clippy::too_many_lines, + reason = "summary formatting is inherently verbose with many write calls" +)] +pub fn format_full_summary(summary: &LastRunSummary) -> Vec { + let mut buf = Vec::new(); + + let stats = SummaryStats::compute(&summary.tasks); + + // Header + let _ = writeln!(buf); + let _ = writeln!( + buf, + "{}", + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) + ); + let _ = writeln!( + buf, + "{}", + " Vite+ Task Runner • Execution Summary".style(Style::new().bold().bright_white()) + ); + let _ = writeln!( + buf, + "{}", + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) + ); + let _ = writeln!(buf); + + // Statistics line + let cache_disabled_str = if stats.cache_disabled > 0 { + let n = stats.cache_disabled; + Str::from( + vite_str::format!("• {n} cache disabled") + .style(Style::new().bright_black()) + .to_string(), + ) + } else { + Str::default() + }; + + let failed_str = if stats.failed > 0 { + let n = stats.failed; + Str::from(vite_str::format!("• {n} failed").style(Style::new().red()).to_string()) + } else { + Str::default() + }; + + let total = stats.total; + let cache_hits = stats.cache_hits; + let cache_misses = stats.cache_misses; + let _ = write!( + buf, + "{} {} {} {}", + "Statistics:".style(Style::new().bold()), + vite_str::format!(" {total} tasks").style(Style::new().bright_white()), + vite_str::format!("• {cache_hits} cache hits").style(Style::new().green()), + vite_str::format!("• {cache_misses} cache misses").style(CACHE_MISS_STYLE), + ); + if !cache_disabled_str.is_empty() { + let _ = write!(buf, " {cache_disabled_str}"); + } + if !failed_str.is_empty() { + let _ = write!(buf, " {failed_str}"); + } + let _ = writeln!(buf); + + // Performance line + #[expect( + clippy::cast_possible_truncation, + reason = "percentage is always 0..=100, fits in u32" + )] + #[expect(clippy::cast_sign_loss, reason = "percentage is always non-negative")] + #[expect( + clippy::cast_precision_loss, + reason = "acceptable precision loss for display percentage" + )] + let cache_rate = if total > 0 { (cache_hits as f64 / total as f64 * 100.0) as u32 } else { 0 }; + + let _ = write!( + buf, + "{} {} cache hit rate", + "Performance:".style(Style::new().bold()), + format_args!("{cache_rate}%").style(if cache_rate >= 75 { + Style::new().green().bold() + } else if cache_rate >= 50 { + CACHE_MISS_STYLE + } else { + Style::new().red() + }) + ); + + if stats.total_saved > Duration::ZERO { + let _ = write!( + buf, + ", {:.2?} saved in total", + stats.total_saved.style(Style::new().green().bold()) + ); + } + let _ = writeln!(buf); + let _ = writeln!(buf); + + // Task Details + let _ = writeln!(buf, "{}", "Task Details:".style(Style::new().bold())); + let _ = writeln!( + buf, + "{}", + "────────────────────────────────────────────────".style(Style::new().bright_black()) + ); + + for (idx, task) in summary.tasks.iter().enumerate() { + // Task index and name + let _ = write!( + buf, + " {} {}", + vite_str::format!("[{}]", idx + 1).style(Style::new().bright_black()), + task.format_task_display().to_string().style(Style::new().bright_white().bold()) + ); + + // Command with cwd prefix + let _ = write!(buf, ": {}", task.format_command_display().style(COMMAND_STYLE)); + + // Exit icon + if task.result.is_success() { + let _ = write!(buf, " {}", "✓".style(Style::new().green().bold())); + } else if let TaskResult::Spawned { outcome: SpawnOutcome::Failed { exit_code }, .. } = + &task.result + { + let code = exit_code.get(); + let _ = write!( + buf, + " {} {}", + "✗".style(Style::new().red().bold()), + vite_str::format!("(exit code: {code})").style(Style::new().red()) + ); + } + let _ = writeln!(buf); + + // Cache status detail + let cache_detail = task.result.format_cache_detail(); + let _ = writeln!(buf, " {}", cache_detail.style(task.result.cache_detail_style())); + + // Error message if present + if let Some(err) = task.result.error() { + let msg = err.display_message(); + let _ = writeln!( + buf, + " {} {}", + "✗ Error:".style(Style::new().red().bold()), + msg.style(Style::new().red()) + ); + } + + // Separator between tasks (except last) + if idx < summary.tasks.len() - 1 { + let _ = writeln!( + buf, + " {}", + "·······················································" + .style(Style::new().bright_black()) + ); + } + } + + let _ = writeln!( + buf, + "{}", + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".style(Style::new().bright_black()) + ); + + buf +} + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Compact summary rendering (default mode) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/// Render a compact summary (one-liner or empty). +/// +/// Rules: +/// - Single task + not cache hit → empty (no summary at all) +/// - Single task + cache hit → thin line + "[vp run] cache hit, {duration} saved." +/// - Multi-task → thin line + "[vp run] {hits}/{total} cache hit ({rate}%), {duration} saved." +/// with optional failure count and `--verbose` hint. +pub fn format_compact_summary(summary: &LastRunSummary) -> Vec { + let stats = SummaryStats::compute(&summary.tasks); + + let is_single_task = summary.tasks.len() == 1; + + // Single task + not cache hit → no summary + if is_single_task && stats.cache_hits == 0 { + return Vec::new(); + } + + let mut buf = Vec::new(); + + // Thin line separator + let _ = writeln!(buf, "{}", "---".style(Style::new().bright_black())); + + if is_single_task { + // Single task cache hit + let _ = writeln!( + buf, + "{} cache hit, {:.2?} saved.", + "[vp run]".style(Style::new().bright_black()), + stats.total_saved.style(Style::new().green().bold()), + ); + } else { + // Multi-task + let total = stats.total; + let hits = stats.cache_hits; + + #[expect( + clippy::cast_possible_truncation, + reason = "percentage is always 0..=100, fits in u32" + )] + #[expect(clippy::cast_sign_loss, reason = "percentage is always non-negative")] + #[expect( + clippy::cast_precision_loss, + reason = "acceptable precision loss for display percentage" + )] + let rate = if total > 0 { (hits as f64 / total as f64 * 100.0) as u32 } else { 0 }; + + let _ = write!( + buf, + "{} {hits}/{total} cache hit ({rate}%)", + "[vp run]".style(Style::new().bright_black()), + ); + + if stats.total_saved > Duration::ZERO { + let _ = write!( + buf, + ", {:.2?} saved", + stats.total_saved.style(Style::new().green().bold()), + ); + } + + if stats.failed > 0 { + let n = stats.failed; + let _ = write!(buf, ", {} failed", n.style(Style::new().red())); + } + + let _ = write!( + buf, + ". {}", + "(Run `vp run --last-details` for full details)".style(Style::new().bright_black()), + ); + let _ = writeln!(buf); + } + + buf +} diff --git a/crates/vite_task_bin/src/lib.rs b/crates/vite_task_bin/src/lib.rs index 392a6df4..c2560653 100644 --- a/crates/vite_task_bin/src/lib.rs +++ b/crates/vite_task_bin/src/lib.rs @@ -130,7 +130,7 @@ impl vite_task::CommandHandler for CommandHandler { envs: Arc::new(envs), })) } - Args::Task(cli_command) => Ok(HandledCommand::ViteTaskCommand(cli_command)), + Args::Task(parsed) => Ok(HandledCommand::ViteTaskCommand(parsed)), } } } diff --git a/crates/vite_task_bin/src/main.rs b/crates/vite_task_bin/src/main.rs index 6c9d41e0..b4a1320b 100644 --- a/crates/vite_task_bin/src/main.rs +++ b/crates/vite_task_bin/src/main.rs @@ -21,7 +21,7 @@ async fn run() -> anyhow::Result { let mut owned_callbacks = OwnedSessionCallbacks::default(); let session = Session::init(owned_callbacks.as_callbacks())?; match args { - Args::Task(command) => session.main(command).await, + Args::Task(parsed) => session.main(parsed).await, args => { // If env FOO is set, run `print-env FOO` via Session::exec before proceeding. // In vite-plus, Session::exec is used for auto-install. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/associate-existing-cache/snapshots/associate existing cache.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/associate-existing-cache/snapshots/associate existing cache.snap index 5e27e637..96505a45 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/associate-existing-cache/snapshots/associate existing cache.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/associate-existing-cache/snapshots/associate existing cache.snap @@ -5,53 +5,14 @@ expression: e2e_outputs > vp run script1 # cache miss $ print hello hello - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] script1: $ print hello ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run script2 # cache hit, same command as script1 $ print hello ✓ cache hit, replaying hello - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] script2: $ print hello ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > json-edit package.json '_.scripts.script2 = "print world"' # change script2 > vp run script2 # cache miss $ print world ✗ cache miss: args changed, executing world - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] script2: $ print world ✓ - → Cache miss: args changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/.gitignore b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/.gitignore new file mode 100644 index 00000000..231280da --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/.gitignore @@ -0,0 +1,7 @@ +# Prevent oxlint from scanning node_modules. +# Without this, oxlint reads files in node_modules/.vite/task-cache, causing +# fspy to fingerprint the cache directory as an input. The cache directory +# changes between runs (DB writes, last-summary.json), producing flaky +# cache-miss reasons that alternate between '' and +# 'node_modules/.vite/task-cache'. +node_modules diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/snapshots/builtin different cwd.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/snapshots/builtin different cwd.snap index a07da593..85835032 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/snapshots/builtin different cwd.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/snapshots/builtin different cwd.snap @@ -21,20 +21,6 @@ $ vp lint Found 2 warnings and 0 errors. Finished in on 2 files with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > cd folder2 && vp run lint # cache miss in folder2 $ vp lint ✓ cache hit, replaying @@ -55,19 +41,8 @@ $ vp lint ✓ cache hit, replaying Found 2 warnings and 0 errors. Finished in on 2 files with 90 rules using threads. - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > echo 'console.log(1);' > folder2/a.js # modify folder2 > cd folder1 && vp run lint # cache hit @@ -82,20 +57,6 @@ $ vp lint ✗ cache miss: content of input 'folder2/a.js' changed, executing Found 1 warning and 0 errors. Finished in on 2 files with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache miss: content of input 'folder2/a.js' changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > cd folder2 && vp run lint # cache miss $ vp lint ✓ cache hit, replaying @@ -109,16 +70,5 @@ $ vp lint ✓ cache hit, replaying Found 1 warning and 0 errors. Finished in on 2 files with 90 rules using threads. - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/.gitignore b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/.gitignore new file mode 100644 index 00000000..231280da --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/.gitignore @@ -0,0 +1,7 @@ +# Prevent oxlint from scanning node_modules. +# Without this, oxlint reads files in node_modules/.vite/task-cache, causing +# fspy to fingerprint the cache directory as an input. The cache directory +# changes between runs (DB writes, last-summary.json), producing flaky +# cache-miss reasons that alternate between '' and +# 'node_modules/.vite/task-cache'. +node_modules diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/snapshots/builtin command with non-zero exit does not show cache not updated.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/snapshots/builtin command with non-zero exit does not show cache not updated.snap index 90d7981c..b28e1c11 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/snapshots/builtin command with non-zero exit does not show cache not updated.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-non-zero-exit/snapshots/builtin command with non-zero exit does not show cache not updated.snap @@ -14,20 +14,6 @@ $ vp lint -D no-debugger Found 0 warnings and 1 error. Finished in on 1 file with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses • 1 failed -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] builtin-non-zero-exit-test#lint: $ vp lint -D no-debugger ✗ (exit code: 1) - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [1]> vp run lint -- -D no-debugger $ vp lint -D no-debugger @@ -40,17 +26,3 @@ $ vp lint -D no-debugger Found 0 warnings and 1 error. Finished in on 1 file with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses • 1 failed -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] builtin-non-zero-exit-test#lint: $ vp lint -D no-debugger ✗ (exit code: 1) - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache disabled.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache disabled.snap index b3062dc5..0dcf4d0a 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache disabled.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache disabled.snap @@ -3,36 +3,8 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run no-cache-task # cache miss -$ print-file test.txt ⊘ cache disabled: no cache config +$ print-file test.txt ⊘ cache disabled test content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-disabled-test#no-cache-task: $ print-file test.txt ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run no-cache-task # cache disabled, runs again -$ print-file test.txt ⊘ cache disabled: no cache config +$ print-file test.txt ⊘ cache disabled test content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-disabled-test#no-cache-task: $ print-file test.txt ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache enabled.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache enabled.snap index 4bc07bee..3014937b 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache enabled.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots/task with cache enabled.snap @@ -5,34 +5,9 @@ expression: e2e_outputs > vp run cached-task # cache miss $ print-file test.txt test content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-disabled-test#cached-task: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run cached-task # cache hit $ print-file test.txt ✓ cache hit, replaying test content - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] cache-disabled-test#cached-task: $ print-file test.txt ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots/cache miss command change.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots/cache miss command change.snap index 2459b8c0..8d10e3cf 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots/cache miss command change.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots/cache miss command change.snap @@ -9,22 +9,8 @@ foo $ print bar bar - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 2 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] task: $ print foo ✓ - → Cache miss: no previous cache entry found - ······················································· - [2] task: $ print bar ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) > json-edit package.json '_.scripts.task = "print baz && print bar"' # change first subtask > vp run task # first: cache miss, second: cache hit @@ -34,38 +20,13 @@ baz $ print bar ✓ cache hit, replaying bar - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 1 cache hits • 1 cache misses -Performance: 50% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] task: $ print baz ✓ - → Cache miss: args changed - ······················································· - [2] task: $ print bar ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 1/2 cache hit (50%), saved. (Run `vp run --last-details` for full details) > json-edit package.json '_.scripts.task = "print bar"' # remove first subtask > vp run task # cache hit $ print bar ✓ cache hit, replaying bar - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] task: $ print bar ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/cwd changed.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/cwd changed.snap index 448a0b3b..992d75fd 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/cwd changed.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/cwd changed.snap @@ -5,20 +5,6 @@ expression: e2e_outputs > vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > mkdir -p subfolder > cp test.txt subfolder/test.txt @@ -28,17 +14,3 @@ Task Details: > vp run test # cache miss: cwd changed ~/subfolder$ print-file test.txt ✗ cache miss: working directory changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: ~/subfolder$ print-file test.txt ✓ - → Cache miss: working directory changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env added.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env added.snap index 4414d10e..eb641e41 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env added.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env added.snap @@ -5,34 +5,6 @@ expression: e2e_outputs > vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > cross-env MY_ENV=1 vp run test # cache miss: env added $ print-file test.txt ✗ cache miss: envs changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: env MY_ENV=1 added -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env removed.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env removed.snap index 50992adf..661a63c0 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env removed.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env removed.snap @@ -5,34 +5,6 @@ expression: e2e_outputs > cross-env MY_ENV=1 vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run test # cache miss: env removed $ print-file test.txt ✗ cache miss: envs changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: env MY_ENV=1 removed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env value changed.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env value changed.snap index 3197f138..f55ba1f4 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env value changed.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/env value changed.snap @@ -5,34 +5,6 @@ expression: e2e_outputs > cross-env MY_ENV=1 vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > cross-env MY_ENV=2 vp run test # cache miss: env value changed $ print-file test.txt ✗ cache miss: envs changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: env MY_ENV value changed from '1' to '2' -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/input content changed.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/input content changed.snap index b7b5b628..b1fd05df 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/input content changed.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/input content changed.snap @@ -5,36 +5,8 @@ expression: e2e_outputs > vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > replace-file-content test.txt initial modified # modify input > vp run test # cache miss: input changed $ print-file test.txt ✗ cache miss: content of input 'test.txt' changed, executing modified content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: content of input 'test.txt' changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env added.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env added.snap index baeb9a19..c4b6d331 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env added.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env added.snap @@ -5,36 +5,8 @@ expression: e2e_outputs > vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > json-edit vite-task.json "_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']" # add pass-through env > vp run test # cache miss: pass-through env added $ print-file test.txt ✗ cache miss: pass-through env config changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: pass-through env 'MY_PASSTHROUGH' added -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env removed.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env removed.snap index 5e112f0e..72fce09f 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env removed.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons/snapshots/pass-through env removed.snap @@ -7,36 +7,8 @@ expression: e2e_outputs > vp run test # cache miss $ print-file test.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > json-edit vite-task.json "delete _.tasks.test.passThroughEnvs" # remove pass-through env > vp run test # cache miss: pass-through env removed $ print-file test.txt ✗ cache miss: pass-through env config changed, executing initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] cache-miss-reasons#test: $ print-file test.txt ✓ - → Cache miss: pass-through env 'MY_PASSTHROUGH' removed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-subcommand/snapshots/cache clean.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-subcommand/snapshots/cache clean.snap index f6f36f8c..ac04c85c 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-subcommand/snapshots/cache clean.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-subcommand/snapshots/cache clean.snap @@ -5,53 +5,14 @@ expression: e2e_outputs > vp run cached-task # cache miss $ print-file test.txt test content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @test/cache-subcommand#cached-task: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run cached-task # cache hit $ print-file test.txt ✓ cache hit, replaying test content - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] @test/cache-subcommand#cached-task: $ print-file test.txt ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > vp cache clean > vp run cached-task # cache miss after clean $ print-file test.txt test content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @test/cache-subcommand#cached-task: $ print-file test.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/colon-in-name/snapshots/read file with colon in name.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/colon-in-name/snapshots/read file with colon in name.snap index e400fcc0..e8dde109 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/colon-in-name/snapshots/read file with colon in name.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/colon-in-name/snapshots/read file with colon in name.snap @@ -4,33 +4,8 @@ expression: e2e_outputs --- > vp run read_colon_in_name # cache miss $ node read_node_fs.js - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] read_colon_in_name: $ node read_node_fs.js ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run read_colon_in_name # cache hit $ node read_node_fs.js ✓ cache hit, replaying - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] read_colon_in_name: $ node read_node_fs.js ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test prints value from additional_envs.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test prints value from additional_envs.snap index 5b6128bb..7c284657 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test prints value from additional_envs.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test prints value from additional_envs.snap @@ -5,17 +5,3 @@ expression: e2e_outputs > vp run env-test -- SYNTHETIC_ENV_VAR test_value_from_synthesizer # prints env value $ vp env-test SYNTHETIC_ENV_VAR test_value_from_synthesizer test_value_from_synthesizer - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] e2e-env-test#env-test: $ vp env-test SYNTHETIC_ENV_VAR test_value_from_synthesizer ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test with different values.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test with different values.snap index 5203f28f..75140305 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test with different values.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-env-test/snapshots/env-test with different values.snap @@ -5,34 +5,6 @@ expression: e2e_outputs > vp run env-test -- FOO bar # sets FOO=bar $ vp env-test FOO bar bar - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] e2e-env-test#env-test: $ vp env-test FOO bar ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run env-test -- BAZ qux # sets BAZ=qux $ vp env-test BAZ qux qux - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] e2e-env-test#env-test: $ vp env-test BAZ qux ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/.gitignore b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/.gitignore new file mode 100644 index 00000000..231280da --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/.gitignore @@ -0,0 +1,7 @@ +# Prevent oxlint from scanning node_modules. +# Without this, oxlint reads files in node_modules/.vite/task-cache, causing +# fspy to fingerprint the cache directory as an input. The cache directory +# changes between runs (DB writes, last-summary.json), producing flaky +# cache-miss reasons that alternate between '' and +# 'node_modules/.vite/task-cache'. +node_modules diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/snapshots/direct lint.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/snapshots/direct lint.snap index 8078ba98..d1662e35 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/snapshots/direct lint.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/e2e-lint-cache/snapshots/direct lint.snap @@ -6,20 +6,6 @@ expression: e2e_outputs $ vp lint Found 0 warnings and 0 errors. Finished in on 0 files with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] e2e-lint-cache#lint: $ vp lint ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > echo debugger > main.js # add lint error > vp run lint # cache miss, lint fails @@ -34,17 +20,3 @@ $ vp lint ✗ cache miss: content of input '' changed, executing Found 1 warning and 0 errors. Finished in on 1 file with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] e2e-lint-cache#lint: $ vp lint ✓ - → Cache miss: content of input '' changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exec-api/snapshots/exec not triggered from script.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exec-api/snapshots/exec not triggered from script.snap index eb4fade4..e72e9ea7 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exec-api/snapshots/exec not triggered from script.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exec-api/snapshots/exec not triggered from script.snap @@ -6,17 +6,3 @@ expression: e2e_outputs $ vp lint Found 0 warnings and 0 errors. Finished in on 0 files with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @test/exec-api#lint-task: $ vp lint ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/multiple task failures returns exit code 1.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/multiple task failures returns exit code 1.snap index acff1d72..28687d8a 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/multiple task failures returns exit code 1.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/multiple task failures returns exit code 1.snap @@ -7,19 +7,5 @@ expression: e2e_outputs ~/packages/pkg-b$ node -e "process.exit(7)" - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 2 cache misses • 2 failed -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] pkg-a#fail: ~/packages/pkg-a$ node -e "process.exit(42)" ✗ (exit code: 42) - → Cache miss: no previous cache entry found - ······················································· - [2] pkg-b#fail: ~/packages/pkg-b$ node -e "process.exit(7)" ✗ (exit code: 7) - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%), 2 failed. (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/single task failure returns task exit code.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/single task failure returns task exit code.snap index 310238da..4f59078e 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/single task failure returns task exit code.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/single task failure returns task exit code.snap @@ -4,17 +4,3 @@ expression: e2e_outputs --- [42]> vp run pkg-a#fail # exits with code 42 ~/packages/pkg-a$ node -e "process.exit(42)" - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses • 1 failed -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] pkg-a#fail: ~/packages/pkg-a$ node -e "process.exit(42)" ✗ (exit code: 42) - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-adt-args/snapshots/individual cache for extra args.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-adt-args/snapshots/individual cache for extra args.snap index de8f439e..13672042 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-adt-args/snapshots/individual cache for extra args.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-adt-args/snapshots/individual cache for extra args.snap @@ -5,68 +5,18 @@ expression: e2e_outputs > vp run say a # cache miss $ print a a - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] say: $ print a ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run say b # cache miss, different args $ print b b - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] say: $ print b ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run say a # cache hit $ print a ✓ cache hit, replaying a - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] say: $ print a ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > vp run say b # cache hit $ print b ✓ cache hit, replaying b - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] say: $ print b ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-envs/snapshots/individual cache for envs.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-envs/snapshots/individual cache for envs.snap index 1d0620a0..baee0694 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-envs/snapshots/individual cache for envs.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/individual-cache-for-envs/snapshots/individual cache for envs.snap @@ -5,68 +5,18 @@ expression: e2e_outputs > FOO=1 vp run hello # cache miss $ print-env FOO 1 - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] hello: $ print-env FOO ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > FOO=2 vp run hello # cache miss, different env $ print-env FOO ✗ cache miss: envs changed, executing 2 - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] hello: $ print-env FOO ✓ - → Cache miss: env FOO value changed from '1' to '2' -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > FOO=1 vp run hello # cache hit $ print-env FOO ✓ cache hit, replaying 1 - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] hello: $ print-env FOO ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > FOO=2 vp run hello # cache hit $ print-env FOO ✓ cache hit, replaying 2 - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] hello: $ print-env FOO ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/.gitignore b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/.gitignore new file mode 100644 index 00000000..231280da --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/.gitignore @@ -0,0 +1,7 @@ +# Prevent oxlint from scanning node_modules. +# Without this, oxlint reads files in node_modules/.vite/task-cache, causing +# fspy to fingerprint the cache directory as an input. The cache directory +# changes between runs (DB writes, last-summary.json), producing flaky +# cache-miss reasons that alternate between '' and +# 'node_modules/.vite/task-cache'. +node_modules diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/snapshots/lint dot git.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/snapshots/lint dot git.snap index 38ea12c2..17184c99 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/snapshots/lint dot git.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/lint-dot-git/snapshots/lint dot git.snap @@ -16,20 +16,6 @@ $ vp lint Found 1 warning and 0 errors. Finished in on 1 file with 90 rules using threads. - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > echo hello > .git/foo.txt # add file inside .git > vp run lint # cache hit, .git is ignored @@ -45,16 +31,5 @@ $ vp lint ✓ cache hit, replaying Found 1 warning and 0 errors. Finished in on 1 file with 90 rules using threads. - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] lint: $ vp lint ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/replay-logs-chronological-order/snapshots/replay logs chronological order.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/replay-logs-chronological-order/snapshots/replay logs chronological order.snap index 7b0be9e8..32199a51 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/replay-logs-chronological-order/snapshots/replay logs chronological order.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/replay-logs-chronological-order/snapshots/replay logs chronological order.snap @@ -97,20 +97,6 @@ $ node build.js [echo.js] 30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 [echo.js] -------------------------------- [build.js] main process end - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] build: $ node build.js ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run build # cache hit $ node build.js ✓ cache hit, replaying [build.js] -------------------------------- @@ -207,19 +193,8 @@ $ node build.js ✓ cache hit, replaying [echo.js] -------------------------------- [build.js] main process end - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] build: $ node build.js ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > vp run build # cache hit $ node build.js ✓ cache hit, replaying [build.js] -------------------------------- @@ -316,16 +291,5 @@ $ node build.js ✓ cache hit, replaying [echo.js] -------------------------------- [build.js] main process end - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] build: $ node build.js ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/shared-caching-inputs/snapshots/shared caching inputs.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/shared-caching-inputs/snapshots/shared caching inputs.snap index f42197bc..bc83c8bb 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/shared-caching-inputs/snapshots/shared caching inputs.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/shared-caching-inputs/snapshots/shared caching inputs.snap @@ -5,70 +5,20 @@ expression: e2e_outputs > vp run script1 # cache miss $ print-file foo.txt initial content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] script1: $ print-file foo.txt ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run script2 # cache hit, same command as script1 $ print-file foo.txt ✓ cache hit, replaying initial content - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] script2: $ print-file foo.txt ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. > replace-file-content foo.txt initial modified # modify shared input > vp run script2 # cache miss, input changed $ print-file foo.txt ✗ cache miss: content of input 'foo.txt' changed, executing modified content - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] script2: $ print-file foo.txt ✓ - → Cache miss: content of input 'foo.txt' changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run script1 # cache hit, script2 already warmed cache $ print-file foo.txt ✓ cache hit, replaying modified content - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] script1: $ print-file foo.txt ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/signal-exit/snapshots/signal terminated task returns non-zero exit code.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/signal-exit/snapshots/signal terminated task returns non-zero exit code.snap index c47cb863..a440d1c1 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/signal-exit/snapshots/signal terminated task returns non-zero exit code.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/signal-exit/snapshots/signal terminated task returns non-zero exit code.snap @@ -4,17 +4,3 @@ expression: e2e_outputs --- [134]> vp run abort # SIGABRT -> exit code 134 $ node -e "process.kill(process.pid, 6)" - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses • 1 failed -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] signal-exit-test#abort: $ node -e "process.kill(process.pid, 6)" ✗ (exit code: 134) - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/multiple tasks get null stdin.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/multiple tasks get null stdin.snap index 5d6f5884..6726177c 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/multiple tasks get null stdin.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/multiple tasks get null stdin.snap @@ -5,21 +5,7 @@ expression: e2e_outputs > echo from-stdin | vp run -r read-stdin ~/packages/other$ read-stdin -$ read-stdin ⊘ cache disabled: no cache config +$ read-stdin ⊘ cache disabled - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 1 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] other#read-stdin: ~/packages/other$ read-stdin ✓ - → Cache miss: no previous cache entry found - ······················································· - [2] stdin-inheritance-test#read-stdin: $ read-stdin ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task no cache inherits stdin.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task no cache inherits stdin.snap index 3ed85c44..1496b7ea 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task no cache inherits stdin.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task no cache inherits stdin.snap @@ -3,19 +3,5 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > echo from-stdin | vp run read-stdin -$ read-stdin ⊘ cache disabled: no cache config +$ read-stdin ⊘ cache disabled from-stdin - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdin-inheritance-test#read-stdin: $ read-stdin ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task with cache gets null stdin.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task with cache gets null stdin.snap index c6a38299..56301c7d 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task with cache gets null stdin.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/single task with cache gets null stdin.snap @@ -4,17 +4,3 @@ expression: e2e_outputs --- > echo from-stdin | vp run read-stdin-cached $ read-stdin - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdin-inheritance-test#read-stdin-cached: $ read-stdin ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache disabled.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache disabled.snap index 56088f27..c349e240 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache disabled.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache disabled.snap @@ -8,24 +8,10 @@ stdin:not-tty stdout:not-tty stderr:not-tty -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 1 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] other#check-tty: ~/packages/other$ check-tty ✓ - → Cache miss: no previous cache entry found - ······················································· - [2] stdio-detection-test#check-tty: $ check-tty ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache hit.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache hit.snap index 707718c8..45275846 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache hit.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache hit.snap @@ -13,22 +13,8 @@ stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 2 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] other#check-tty-cached: ~/packages/other$ check-tty ✓ - → Cache miss: no previous cache entry found - ······················································· - [2] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) > vp run -r check-tty-cached ~/packages/other$ check-tty ✓ cache hit, replaying stdin:not-tty @@ -40,19 +26,5 @@ stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 2 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] other#check-tty-cached: ~/packages/other$ check-tty ✓ - → Cache hit - output replayed - saved - ······················································· - [2] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 2/2 cache hit (100%), saved. (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache miss.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache miss.snap index 2a2d6eeb..b323837e 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache miss.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache miss.snap @@ -13,19 +13,5 @@ stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 2 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] other#check-tty-cached: ~/packages/other$ check-tty ✓ - → Cache miss: no previous cache entry found - ······················································· - [2] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache disabled.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache disabled.snap index afea75d1..b4f62e70 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache disabled.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache disabled.snap @@ -3,21 +3,7 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run check-tty -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:tty stdout:tty stderr:tty - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdio-detection-test#check-tty: $ check-tty ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache hit.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache hit.snap index 5381bb2f..2f1b1839 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache hit.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache hit.snap @@ -7,36 +7,11 @@ $ check-tty stdin:not-tty stdout:not-tty stderr:not-tty - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ > vp run check-tty-cached $ check-tty ✓ cache hit, replaying stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 1 cache hits • 0 cache misses -Performance: 100% cache hit rate, saved in total - -Task Details: -──────────────────────────────────────────────── - [1] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache hit - output replayed - saved -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache miss.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache miss.snap index 2d0a4310..0763cd35 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache miss.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/single task, cache miss.snap @@ -7,17 +7,3 @@ $ check-tty stdin:not-tty stdout:not-tty stderr:not-tty - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 1 cache misses -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdio-detection-test#check-tty-cached: $ check-tty ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/multi-node ancestor forces piped for nested single-node graph.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/multi-node ancestor forces piped for nested single-node graph.snap index 15f23f7d..af2428c0 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/multi-node ancestor forces piped for nested single-node graph.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/multi-node ancestor forces piped for nested single-node graph.snap @@ -3,29 +3,15 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run -r foo-nested -~/packages/other$ check-tty ⊘ cache disabled: no cache config +~/packages/other$ check-tty ⊘ cache disabled stdin:not-tty stdout:not-tty stderr:not-tty -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 0 cache misses • 2 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] other#bar: ~/packages/other$ check-tty ✓ - → Cache disabled in task configuration - ······················································· - [2] stdio-graph-criteria-test#bar: $ check-tty ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/single-node chains inherit even with multi-node sibling graph.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/single-node chains inherit even with multi-node sibling graph.snap index 3a9c8bda..a88e1731 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/single-node chains inherit even with multi-node sibling graph.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-graph-criteria/snapshots/single-node chains inherit even with multi-node sibling graph.snap @@ -3,45 +3,25 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run foo -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:tty stdout:tty stderr:tty -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:tty stdout:tty stderr:tty -~/packages/other$ check-tty ⊘ cache disabled: no cache config +~/packages/other$ check-tty ⊘ cache disabled stdin:not-tty stdout:not-tty stderr:not-tty -$ check-tty ⊘ cache disabled: no cache config +$ check-tty ⊘ cache disabled stdin:not-tty stdout:not-tty stderr:not-tty - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 4 tasks • 0 cache hits • 0 cache misses • 4 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] stdio-graph-criteria-test#foo: $ check-tty ✓ - → Cache disabled in task configuration - ······················································· - [2] stdio-graph-criteria-test#bar: $ check-tty ✓ - → Cache disabled in task configuration - ······················································· - [3] other#check-tty: ~/packages/other$ check-tty ✓ - → Cache disabled in task configuration - ······················································· - [4] stdio-graph-criteria-test#check-tty: $ check-tty ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/4 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/package.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/package.json new file mode 100644 index 00000000..99f164ce --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/package.json @@ -0,0 +1,4 @@ +{ + "name": "summary-output-test", + "private": true +} diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/a/package.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/a/package.json new file mode 100644 index 00000000..e940683c --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/a/package.json @@ -0,0 +1,6 @@ +{ + "name": "@summary/a", + "scripts": { + "build": "print built-a" + } +} diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/b/package.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/b/package.json new file mode 100644 index 00000000..08f6e258 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/packages/b/package.json @@ -0,0 +1,9 @@ +{ + "name": "@summary/b", + "dependencies": { + "@summary/a": "workspace:*" + }, + "scripts": { + "build": "print built-b" + } +} diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/pnpm-workspace.yaml b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/pnpm-workspace.yaml new file mode 100644 index 00000000..924b55f4 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - packages/* diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots.toml b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots.toml new file mode 100644 index 00000000..ae9adc6a --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots.toml @@ -0,0 +1,80 @@ +# Tests for compact and verbose summary output + +# Single task, cache miss → no summary at all +[[e2e]] +name = "single task cache miss shows no summary" +cwd = "packages/a" +steps = [ + "vp run build", +] + +# Single task, cache hit → compact one-liner +[[e2e]] +name = "single task cache hit shows compact summary" +cwd = "packages/a" +steps = [ + "vp run build # first run, cache miss", + "vp run build # second run, cache hit → compact summary", +] + +# Multi-task (recursive), all cache miss → compact summary with 0 hits +[[e2e]] +name = "multi task all cache miss shows compact summary" +steps = [ + "vp run -r build", +] + +# Multi-task (recursive), some cache hits → compact summary with hit count +[[e2e]] +name = "multi task with cache hits shows compact summary" +steps = [ + "vp run -r build # first run, all miss", + "vp run -r build # second run, all hit", +] + +# Single task with --verbose → full detailed summary +[[e2e]] +name = "single task verbose shows full summary" +cwd = "packages/a" +steps = [ + "vp run -v build", +] + +# Multi-task with --verbose → full detailed summary +[[e2e]] +name = "multi task verbose shows full summary" +steps = [ + "vp run -r -v build", +] + +# Multi-task with --verbose after cache hits +[[e2e]] +name = "multi task verbose with cache hits shows full summary" +steps = [ + "vp run -r build # first run, populate cache", + "vp run -r -v build # second run, verbose with cache hits", +] + +# --last-details with no previous run +[[e2e]] +name = "last details with no previous run shows error" +steps = [ + "vp run --last-details", +] + +# --last-details after a run shows saved summary +[[e2e]] +name = "last details after run shows saved summary" +cwd = "packages/a" +steps = [ + "vp run build # populate summary file", + "vp run --last-details # display saved summary", +] + +# --last-details after a multi-task run +[[e2e]] +name = "last details after multi task run shows saved summary" +steps = [ + "vp run -r build # populate summary file", + "vp run --last-details # display saved summary", +] diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after multi task run shows saved summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after multi task run shows saved summary.snap new file mode 100644 index 00000000..68443d6a --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after multi task run shows saved summary.snap @@ -0,0 +1,30 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -r build # populate summary file +~/packages/a$ print built-a +built-a + +~/packages/b$ print built-b +built-b + +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) +> vp run --last-details # display saved summary + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 2 tasks • 0 cache hits • 2 cache misses +Performance: 0% cache hit rate + +Task Details: +──────────────────────────────────────────────── + [1] @summary/a#build: ~/packages/a$ print built-a ✓ + → Cache miss: no previous cache entry found + ······················································· + [2] @summary/b#build: ~/packages/b$ print built-b ✓ + → Cache miss: no previous cache entry found +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after run shows saved summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after run shows saved summary.snap new file mode 100644 index 00000000..01712736 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details after run shows saved summary.snap @@ -0,0 +1,21 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run build # populate summary file +~/packages/a$ print built-a +built-a +> vp run --last-details # display saved summary + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 1 tasks • 0 cache hits • 1 cache misses +Performance: 0% cache hit rate + +Task Details: +──────────────────────────────────────────────── + [1] @summary/a#build: ~/packages/a$ print built-a ✓ + → Cache miss: no previous cache entry found +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details with no previous run shows error.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details with no previous run shows error.snap new file mode 100644 index 00000000..29df10a7 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/last details with no previous run shows error.snap @@ -0,0 +1,6 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +[1]> vp run --last-details +No previous run summary found. Run a task first to generate a summary. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task all cache miss shows compact summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task all cache miss shows compact summary.snap new file mode 100644 index 00000000..d9feb62d --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task all cache miss shows compact summary.snap @@ -0,0 +1,13 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -r build +~/packages/a$ print built-a +built-a + +~/packages/b$ print built-b +built-b + +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose shows full summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose shows full summary.snap new file mode 100644 index 00000000..f0d6fbcc --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose shows full summary.snap @@ -0,0 +1,27 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -r -v build +~/packages/a$ print built-a +built-a + +~/packages/b$ print built-b +built-b + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 2 tasks • 0 cache hits • 2 cache misses +Performance: 0% cache hit rate + +Task Details: +──────────────────────────────────────────────── + [1] @summary/a#build: ~/packages/a$ print built-a ✓ + → Cache miss: no previous cache entry found + ······················································· + [2] @summary/b#build: ~/packages/b$ print built-b ✓ + → Cache miss: no previous cache entry found +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose with cache hits shows full summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose with cache hits shows full summary.snap new file mode 100644 index 00000000..559bd896 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task verbose with cache hits shows full summary.snap @@ -0,0 +1,36 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -r build # first run, populate cache +~/packages/a$ print built-a +built-a + +~/packages/b$ print built-b +built-b + +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) +> vp run -r -v build # second run, verbose with cache hits +~/packages/a$ print built-a ✓ cache hit, replaying +built-a + +~/packages/b$ print built-b ✓ cache hit, replaying +built-b + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 2 tasks • 2 cache hits • 0 cache misses +Performance: 100% cache hit rate, saved in total + +Task Details: +──────────────────────────────────────────────── + [1] @summary/a#build: ~/packages/a$ print built-a ✓ + → Cache hit - output replayed - saved + ······················································· + [2] @summary/b#build: ~/packages/b$ print built-b ✓ + → Cache hit - output replayed - saved +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task with cache hits shows compact summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task with cache hits shows compact summary.snap new file mode 100644 index 00000000..c11e56e9 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/multi task with cache hits shows compact summary.snap @@ -0,0 +1,22 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -r build # first run, all miss +~/packages/a$ print built-a +built-a + +~/packages/b$ print built-b +built-b + +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) +> vp run -r build # second run, all hit +~/packages/a$ print built-a ✓ cache hit, replaying +built-a + +~/packages/b$ print built-b ✓ cache hit, replaying +built-b + +--- +[vp run] 2/2 cache hit (100%), saved. (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache hit shows compact summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache hit shows compact summary.snap new file mode 100644 index 00000000..358657d8 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache hit shows compact summary.snap @@ -0,0 +1,13 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run build # first run, cache miss +~/packages/a$ print built-a +built-a +> vp run build # second run, cache hit → compact summary +~/packages/a$ print built-a ✓ cache hit, replaying +built-a + +--- +[vp run] cache hit, saved. diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache miss shows no summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache miss shows no summary.snap new file mode 100644 index 00000000..b3fecf79 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task cache miss shows no summary.snap @@ -0,0 +1,7 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run build +~/packages/a$ print built-a +built-a diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task verbose shows full summary.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task verbose shows full summary.snap new file mode 100644 index 00000000..28abff9f --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/snapshots/single task verbose shows full summary.snap @@ -0,0 +1,21 @@ +--- +source: crates/vite_task_bin/tests/e2e_snapshots/main.rs +expression: e2e_outputs +--- +> vp run -v build +~/packages/a$ print built-a +built-a + + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + Vite+ Task Runner • Execution Summary +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +Statistics: 1 tasks • 0 cache hits • 1 cache misses +Performance: 0% cache hit rate + +Task Details: +──────────────────────────────────────────────── + [1] @summary/a#build: ~/packages/a$ print built-a ✓ + → Cache miss: no previous cache entry found +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/vite-task.json b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/vite-task.json new file mode 100644 index 00000000..1d0fe9f2 --- /dev/null +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/summary-output/vite-task.json @@ -0,0 +1,3 @@ +{ + "cacheScripts": true +} diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-list/snapshots/vp run in script.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-list/snapshots/vp run in script.snap index b0e427ef..3e933d32 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-list/snapshots/vp run in script.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-list/snapshots/vp run in script.snap @@ -4,7 +4,7 @@ expression: e2e_outputs --- > vp run list-tasks @ expect-milestone: task-select::0 -$ vp run ⊘ cache disabled: no cache config +$ vp run ⊘ cache disabled Search task (↑/↓ to move, enter to select): > hello: echo hello from root list-tasks: vp run @@ -13,34 +13,6 @@ Search task (↑/↓ to move, enter to select): app#test: echo test app lib#build: echo build lib @ write-key: enter -$ vp run ⊘ cache disabled: no cache config -$ echo hello from root ⊘ cache disabled: built-in command +$ vp run ⊘ cache disabled +$ echo hello from root ⊘ cache disabled hello from root - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] task-list-test#hello: $ echo hello from root ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] task-list-test#list-tasks: $ vp run ✓ - → Cache disabled in task configuration -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-no-trailing-newline/snapshots/no trailing newline.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-no-trailing-newline/snapshots/no trailing newline.snap index 8e80c017..442d5f93 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-no-trailing-newline/snapshots/no trailing newline.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-no-trailing-newline/snapshots/no trailing newline.snap @@ -3,24 +3,10 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run hello # runs echo -n hello -$ echo -n foo ⊘ cache disabled: built-in command +$ echo -n foo ⊘ cache disabled foo -$ echo bar ⊘ cache disabled: built-in command +$ echo bar ⊘ cache disabled bar - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 0 cache misses • 2 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] hello: $ echo -n foo ✓ - → Cache disabled for built-in command - ······················································· - [2] hello: $ echo bar ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select-truncate/snapshots/interactive long command truncated.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select-truncate/snapshots/interactive long command truncated.snap index 0ff4c0d7..6b3f2572 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select-truncate/snapshots/interactive long command truncated.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select-truncate/snapshots/interactive long command truncated.snap @@ -38,19 +38,5 @@ Search task (↑/↓ to move, enter to select): > long-cmd: echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa… test: echo test app @ write-key: enter -~/packages/app$ echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ⊘ cache disabled: built-in command +~/packages/app$ echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ⊘ cache disabled aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#long-cmd: ~/packages/app$ echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive enter with no results does nothing.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive enter with no results does nothing.snap index 653c1409..502ef93c 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive enter with no results does nothing.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive enter with no results does nothing.snap @@ -40,19 +40,5 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive escape clears query.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive escape clears query.snap index 116c06ad..ebfff74c 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive escape clears query.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive escape clears query.snap @@ -40,19 +40,5 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive scroll long list.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive scroll long list.snap index b032faf8..42f79c81 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive scroll long list.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive scroll long list.snap @@ -65,19 +65,5 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search other package task.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search other package task.snap index ccc81642..f0a8b8d7 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search other package task.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search other package task.snap @@ -23,19 +23,5 @@ Search task (↑/↓ to move, enter to select): Search task (↑/↓ to move, enter to select): typec > lib#typecheck: echo typecheck lib @ write-key: enter -~/packages/lib$ echo typecheck lib ⊘ cache disabled: built-in command +~/packages/lib$ echo typecheck lib ⊘ cache disabled typecheck lib - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#typecheck: ~/packages/lib$ echo typecheck lib ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search preserves rating within package.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search preserves rating within package.snap index dfcbf9e9..e1ea8627 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search preserves rating within package.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search preserves rating within package.snap @@ -35,19 +35,5 @@ Search task (↑/↓ to move, enter to select): t app#test: echo test app (…1 more) @ write-key: enter -~/packages/lib$ echo test lib ⊘ cache disabled: built-in command +~/packages/lib$ echo test lib ⊘ cache disabled test lib - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#test: ~/packages/lib$ echo test lib ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search then select.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search then select.snap index 138d4395..f4900488 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search then select.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search then select.snap @@ -24,19 +24,5 @@ Search task (↑/↓ to move, enter to select): lin > lint: echo lint app lib#lint: echo lint lib @ write-key: enter -~/packages/app$ echo lint app ⊘ cache disabled: built-in command +~/packages/app$ echo lint app ⊘ cache disabled lint app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#lint: ~/packages/app$ echo lint app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search with hash skips reorder.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search with hash skips reorder.snap index 9db7109e..626115d9 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search with hash skips reorder.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive search with hash skips reorder.snap @@ -26,19 +26,5 @@ Search task (↑/↓ to move, enter to select): lib# lib#test: echo test lib lib#typecheck: echo typecheck lib @ write-key: enter -~/packages/lib$ echo build lib ⊘ cache disabled: built-in command +~/packages/lib$ echo build lib ⊘ cache disabled build lib - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#build: ~/packages/lib$ echo build lib ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task from lib.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task from lib.snap index 4aaa2919..a0131bd7 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task from lib.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task from lib.snap @@ -19,19 +19,5 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/lib$ echo build lib ⊘ cache disabled: built-in command +~/packages/lib$ echo build lib ⊘ cache disabled build lib - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#build: ~/packages/lib$ echo build lib ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task.snap index ac252807..a10f8adb 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select task.snap @@ -35,19 +35,5 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/app$ echo lint app ⊘ cache disabled: built-in command +~/packages/app$ echo lint app ⊘ cache disabled lint app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#lint: ~/packages/app$ echo lint app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with recursive.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with recursive.snap index acd834b1..02494552 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with recursive.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with recursive.snap @@ -19,25 +19,11 @@ Search task (↑/↓ to move, enter to select): task-select-test#format: echo format root (…3 more) @ write-key: enter -~/packages/lib$ echo build lib ⊘ cache disabled: built-in command +~/packages/lib$ echo build lib ⊘ cache disabled build lib -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 0 cache misses • 2 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#build: ~/packages/lib$ echo build lib ✓ - → Cache disabled for built-in command - ······················································· - [2] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo and transitive.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo and transitive.snap index f5bee2b6..43af27ab 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo and transitive.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo and transitive.snap @@ -9,25 +9,11 @@ Search task (↑/↓ to move, enter to select): buid > build: echo build app lib#build: echo build lib @ write-key: enter -~/packages/lib$ echo build lib ⊘ cache disabled: built-in command +~/packages/lib$ echo build lib ⊘ cache disabled build lib -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 0 cache misses • 2 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] lib#build: ~/packages/lib$ echo build lib ✓ - → Cache disabled for built-in command - ······················································· - [2] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo.snap index d710f842..5e0ff641 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/task-select/snapshots/interactive select with typo.snap @@ -9,19 +9,5 @@ Search task (↑/↓ to move, enter to select): buid > build: echo build app lib#build: echo build lib @ write-key: enter -~/packages/app$ echo build app ⊘ cache disabled: built-in command +~/packages/app$ echo build app ⊘ cache disabled build app - - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 1 tasks • 0 cache hits • 0 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] app#build: ~/packages/app$ echo build app ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/recursive build runs dependencies before dependents.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/recursive build runs dependencies before dependents.snap index 7027a21b..65b3a8e6 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/recursive build runs dependencies before dependents.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/recursive build runs dependencies before dependents.snap @@ -3,31 +3,14 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run -r build # core -> lib -> app -~/packages/core$ echo 'Building core' ⊘ cache disabled: built-in command +~/packages/core$ echo 'Building core' ⊘ cache disabled Building core -~/packages/lib$ echo 'Building lib' ⊘ cache disabled: built-in command +~/packages/lib$ echo 'Building lib' ⊘ cache disabled Building lib -~/packages/app$ echo 'Building app' ⊘ cache disabled: built-in command +~/packages/app$ echo 'Building app' ⊘ cache disabled Building app - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 3 tasks • 0 cache hits • 0 cache misses • 3 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @topo/core#build: ~/packages/core$ echo 'Building core' ✓ - → Cache disabled for built-in command - ······················································· - [2] @topo/lib#build: ~/packages/lib$ echo 'Building lib' ✓ - → Cache disabled for built-in command - ······················································· - [3] @topo/app#build: ~/packages/app$ echo 'Building app' ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/3 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from app runs all dependencies.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from app runs all dependencies.snap index 905651f8..db8a1f2e 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from app runs all dependencies.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from app runs all dependencies.snap @@ -3,31 +3,14 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run -t build # core -> lib -> app -~/packages/core$ echo 'Building core' ⊘ cache disabled: built-in command +~/packages/core$ echo 'Building core' ⊘ cache disabled Building core -~/packages/lib$ echo 'Building lib' ⊘ cache disabled: built-in command +~/packages/lib$ echo 'Building lib' ⊘ cache disabled Building lib -~/packages/app$ echo 'Building app' ⊘ cache disabled: built-in command +~/packages/app$ echo 'Building app' ⊘ cache disabled Building app - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 3 tasks • 0 cache hits • 0 cache misses • 3 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @topo/core#build: ~/packages/core$ echo 'Building core' ✓ - → Cache disabled for built-in command - ······················································· - [2] @topo/lib#build: ~/packages/lib$ echo 'Building lib' ✓ - → Cache disabled for built-in command - ······················································· - [3] @topo/app#build: ~/packages/app$ echo 'Building app' ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/3 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from lib runs only its dependencies.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from lib runs only its dependencies.snap index aa074606..908c547d 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from lib runs only its dependencies.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/topological-execution-order/snapshots/transitive build from lib runs only its dependencies.snap @@ -3,25 +3,11 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run -t build # core -> lib -~/packages/core$ echo 'Building core' ⊘ cache disabled: built-in command +~/packages/core$ echo 'Building core' ⊘ cache disabled Building core -~/packages/lib$ echo 'Building lib' ⊘ cache disabled: built-in command +~/packages/lib$ echo 'Building lib' ⊘ cache disabled Building lib - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 0 cache misses • 2 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] @topo/core#build: ~/packages/core$ echo 'Building core' ✓ - → Cache disabled for built-in command - ······················································· - [2] @topo/lib#build: ~/packages/lib$ echo 'Building lib' ✓ - → Cache disabled for built-in command -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite-task-smoke/snapshots/cache hit after file modification.snap b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite-task-smoke/snapshots/cache hit after file modification.snap index 4ac8bb58..bcb1e6a3 100644 --- a/crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite-task-smoke/snapshots/cache hit after file modification.snap +++ b/crates/vite_task_bin/tests/e2e_snapshots/fixtures/vite-task-smoke/snapshots/cache hit after file modification.snap @@ -3,50 +3,22 @@ source: crates/vite_task_bin/tests/e2e_snapshots/main.rs expression: e2e_outputs --- > vp run test-task # cache miss -$ echo hello ⊘ cache disabled: built-in command +$ echo hello ⊘ cache disabled hello $ print-file main.js console.log('foo'); - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 1 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] vite-task-smoke#test-task: $ echo hello ✓ - → Cache disabled for built-in command - ······················································· - [2] vite-task-smoke#test-task: $ print-file main.js ✓ - → Cache miss: no previous cache entry found -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) > replace-file-content main.js foo bar # modify input file > vp run test-task # cache miss, main.js changed -$ echo hello ⊘ cache disabled: built-in command +$ echo hello ⊘ cache disabled hello $ print-file main.js ✗ cache miss: content of input 'main.js' changed, executing console.log('bar'); - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Vite+ Task Runner • Execution Summary -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Statistics: 2 tasks • 0 cache hits • 1 cache misses • 1 cache disabled -Performance: 0% cache hit rate - -Task Details: -──────────────────────────────────────────────── - [1] vite-task-smoke#test-task: $ echo hello ✓ - → Cache disabled for built-in command - ······················································· - [2] vite-task-smoke#test-task: $ print-file main.js ✓ - → Cache miss: content of input 'main.js' changed -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +--- +[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details) diff --git a/crates/vite_task_plan/tests/plan_snapshots/main.rs b/crates/vite_task_plan/tests/plan_snapshots/main.rs index 294a74ad..fe5d49d2 100644 --- a/crates/vite_task_plan/tests/plan_snapshots/main.rs +++ b/crates/vite_task_plan/tests/plan_snapshots/main.rs @@ -174,8 +174,8 @@ fn run_case_inner( continue; } }; - let Cli::Command(command) = cli; - let Command::Run(run_command) = command else { + let Cli::Command(parsed) = cli; + let Command::Run(run_command) = parsed else { panic!("only `run` commands supported in plan tests") };