Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

- **Fixed** Uncached tasks executed directly now preserve colors with `vp run --log labeled` and `--log grouped`, including Vitest coverage tables ([#997](https://github.com/voidzero-dev/vite-task/pull/997)).

- **Fixed** On Windows, tasks with automatic file-access tracking can now run Git Bash's `sh` and other MSYS2 or Cygwin programs, which aborted with `fatal error - MapViewOfFileEx 'shared.5'(…) Win32 error 487` ([#830](https://github.com/voidzero-dev/vite-task/issues/830), [#952](https://github.com/voidzero-dev/vite-task/pull/952)).
- **Fixed** On Linux, cached tasks no longer fail to spawn child processes in restricted sandboxes, for example rootless bubblewrap that denies the `seccomp` syscall. When the `seccomp` filter for file-access tracking cannot be installed, the process runs untracked instead and the run is reported as not cached. The not-cached message now reads "automatic file tracking couldn't record everything this task did", which fits both this case and a full tracking channel ([#700](https://github.com/voidzero-dev/vite-task/issues/700), [#701](https://github.com/voidzero-dev/vite-task/pull/701)).
- **Fixed** `vp run <task>` in a package that doesn't define the task now reports `Task "<task>" not found` when another package's `vite.config.*` fails to load, instead of failing with that package's error. Showing the tasks to choose from loads every package's config, so the task selector or task list is skipped then ([#987](https://github.com/voidzero-dev/vite-task/pull/987)).
Expand Down
21 changes: 16 additions & 5 deletions crates/vt/src/session/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ use std::{

use futures_util::future::LocalBoxFuture;
use tokio_util::sync::CancellationToken;
use vt_casefold::EnvName;
use vt_glob::path::PathGlobSet;
use vt_ipc_shared::NODE_CLIENT_PATH_ENV_NAME;
use vt_path::{AbsolutePath, RelativePathBuf};
use vt_plan::{SpawnExecution, cache_metadata::CacheMetadata};
use vt_plan::{SpawnCommand, SpawnExecution, cache_metadata::CacheMetadata};
use vt_server::{Recorder, Reports, ServerHandle, StopAccepting, serve};

use self::{
Expand Down Expand Up @@ -205,9 +206,10 @@ impl<'a> ExecutionMode<'a> {
}

/// The extra envs to inject into the child: IPC connection info + the
/// napi addon path runner-aware tools `require()`. Empty when execution
/// is uncached.
fn injected_envs(&self) -> Vec<(&OsStr, &OsStr)> {
/// napi addon path runner-aware tools `require()`. Uncached piped tasks
/// also preserve the parent terminal's color support unless the task
/// explicitly controls colors.
fn injected_envs(&self, command: &SpawnCommand) -> Vec<(&OsStr, &OsStr)> {
match self {
Self::Cached { state: CacheState { tracking: t, .. }, .. } => {
let mut envs: Vec<(&OsStr, &OsStr)> =
Expand All @@ -218,6 +220,15 @@ impl<'a> ExecutionMode<'a> {
));
envs
}
Self::Uncached { pipe_writers: Some(_) }
if !command.shell_fallback
&& super::stdout_supports_color()
&& !["FORCE_COLOR", "NO_COLOR", "NODE_DISABLE_COLORS"].iter().any(|name| {
command.spawn_envs.contains_key(EnvName::from_ref(OsStr::new(name)))
Comment thread
Siornya marked this conversation as resolved.
Resolved
}) =>
{
vec![(OsStr::new("FORCE_COLOR"), OsStr::new("1"))]
}
Self::Uncached { .. } => Vec::new(),
}
}
Expand Down Expand Up @@ -498,7 +509,7 @@ async fn run(
fspy_enabled,
spawn_stdio,
fast_fail_token.clone(),
mode.injected_envs(),
mode.injected_envs(&spawn_execution.spawn_command),
)
.await
.map_err(|err| Report::failed(ExecutionError::Spawn(err)))?;
Expand Down
1 change: 1 addition & 0 deletions crates/vt/src/session/reporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ pub mod test_fixtures {
kind: ExecutionItemKind::Leaf(LeafExecutionKind::Spawn(SpawnExecution {
cache_metadata: None,
spawn_command: SpawnCommand {
shell_fallback: false,
program_path: test_path(),
args: Arc::from([]),
spawn_envs: Arc::new(BTreeMap::new()),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"name": "color-env-handling",
"private": true
"private": true,
"scripts": {
"uncached-color": "vtt print-color green coverage-row",
"uncached-force": "vtt print-env FORCE_COLOR",
"explicit-no-color": "FORCE_COLOR=0 vtt print-env FORCE_COLOR",
"shell-force": "vtt print-env FORCE_COLOR > shell-force.txt"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,35 @@ argv = ["vt", "run", "print-colored-b"]
envs = [["FORCE_COLOR", "1"]]
comment = "task B — cache hit replayed; formatted snapshot proves the cached bytes were coloured, even though the cache-miss run (above) showed them as plain text"
formatted-snapshot = true

[[e2e]]
name = "uncached_piped_colors"

[[e2e.steps]]
argv = ["vt", "run", "--log", "labeled", "uncached-color"]
formatted-snapshot = true

[[e2e.steps]]
argv = ["vt", "run", "--log", "grouped", "uncached-color"]
formatted-snapshot = true

[[e2e]]
name = "uncached_explicit_color_controls"
steps = [
{ argv = ["vt", "run", "--log", "labeled", "uncached-force"], envs = [["FORCE_COLOR", "0"]] },
{ argv = ["vt", "run", "--log", "labeled", "uncached-force"], envs = [["FORCE_COLOR", "3"]] },
{ argv = ["vt", "run", "--log", "labeled", "uncached-force"], envs = [["NO_COLOR", "1"]] },
{ argv = ["vt", "run", "--log", "labeled", "uncached-force"], envs = [["NODE_DISABLE_COLORS", "1"]] },
["vt", "run", "--log", "labeled", "explicit-no-color"],
]

[[e2e]]
name = "uncached_stdio_color_detection"
steps = [
["vt", "run", "--log", "labeled", "shell-force"],
["vtt", "print-file", "shell-force.txt"],
["vt", "run", "--log", "grouped", "shell-force"],
["vtt", "print-file", "shell-force.txt"],
["vtt", "pipe-stdout", "--", "vt", "run", "--log", "labeled", "uncached-force"],
["vt", "run", "--log", "interleaved", "uncached-force"],
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# uncached_explicit_color_controls

## `FORCE_COLOR=0 vt run --log labeled uncached-force`

```
[color-env-handling#uncached-force] $ vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#uncached-force] 0
```

## `FORCE_COLOR=3 vt run --log labeled uncached-force`

```
[color-env-handling#uncached-force] $ vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#uncached-force] 3
```

## `NO_COLOR=1 vt run --log labeled uncached-force`

```
[color-env-handling#uncached-force] $ vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#uncached-force] (undefined)
```

## `NODE_DISABLE_COLORS=1 vt run --log labeled uncached-force`

```
[color-env-handling#uncached-force] $ vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#uncached-force] (undefined)
```

## `vt run --log labeled explicit-no-color`

```
[color-env-handling#explicit-no-color] $ FORCE_COLOR=0 vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#explicit-no-color] 0
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# uncached_piped_colors

## `vt run --log labeled uncached-color`

```
\x1b[90m[color-env-handling#uncached-color] \x1b[34m$ vtt print-color green coverage-row \x1b[30m\xe2\x8a\x98 \x1b[90mcache disabled
\x1b[90m[color-env-handling#uncached-color] \x1b[32mcoverage-row
```

## `vt run --log grouped uncached-color`

```
\x1b[90m[color-env-handling#uncached-color] \x1b[34m$ vtt print-color green coverage-row \x1b[30m\xe2\x8a\x98 \x1b[90mcache disabled
\x1b[90m\xe2\x94\x80\xe2\x94\x80 \x1b[90m[color-env-handling#uncached-color] \x1b[90m\xe2\x94\x80\xe2\x94\x80
\x1b[32mcoverage-row
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# uncached_stdio_color_detection

## `vt run --log labeled shell-force`

```
[color-env-handling#shell-force] $ vtt print-env FORCE_COLOR > shell-force.txt ⊘ cache disabled
```

## `vtt print-file shell-force.txt`

```
(undefined)
```

## `vt run --log grouped shell-force`

```
[color-env-handling#shell-force] $ vtt print-env FORCE_COLOR > shell-force.txt ⊘ cache disabled
```

## `vtt print-file shell-force.txt`

```
(undefined)
```

## `vtt pipe-stdout -- vt run --log labeled uncached-force`

```
--- stdout ---
[color-env-handling#uncached-force] $ vtt print-env FORCE_COLOR ⊘ cache disabled
[color-env-handling#uncached-force] (undefined)
```

## `vt run --log interleaved uncached-force`

```
$ vtt print-env FORCE_COLOR ⊘ cache disabled
(undefined)
```
5 changes: 5 additions & 0 deletions crates/vt_plan/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ pub struct SpawnCommand {
#[serde(serialize_with = "serialize_envs")]
pub spawn_envs: Arc<BTreeMap<EnvName<Arc<OsStr>>, Arc<OsStr>>>,

/// Whether the runner delegates an unparsed task script to the system shell.
/// Color controls inside the script are not represented in `spawn_envs`.
#[serde(skip)]
pub shell_fallback: bool,

/// Current working directory
pub cwd: Arc<AbsolutePath>,
}
Expand Down
4 changes: 3 additions & 1 deletion crates/vt_plan/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ async fn plan_task_as_execution_node(
context.resolved_global_cache(),
),
};
let spawn_execution = plan_spawn_execution(
let mut spawn_execution = plan_spawn_execution(
context.workspace_path(),
Some(ExecutionCacheKey::UserTask {
task_name: task_node.task_display.task_name.clone(),
Expand All @@ -408,6 +408,7 @@ async fn plan_task_as_execution_node(
Arc::clone(&*SHELL_PROGRAM_PATH),
SHELL_ARGS.iter().map(|s| Str::from(*s)).chain(std::iter::once(script)).collect(),
)?;
spawn_execution.spawn_command.shell_fallback = true;
items.push(ExecutionItem {
execution_item_display,
kind: ExecutionItemKind::Leaf(LeafExecutionKind::Spawn(spawn_execution)),
Expand Down Expand Up @@ -723,6 +724,7 @@ fn plan_spawn_execution(

Ok(SpawnExecution {
spawn_command: SpawnCommand {
shell_fallback: false,
program_path,
args: Arc::clone(&args),
cwd,
Expand Down