Skip to content
Merged
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
69 changes: 61 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
test:
needs: detect-changes
if: needs.detect-changes.outputs.code-changed == 'true'
name: Test
name: Test (${{ matrix.shard }})
strategy:
fail-fast: false
matrix:
Expand All @@ -77,18 +77,71 @@ jobs:
target: x86_64-unknown-linux-gnu
cargo_cmd: cargo-zigbuild
build_target: x86_64-unknown-linux-gnu.2.17
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: linux-gnu
scope: ''
run_env: ''
- os: namespace-profile-mac-default
target: aarch64-apple-darwin
cargo_cmd: cargo
build_target: aarch64-apple-darwin
shard: macos-arm64
scope: ''
run_env: ''
- os: namespace-profile-mac-default
target: x86_64-apple-darwin
cargo_cmd: cargo
build_target: x86_64-apple-darwin
shard: macos-x64
scope: ''
run_env: ''
# Windows e2e fixtures dominate wall-clock (60s per PTY step vs 20s on
# Unix). Coverage is partitioned by crate: the e2e shards run
# `-p vite_task_bin` and the non-e2e shard runs
# `--workspace --exclude vite_task_bin`; the union is the workspace
# by construction. The e2e_snapshots harness self-shards via
# VT_SHARD_INDEX/VT_SHARD_TOTAL across the 5 e2e jobs.
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-e2e-1
scope: '-p vite_task_bin'
run_env: 'VT_SHARD_INDEX=1 VT_SHARD_TOTAL=5'
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-e2e-2
scope: '-p vite_task_bin'
run_env: 'VT_SHARD_INDEX=2 VT_SHARD_TOTAL=5'
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-e2e-3
scope: '-p vite_task_bin'
run_env: 'VT_SHARD_INDEX=3 VT_SHARD_TOTAL=5'
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-e2e-4
scope: '-p vite_task_bin'
run_env: 'VT_SHARD_INDEX=4 VT_SHARD_TOTAL=5'
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-e2e-5
scope: '-p vite_task_bin'
run_env: 'VT_SHARD_INDEX=5 VT_SHARD_TOTAL=5'
- os: windows-latest
target: x86_64-pc-windows-msvc
cargo_cmd: cargo
build_target: x86_64-pc-windows-msvc
shard: windows-non-e2e
scope: '--workspace --exclude vite_task_bin'
run_env: ''
runs-on: ${{ matrix.os }}
steps:
- uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2
Expand Down Expand Up @@ -124,13 +177,13 @@ jobs:
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}

- name: Build tests
run: ${{ matrix.cargo_cmd }} test --no-run --target ${{ matrix.build_target }}
run: ${{ matrix.cargo_cmd }} test --no-run ${{ matrix.scope }} --target ${{ matrix.build_target }}

# Default `cargo test` runs only tests that need nothing beyond the
# Rust toolchain; this step verifies that contract before Node.js
# and pnpm enter the picture.
- name: Run tests
run: ${{ matrix.cargo_cmd }} test --target ${{ matrix.build_target }}
run: ${{ matrix.run_env }} ${{ matrix.cargo_cmd }} test ${{ matrix.scope }} --target ${{ matrix.build_target }}

# x86_64-apple-darwin runs on arm64 runner under Rosetta; install x64 Node
# so fspy's x86_64 preload dylib can be injected into spawned node procs.
Expand All @@ -139,7 +192,7 @@ jobs:
architecture: ${{ matrix.target == 'x86_64-apple-darwin' && 'x64' || '' }}

- name: Run ignored tests
run: ${{ matrix.cargo_cmd }} test --target ${{ matrix.build_target }} -- --ignored
run: ${{ matrix.run_env }} ${{ matrix.cargo_cmd }} test ${{ matrix.scope }} --target ${{ matrix.build_target }} -- --ignored

test-musl:
needs: detect-changes
Expand Down
37 changes: 37 additions & 0 deletions crates/vite_task_bin/tests/e2e_snapshots/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,28 @@ fn run_case(
Ok(())
}

/// Parses `VT_SHARD_INDEX` (1..=total) and `VT_SHARD_TOTAL` env vars for CI
/// sharding. Both unset means "run all trials". Both set selects one shard via
/// round-robin. Exactly one set is a CI misconfiguration and panics.
fn parse_shard_env() -> Option<(usize, usize)> {
let index = std::env::var("VT_SHARD_INDEX").ok();
let total = std::env::var("VT_SHARD_TOTAL").ok();
match (index, total) {
(None, None) => None,
(Some(i), Some(t)) => {
let index: usize = i.parse().expect("VT_SHARD_INDEX must be a positive integer");
let total: usize = t.parse().expect("VT_SHARD_TOTAL must be a positive integer");
assert!(total > 0, "VT_SHARD_TOTAL must be > 0");
assert!(
(1..=total).contains(&index),
"VT_SHARD_INDEX must be in 1..={total}, got {index}"
);
Some((index, total))
}
_ => panic!("VT_SHARD_INDEX and VT_SHARD_TOTAL must both be set or both unset"),
}
}

#[expect(clippy::disallowed_types, reason = "Path required for CARGO_MANIFEST_DIR path traversal")]
fn main() {
let tmp_dir = tempfile::tempdir().unwrap();
Expand Down Expand Up @@ -576,6 +598,8 @@ fn main() {
args.test_threads = Some(1);
}

let shard = parse_shard_env();

let tests: Vec<libtest_mimic::Trial> = fixture_paths
.into_iter()
.flat_map(|fixture_path| {
Expand Down Expand Up @@ -626,5 +650,18 @@ fn main() {
})
.collect();

let tests = match shard {
Some((index, total)) => {
let count = tests.len();
tests
.into_iter()
.enumerate()
.filter(|(i, _)| i * total / count + 1 == index)
.map(|(_, t)| t)
.collect()
}
None => tests,
};

libtest_mimic::run(&args, tests).exit();
}
Loading