Skip to content

Commit c7a069c

Browse files
branchseerclaude
andcommitted
test(e2e): add argv step spawn mode
Replace shell string steps with structured argv format in all e2e test fixtures. Steps now use `argv` arrays instead of shell command strings, with optional `comment` and `envs` fields: ```toml # Simple: steps = [["vt", "run", "build"]] # With metadata: steps = [{ argv = ["vt", "run", "test"], comment = "cache miss", envs = [["MY_ENV", "1"]] }] # Stdin piping via vtt helper (no shell): steps = [["vtt", "pipe-stdin", "from-stdin", "--", "vt", "run", "read-stdin"]] ``` Processes are spawned directly without a shell wrapper, avoiding shell interference with signal handling and exit codes. Programs are resolved from `CARGO_BIN_EXE_<name>` env vars. Shell redirects are replaced with `vtt write-file` and `vtt pipe-stdin` helpers. Also documents Conventional Commits format for PR titles in CLAUDE.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2295d41 commit c7a069c

File tree

54 files changed

+1001
-335
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1001
-335
lines changed

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ just doc # Documentation generation
3838

3939
If `gt` (Graphite CLI) is available in PATH, use it instead of `gh` to create pull requests.
4040

41+
PR titles must use [Conventional Commits](https://www.conventionalcommits.org) format: `type(scope): summary` (scope is optional), e.g. `feat(cache): add LRU eviction`, `fix: handle symlink loops`, `test(e2e): add ctrl-c propagation test`.
42+
4143
## Tests
4244

4345
```bash

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vite_task_bin/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ pty_terminal = { workspace = true }
3636
pty_terminal_test = { workspace = true }
3737
regex = { workspace = true }
3838
serde = { workspace = true, features = ["derive", "rc"] }
39+
shell-escape = { workspace = true }
3940
tempfile = { workspace = true }
4041
toml = { workspace = true }
42+
vec1 = { workspace = true, features = ["serde"] }
4143
vite_path = { workspace = true, features = ["absolute-redaction"] }
4244
vite_workspace = { workspace = true }
4345

crates/vite_task_bin/src/vtt/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@
88

99
mod barrier;
1010
mod check_tty;
11+
mod pipe_stdin;
1112
mod print;
1213
mod print_cwd;
1314
mod print_env;
1415
mod print_file;
1516
mod read_stdin;
1617
mod replace_file_content;
1718
mod touch_file;
19+
mod write_file;
1820

1921
fn main() {
2022
let args: Vec<String> = std::env::args().collect();
2123
if args.len() < 2 {
2224
eprintln!("Usage: vtt <subcommand> [args...]");
2325
eprintln!(
24-
"Subcommands: barrier, check-tty, print, print-cwd, print-env, print-file, read-stdin, replace-file-content, touch-file"
26+
"Subcommands: barrier, check-tty, pipe-stdin, print, print-cwd, print-env, print-file, read-stdin, replace-file-content, touch-file, write-file"
2527
);
2628
std::process::exit(1);
2729
}
@@ -41,7 +43,9 @@ fn main() {
4143
"print-file" => print_file::run(&args[2..]),
4244
"read-stdin" => read_stdin::run(),
4345
"replace-file-content" => replace_file_content::run(&args[2..]),
46+
"pipe-stdin" => pipe_stdin::run(&args[2..]),
4447
"touch-file" => touch_file::run(&args[2..]),
48+
"write-file" => write_file::run(&args[2..]),
4549
other => {
4650
eprintln!("Unknown subcommand: {other}");
4751
std::process::exit(1);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// pipe-stdin `<data>` -- `<command>` [`<args>`...]
2+
///
3+
/// Spawns `<command>` with `<data>` piped to its stdin, then exits with
4+
/// the child's exit code. If `<data>` is empty, an empty stdin is provided.
5+
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
6+
let sep = args
7+
.iter()
8+
.position(|a| a == "--")
9+
.ok_or("Usage: vtt pipe-stdin <data> -- <command> [args...]")?;
10+
let data = &args[..sep].join(" ");
11+
let cmd_args = &args[sep + 1..];
12+
if cmd_args.is_empty() {
13+
return Err("Usage: vtt pipe-stdin <data> -- <command> [args...]".into());
14+
}
15+
16+
let mut child = std::process::Command::new(&cmd_args[0])
17+
.args(&cmd_args[1..])
18+
.stdin(std::process::Stdio::piped())
19+
.envs(std::env::vars())
20+
.spawn()?;
21+
22+
if let Some(mut stdin) = child.stdin.take() {
23+
use std::io::Write;
24+
if !data.is_empty() {
25+
stdin.write_all(data.as_bytes())?;
26+
}
27+
stdin.write_all(b"\n")?;
28+
// stdin is closed when dropped, signaling EOF
29+
}
30+
31+
let status = child.wait()?;
32+
std::process::exit(status.code().unwrap_or(1));
33+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub fn run(args: &[String]) -> Result<(), Box<dyn std::error::Error>> {
2+
if args.len() < 2 {
3+
return Err("Usage: vtt write-file <filename> <content>".into());
4+
}
5+
std::fs::write(&args[0], &args[1])?;
6+
Ok(())
7+
}

crates/vite_task_bin/tests/e2e_snapshots/fixtures/associate-existing-cache/snapshots.toml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,26 @@
33
[[e2e]]
44
name = "associate existing cache"
55
steps = [
6-
"vt run script1 # cache miss",
7-
"vt run script2 # cache hit, same command as script1",
8-
"vtt replace-file-content package.json '\"script2\": \"vtt print hello\"' '\"script2\": \"vtt print world\"' # change script2",
9-
"vt run script2 # cache miss",
6+
{ argv = [
7+
"vt",
8+
"run",
9+
"script1",
10+
], comment = "cache miss" },
11+
{ argv = [
12+
"vt",
13+
"run",
14+
"script2",
15+
], comment = "cache hit, same command as script1" },
16+
{ argv = [
17+
"vtt",
18+
"replace-file-content",
19+
"package.json",
20+
"\"script2\": \"vtt print hello\"",
21+
"\"script2\": \"vtt print world\"",
22+
], comment = "change script2" },
23+
{ argv = [
24+
"vt",
25+
"run",
26+
"script2",
27+
], comment = "cache miss" },
1028
]

crates/vite_task_bin/tests/e2e_snapshots/fixtures/builtin-different-cwd/snapshots.toml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,24 @@
33
[[e2e]]
44
name = "builtin different cwd"
55
steps = [
6-
"vt run cwd1 # cache miss in folder1",
7-
"vt run cwd2 # cache miss in folder2 (different cwd)",
8-
"vt run cwd1 # cache hit in folder1",
9-
"vt run cwd2 # cache hit in folder2",
6+
{ argv = [
7+
"vt",
8+
"run",
9+
"cwd1",
10+
], comment = "cache miss in folder1" },
11+
{ argv = [
12+
"vt",
13+
"run",
14+
"cwd2",
15+
], comment = "cache miss in folder2 (different cwd)" },
16+
{ argv = [
17+
"vt",
18+
"run",
19+
"cwd1",
20+
], comment = "cache hit in folder1" },
21+
{ argv = [
22+
"vt",
23+
"run",
24+
"cwd2",
25+
], comment = "cache hit in folder2" },
1026
]

crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-disabled/snapshots.toml

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,30 @@
22

33
[[e2e]]
44
name = "task with cache disabled"
5-
steps = ["vt run no-cache-task # cache miss", "vt run no-cache-task # cache disabled, runs again"]
5+
steps = [
6+
{ argv = [
7+
"vt",
8+
"run",
9+
"no-cache-task",
10+
], comment = "cache miss" },
11+
{ argv = [
12+
"vt",
13+
"run",
14+
"no-cache-task",
15+
], comment = "cache disabled, runs again" },
16+
]
617

718
[[e2e]]
819
name = "task with cache enabled"
9-
steps = ["vt run cached-task # cache miss", "vt run cached-task # cache hit"]
20+
steps = [
21+
{ argv = [
22+
"vt",
23+
"run",
24+
"cached-task",
25+
], comment = "cache miss" },
26+
{ argv = [
27+
"vt",
28+
"run",
29+
"cached-task",
30+
], comment = "cache hit" },
31+
]

crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots.toml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,33 @@
33
[[e2e]]
44
name = "cache miss command change"
55
steps = [
6-
"vt run task # cache miss",
7-
"vtt replace-file-content vite-task.json 'vtt print foo && vtt print bar' 'vtt print baz && vtt print bar' # change first subtask",
8-
"vt run task # first: cache miss, second: cache hit",
9-
"vtt replace-file-content vite-task.json 'vtt print baz && vtt print bar' 'vtt print bar' # remove first subtask",
10-
"vt run task # cache hit",
6+
{ argv = [
7+
"vt",
8+
"run",
9+
"task",
10+
], comment = "cache miss" },
11+
{ argv = [
12+
"vtt",
13+
"replace-file-content",
14+
"vite-task.json",
15+
"vtt print foo && vtt print bar",
16+
"vtt print baz && vtt print bar",
17+
], comment = "change first subtask" },
18+
{ argv = [
19+
"vt",
20+
"run",
21+
"task",
22+
], comment = "first: cache miss, second: cache hit" },
23+
{ argv = [
24+
"vtt",
25+
"replace-file-content",
26+
"vite-task.json",
27+
"vtt print baz && vtt print bar",
28+
"vtt print bar",
29+
], comment = "remove first subtask" },
30+
{ argv = [
31+
"vt",
32+
"run",
33+
"task",
34+
], comment = "cache hit" },
1135
]

0 commit comments

Comments
 (0)