From 83c8d17984f000682005f2fc6d555d1ee02e7d43 Mon Sep 17 00:00:00 2001 From: Shubhanshu Shukla <76910689+kshanxs@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:30:14 +0530 Subject: [PATCH 1/2] feat(log): drop the package name from labels in single-package workspaces In a workspace with one package, every task belongs to that package, so `--log=labeled` and `--log=grouped` now label output `[task]` instead of `[pkg#task]`. Monorepos keep the package name. Refs voidzero-dev/vite-plus#2912 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + crates/vt/src/session/mod.rs | 55 ++++++++++++------- crates/vt/src/session/reporter/grouped/mod.rs | 9 ++- crates/vt/src/session/reporter/labeled/mod.rs | 12 +++- crates/vt/src/session/reporter/mod.rs | 15 +++-- .../fixtures/log_single_package/package.json | 4 ++ .../log_single_package/snapshots.toml | 13 +++++ .../log_single_package/snapshots/grouped.md | 18 ++++++ .../log_single_package/snapshots/labeled.md | 16 ++++++ .../log_single_package/vite-task.json | 13 +++++ crates/vt_graph/src/lib.rs | 6 ++ docs/stdio.md | 2 +- 12 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/package.json create mode 100644 crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots.toml create mode 100644 crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/grouped.md create mode 100644 crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/labeled.md create mode 100644 crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/vite-task.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e2ea8f4..c9f42f7b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +- **Changed** In a workspace with a single package, `vp run --log=labeled` and `vp run --log=grouped` now label output with `[task]` instead of `[package#task]`. Monorepos keep the package name in the label ([vite-plus#2912](https://github.com/voidzero-dev/vite-plus/issues/2912), [#???](https://github.com/voidzero-dev/vite-task/pull/???)). - **Perf** When tasks miss the cache, `vp run` no longer waits for the disk after saving each task's result, so the run finishes sooner. If the computer loses power or the operating system crashes during `vp run`, the cache entries that the run saved can be lost, and those tasks run again next time instead of hitting the cache ([#871](https://github.com/voidzero-dev/vite-task/pull/871)). - **Fixed** Running `vp run` in a package that sits inside a workspace folder but isn't listed in its `pnpm-workspace.yaml` `packages` or `package.json` `workspaces` now runs that package's own tasks, instead of treating the enclosing workspace as its root. When both configurations exist, `pnpm-workspace.yaml` takes precedence ([#859](https://github.com/voidzero-dev/vite-task/pull/859)). - **Fixed** A mistyped or misplaced setting in a task now gets an error that names it. For example, `cache: { outputs: [...] }` now fails with an `unknown field` error that names `outputs` and lists the accepted settings, instead of `data did not match any variant of untagged enum UserTaskDefinition` ([vite-plus#2635](https://github.com/voidzero-dev/vite-plus/issues/2635), [#815](https://github.com/voidzero-dev/vite-task/pull/815)). diff --git a/crates/vt/src/session/mod.rs b/crates/vt/src/session/mod.rs index 5d449279b..5e910fa44 100644 --- a/crates/vt/src/session/mod.rs +++ b/crates/vt/src/session/mod.rs @@ -337,7 +337,6 @@ impl<'a> Session<'a> { }; let workspace_path = self.workspace_path(); - let writer: Box = Box::new(std::io::stdout()); // Detect color support once at the point where reporters are // constructed. The reporters and their pipe writers then strip @@ -349,26 +348,7 @@ impl<'a> Session<'a> { stderr: stderr_supports_color(), }; - let inner: Box = match run_command - .flags - .log - { - crate::cli::LogMode::Interleaved => Box::new(InterleavedReporterBuilder::new( - Arc::clone(&workspace_path), - writer, - color_support, - )), - crate::cli::LogMode::Labeled => Box::new(LabeledReporterBuilder::new( - Arc::clone(&workspace_path), - writer, - color_support, - )), - crate::cli::LogMode::Grouped => Box::new(GroupedReporterBuilder::new( - Arc::clone(&workspace_path), - writer, - color_support, - )), - }; + let inner = self.make_mode_reporter(run_command.flags.log, color_support); let builder = Box::new(SummaryReporterBuilder::new( inner, @@ -669,6 +649,39 @@ impl<'a> Session<'a> { } } + /// Create the reporter for the `--log` mode, writing to stdout. + fn make_mode_reporter( + &self, + log_mode: crate::cli::LogMode, + color_support: ColorSupport, + ) -> Box { + let workspace_path = self.workspace_path(); + let writer: Box = Box::new(std::io::stdout()); + // In a single-package workspace every task belongs to the same package, + // so `labeled` and `grouped` label tasks as `[task]` instead of `[pkg#task]`. + let include_package_name = !matches!( + &self.lazy_task_graph, + LazyTaskGraph::Initialized(graph) if graph.is_single_package() + ); + match log_mode { + crate::cli::LogMode::Interleaved => { + Box::new(InterleavedReporterBuilder::new(workspace_path, writer, color_support)) + } + crate::cli::LogMode::Labeled => Box::new(LabeledReporterBuilder::new( + workspace_path, + writer, + color_support, + include_package_name, + )), + crate::cli::LogMode::Grouped => Box::new(GroupedReporterBuilder::new( + workspace_path, + writer, + color_support, + include_package_name, + )), + } + } + pub const fn task_graph(&self) -> Option<&TaskGraph> { match &self.lazy_task_graph { LazyTaskGraph::Initialized(graph) => Some(graph.task_graph()), diff --git a/crates/vt/src/session/reporter/grouped/mod.rs b/crates/vt/src/session/reporter/grouped/mod.rs index 78bfb48aa..42b43c426 100644 --- a/crates/vt/src/session/reporter/grouped/mod.rs +++ b/crates/vt/src/session/reporter/grouped/mod.rs @@ -22,6 +22,7 @@ pub struct GroupedReporterBuilder { workspace_path: Arc, writer: Box, color_support: ColorSupport, + include_package_name: bool, } impl GroupedReporterBuilder { @@ -34,8 +35,9 @@ impl GroupedReporterBuilder { workspace_path: Arc, writer: Box, color_support: ColorSupport, + include_package_name: bool, ) -> Self { - Self { workspace_path, writer, color_support } + Self { workspace_path, writer, color_support, include_package_name } } } @@ -45,6 +47,7 @@ impl GraphExecutionReporterBuilder for GroupedReporterBuilder { writer: Rc::new(RefCell::new(self.writer)), workspace_path: self.workspace_path, color_support: self.color_support, + include_package_name: self.include_package_name, }) } } @@ -53,6 +56,7 @@ struct GroupedGraphReporter { writer: Rc>>, workspace_path: Arc, color_support: ColorSupport, + include_package_name: bool, } impl GraphExecutionReporter for GroupedGraphReporter { @@ -61,7 +65,7 @@ impl GraphExecutionReporter for GroupedGraphReporter { display: &ExecutionItemDisplay, _leaf_kind: &LeafExecutionKind, ) -> Box { - let label = format_task_label(display); + let label = format_task_label(display, self.include_package_name); Box::new(GroupedLeafReporter { writer: Rc::clone(&self.writer), display: display.clone(), @@ -177,6 +181,7 @@ mod tests { test_path(), Box::new(std::io::sink()), ColorSupport::uniform(false), + true, )); let mut reporter = builder.build(); let mut leaf = reporter.new_leaf_execution(&item.execution_item_display, leaf_kind(item)); diff --git a/crates/vt/src/session/reporter/labeled/mod.rs b/crates/vt/src/session/reporter/labeled/mod.rs index ae50f796e..444ad5689 100644 --- a/crates/vt/src/session/reporter/labeled/mod.rs +++ b/crates/vt/src/session/reporter/labeled/mod.rs @@ -4,6 +4,7 @@ use std::{cell::RefCell, io::Write, process::ExitStatus as StdExitStatus, rc::Rc use vt_path::AbsolutePath; use vt_plan::{ExecutionItemDisplay, LeafExecutionKind}; +use vt_str::Str; use super::{ ColorSupport, ExitStatus, GraphExecutionReporter, GraphExecutionReporterBuilder, @@ -21,6 +22,7 @@ pub struct LabeledReporterBuilder { workspace_path: Arc, writer: Box, color_support: ColorSupport, + include_package_name: bool, } impl LabeledReporterBuilder { @@ -31,8 +33,9 @@ impl LabeledReporterBuilder { workspace_path: Arc, writer: Box, color_support: ColorSupport, + include_package_name: bool, ) -> Self { - Self { workspace_path, writer, color_support } + Self { workspace_path, writer, color_support, include_package_name } } } @@ -42,6 +45,7 @@ impl GraphExecutionReporterBuilder for LabeledReporterBuilder { writer: Rc::new(RefCell::new(self.writer)), workspace_path: self.workspace_path, color_support: self.color_support, + include_package_name: self.include_package_name, }) } } @@ -50,6 +54,7 @@ struct LabeledGraphReporter { writer: Rc>>, workspace_path: Arc, color_support: ColorSupport, + include_package_name: bool, } impl GraphExecutionReporter for LabeledGraphReporter { @@ -62,6 +67,7 @@ impl GraphExecutionReporter for LabeledGraphReporter { writer: Rc::clone(&self.writer), display: display.clone(), workspace_path: Arc::clone(&self.workspace_path), + label: format_task_label(display, self.include_package_name), started: false, color_support: self.color_support, }) @@ -78,13 +84,14 @@ struct LabeledLeafReporter { writer: Rc>>, display: ExecutionItemDisplay, workspace_path: Arc, + label: Str, started: bool, color_support: ColorSupport, } impl LeafExecutionReporter for LabeledLeafReporter { fn start(&mut self, cache_status: CacheStatus) -> StdioConfig { - let label = format_task_label(&self.display); + let label = &self.label; let line = format_command_with_cache_status(&self.display, &self.workspace_path, &cache_status); @@ -157,6 +164,7 @@ mod tests { test_path(), Box::new(std::io::sink()), ColorSupport::uniform(false), + true, )); let mut reporter = builder.build(); let mut leaf = reporter.new_leaf_execution(&item.execution_item_display, leaf_kind(item)); diff --git a/crates/vt/src/session/reporter/mod.rs b/crates/vt/src/session/reporter/mod.rs index af0396f93..f02c05d06 100644 --- a/crates/vt/src/session/reporter/mod.rs +++ b/crates/vt/src/session/reporter/mod.rs @@ -257,11 +257,16 @@ fn format_cwd_relative(display: &ExecutionItemDisplay, workspace_path: &Absolute } /// Format the task label for labeled/grouped modes (e.g., `[pkg#task]`). -fn format_task_label(display: &ExecutionItemDisplay) -> Str { - vt_str::format!( - "{}", - vt_str::format!("[{}]", display.task_display).style(Style::new().bright_black()) - ) +/// +/// With `include_package_name` set to `false`, the label is just `[task]`. +/// Used for single-package workspaces, where every task is in the same package. +fn format_task_label(display: &ExecutionItemDisplay, include_package_name: bool) -> Str { + let label = if include_package_name { + vt_str::format!("[{}]", display.task_display) + } else { + vt_str::format!("[{}]", display.task_display.task_name) + }; + vt_str::format!("{}", label.style(Style::new().bright_black())) } /// Format the command string with cwd prefix for display (e.g., `~/packages/lib$ vitest run`). diff --git a/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/package.json b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/package.json new file mode 100644 index 000000000..6e774a834 --- /dev/null +++ b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/package.json @@ -0,0 +1,4 @@ +{ + "name": "single-package", + "private": true +} diff --git a/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots.toml b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots.toml new file mode 100644 index 000000000..e0d31824d --- /dev/null +++ b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots.toml @@ -0,0 +1,13 @@ +[[e2e]] +name = "labeled" +comment = """ +In a single-package workspace, `--log=labeled` prefixes lines with `[task]` instead of `[pkg#task]`. +""" +steps = [["vt", "run", "--log=labeled", "build"]] + +[[e2e]] +name = "grouped" +comment = """ +In a single-package workspace, `--log=grouped` labels each block with `[task]` instead of `[pkg#task]`. +""" +steps = [["vt", "run", "--log=grouped", "build"]] diff --git a/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/grouped.md b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/grouped.md new file mode 100644 index 000000000..0619f954b --- /dev/null +++ b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/grouped.md @@ -0,0 +1,18 @@ +# grouped + +In a single-package workspace, `--log=grouped` labels each block with `[task]` instead of `[pkg#task]`. + +## `vt run --log=grouped build` + +``` +[lint] $ echo lint ⊘ cache disabled +── [lint] ── +lint + +[build] $ echo build ⊘ cache disabled +── [build] ── +build + +--- +vt run: 2/2 successful. (Run `vt run --last-details` for full details) +``` diff --git a/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/labeled.md b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/labeled.md new file mode 100644 index 000000000..16b728853 --- /dev/null +++ b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/snapshots/labeled.md @@ -0,0 +1,16 @@ +# labeled + +In a single-package workspace, `--log=labeled` prefixes lines with `[task]` instead of `[pkg#task]`. + +## `vt run --log=labeled build` + +``` +[lint] $ echo lint ⊘ cache disabled +[lint] lint + +[build] $ echo build ⊘ cache disabled +[build] build + +--- +vt run: 2/2 successful. (Run `vt run --last-details` for full details) +``` diff --git a/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/vite-task.json b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/vite-task.json new file mode 100644 index 000000000..094dfec36 --- /dev/null +++ b/crates/vt_bin/tests/e2e_snapshots/fixtures/log_single_package/vite-task.json @@ -0,0 +1,13 @@ +{ + "tasks": { + "lint": { + "command": "echo lint", + "cache": false + }, + "build": { + "command": "echo build", + "dependsOn": ["lint"], + "cache": false + } + } +} diff --git a/crates/vt_graph/src/lib.rs b/crates/vt_graph/src/lib.rs index 7169a95b0..e26ba7119 100644 --- a/crates/vt_graph/src/lib.rs +++ b/crates/vt_graph/src/lib.rs @@ -572,6 +572,12 @@ impl IndexedTaskGraph { &self.task_graph } + /// Whether the workspace has only one package, i.e. it is not a monorepo. + #[must_use] + pub fn is_single_package(&self) -> bool { + self.indexed_package_graph.package_graph().node_count() == 1 + } + #[must_use] pub fn get_package_name(&self, package_index: PackageNodeIndex) -> &str { self.indexed_package_graph.package_graph()[package_index].package_json.name.as_str() diff --git a/docs/stdio.md b/docs/stdio.md index 2d7e0e316..9bfd2e39e 100644 --- a/docs/stdio.md +++ b/docs/stdio.md @@ -18,7 +18,7 @@ The flag goes before the task name. Anything after the task name is passed to th ### Examples -In `interleaved` mode, task names are omitted from the command line to keep output clean. In `labeled` and `grouped` modes, the `[pkg#task]` prefix is necessary to identify which task produced each line. +In `interleaved` mode, task names are omitted from the command line to keep output clean. In `labeled` and `grouped` modes, the `[pkg#task]` prefix is necessary to identify which task produced each line. In a workspace with a single package, the prefix is just `[task]`, since every task belongs to that package. #### `interleaved` From cf81582b4f44ef9d636fc2b5a852801d2535c5db Mon Sep 17 00:00:00 2001 From: Shubhanshu Shukla <76910689+kshanxs@users.noreply.github.com> Date: Sun, 25 Oct 2026 01:30:48 +0530 Subject: [PATCH 2/2] docs(changelog): link #883 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f42f7b4..3bbbd9c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -- **Changed** In a workspace with a single package, `vp run --log=labeled` and `vp run --log=grouped` now label output with `[task]` instead of `[package#task]`. Monorepos keep the package name in the label ([vite-plus#2912](https://github.com/voidzero-dev/vite-plus/issues/2912), [#???](https://github.com/voidzero-dev/vite-task/pull/???)). +- **Changed** In a workspace with a single package, `vp run --log=labeled` and `vp run --log=grouped` now label output with `[task]` instead of `[package#task]`. Monorepos keep the package name in the label ([vite-plus#2912](https://github.com/voidzero-dev/vite-plus/issues/2912), [#883](https://github.com/voidzero-dev/vite-task/pull/883)). - **Perf** When tasks miss the cache, `vp run` no longer waits for the disk after saving each task's result, so the run finishes sooner. If the computer loses power or the operating system crashes during `vp run`, the cache entries that the run saved can be lost, and those tasks run again next time instead of hitting the cache ([#871](https://github.com/voidzero-dev/vite-task/pull/871)). - **Fixed** Running `vp run` in a package that sits inside a workspace folder but isn't listed in its `pnpm-workspace.yaml` `packages` or `package.json` `workspaces` now runs that package's own tasks, instead of treating the enclosing workspace as its root. When both configurations exist, `pnpm-workspace.yaml` takes precedence ([#859](https://github.com/voidzero-dev/vite-task/pull/859)). - **Fixed** A mistyped or misplaced setting in a task now gets an error that names it. For example, `cache: { outputs: [...] }` now fails with an `unknown field` error that names `outputs` and lists the accepted settings, instead of `data did not match any variant of untagged enum UserTaskDefinition` ([vite-plus#2635](https://github.com/voidzero-dev/vite-plus/issues/2635), [#815](https://github.com/voidzero-dev/vite-task/pull/815)).