Skip to content

Commit d143fc6

Browse files
committed
feat(env): use trampoline exe instead of .cmd wrappers on Windows
Replace Windows .cmd shim wrappers with lightweight trampoline .exe binaries to eliminate the "Terminate batch job (Y/N)?" prompt on Ctrl+C. The trampoline binary detects its tool name from its own filename, sets VITE_PLUS_SHIM_TOOL env var, and spawns vp.exe. It installs a Ctrl+C handler that ignores the signal (the child process handles it), avoiding the batch file prompt entirely. - Add crates/vite_trampoline/ with minimal Windows trampoline binary - Update shim detection to check env var before argv[0] - Replace .cmd/.sh wrapper creation with trampoline .exe copying - Add legacy .cmd cleanup during setup --refresh - Update CI to build and distribute vp-shim.exe for Windows targets - Add RFC document with feasibility study Closes #835
1 parent 2214cd3 commit d143fc6

File tree

23 files changed

+830
-290
lines changed

23 files changed

+830
-290
lines changed

.github/actions/build-upstream/action.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ runs:
4040
packages/cli/binding/index.d.cts
4141
target/${{ inputs.target }}/release/vp
4242
target/${{ inputs.target }}/release/vp.exe
43+
target/${{ inputs.target }}/release/vp-shim.exe
4344
key: ${{ steps.cache-key.outputs.key }}
4445

4546
# Apply Vite+ branding patches to rolldown-vite source (CI checks out
@@ -111,6 +112,11 @@ runs:
111112
shell: bash
112113
run: cargo build --release --target ${{ inputs.target }} -p vite_global_cli
113114

115+
- name: Build trampoline shim binary (Windows only)
116+
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'windows')
117+
shell: bash
118+
run: cargo build --release --target ${{ inputs.target }} -p vite_trampoline
119+
114120
- name: Save NAPI binding cache
115121
if: steps.cache-restore.outputs.cache-hit != 'true'
116122
uses: actions/cache/save@94b89442628ad1d101e352b7ee38f30e1bef108e # v5
@@ -123,6 +129,7 @@ runs:
123129
packages/cli/binding/index.d.cts
124130
target/${{ inputs.target }}/release/vp
125131
target/${{ inputs.target }}/release/vp.exe
132+
target/${{ inputs.target }}/release/vp-shim.exe
126133
key: ${{ steps.cache-key.outputs.key }}
127134

128135
# Build vite-plus TypeScript after native bindings are ready

.github/workflows/e2e-test.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ jobs:
112112
cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../..
113113
# Copy vp binary for e2e-test job (findVpBinary expects it in target/)
114114
cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true
115+
cp target/${{ matrix.target }}/release/vp-shim.exe tmp/tgz/vp-shim.exe 2>/dev/null || true
115116
ls -la tmp/tgz
116117
117118
- name: Upload tgz artifacts
@@ -289,12 +290,24 @@ jobs:
289290
# Place vp binary where install-global-cli.ts expects it (target/release/)
290291
mkdir -p target/release
291292
cp tmp/tgz/vp target/release/vp 2>/dev/null || cp tmp/tgz/vp.exe target/release/vp.exe 2>/dev/null || true
293+
cp tmp/tgz/vp-shim.exe target/release/vp-shim.exe 2>/dev/null || true
292294
chmod +x target/release/vp 2>/dev/null || true
293295
node $GITHUB_WORKSPACE/packages/tools/src/install-global-cli.ts --tgz $GITHUB_WORKSPACE/tmp/tgz/vite-plus-0.0.0.tgz
294296
echo "$HOME/.vite-plus/bin" >> $GITHUB_PATH
297+
# Debug: verify vp is callable
298+
ls -la "$HOME/.vite-plus/bin/" || true
299+
300+
- name: Verify vp CLI is in PATH
301+
shell: bash
302+
run: |
303+
echo "PATH: $PATH"
304+
ls -la "$HOME/.vite-plus/bin/" || true
305+
which vp || true
306+
vp --version || true
295307
296308
- name: Migrate in ${{ matrix.project.name }}
297309
working-directory: ${{ runner.temp }}/vite-plus-ecosystem-ci/${{ matrix.project.name }}${{ matrix.project.directory && format('/{0}', matrix.project.directory) || '' }}
310+
shell: bash
298311
run: |
299312
node $GITHUB_WORKSPACE/ecosystem-ci/patch-project.ts ${{ matrix.project.name }}
300313
vp install --no-frozen-lockfile

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ jobs:
124124
path: |
125125
./target/${{ matrix.settings.target }}/release/vp
126126
./target/${{ matrix.settings.target }}/release/vp.exe
127+
./target/${{ matrix.settings.target }}/release/vp-shim.exe
127128
if-no-files-found: error
128129

129130
- name: Remove .node files before upload dist

.github/workflows/test-standalone-install.yml

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ defaults:
1919
shell: bash
2020

2121
env:
22-
VITE_PLUS_VERSION: latest
22+
VITE_PLUS_VERSION: alpha
2323

2424
jobs:
2525
test-install-sh:
@@ -131,7 +131,7 @@ jobs:
131131
run: |
132132
docker run --rm --platform linux/arm64 \
133133
-v "${{ github.workspace }}:/workspace" \
134-
-e VITE_PLUS_VERSION=latest \
134+
-e VITE_PLUS_VERSION=alpha \
135135
ubuntu:20.04 bash -c "
136136
ls -al ~/
137137
apt-get update && apt-get install -y curl ca-certificates
@@ -233,7 +233,7 @@ jobs:
233233
exit 1
234234
}
235235
236-
$expectedShims = @("node.cmd", "npm.cmd", "npx.cmd")
236+
$expectedShims = @("node.exe", "npm.exe", "npx.exe")
237237
foreach ($shim in $expectedShims) {
238238
$shimFile = Join-Path $binPath $shim
239239
if (-not (Test-Path $shimFile)) {
@@ -300,7 +300,7 @@ jobs:
300300
exit 1
301301
}
302302
303-
$expectedShims = @("node.cmd", "npm.cmd", "npx.cmd")
303+
$expectedShims = @("node.exe", "npm.exe", "npx.exe")
304304
foreach ($shim in $expectedShims) {
305305
$shimFile = Join-Path $binPath $shim
306306
if (-not (Test-Path $shimFile)) {
@@ -380,8 +380,8 @@ jobs:
380380
exit 1
381381
}
382382
383-
# Verify shim executables exist (all use .cmd wrappers on Windows)
384-
$expectedShims = @("node.cmd", "npm.cmd", "npx.cmd")
383+
# Verify shim executables exist (trampoline .exe files on Windows)
384+
$expectedShims = @("node.exe", "npm.exe", "npx.exe")
385385
foreach ($shim in $expectedShims) {
386386
$shimFile = Join-Path $binPath $shim
387387
if (-not (Test-Path $shimFile)) {
@@ -419,8 +419,8 @@ jobs:
419419
set "BIN_PATH=%USERPROFILE%\.vite-plus\bin"
420420
dir "%BIN_PATH%"
421421
422-
REM Verify shim executables exist (Windows uses .cmd wrappers)
423-
for %%s in (node.cmd npm.cmd npx.cmd vp.cmd) do (
422+
REM Verify shim executables exist (Windows uses trampoline .exe files)
423+
for %%s in (node.exe npm.exe npx.exe vp.exe) do (
424424
if not exist "%BIN_PATH%\%%s" (
425425
echo Error: Shim not found: %BIN_PATH%\%%s
426426
exit /b 1
@@ -462,22 +462,13 @@ jobs:
462462
exit 1
463463
fi
464464
465-
# Verify .cmd wrappers exist (for cmd.exe/PowerShell)
466-
for shim in node.cmd npm.cmd npx.cmd vp.cmd; do
465+
# Verify trampoline .exe files exist
466+
for shim in node.exe npm.exe npx.exe vp.exe; do
467467
if [ ! -f "$BIN_PATH/$shim" ]; then
468-
echo "Error: .cmd wrapper not found: $BIN_PATH/$shim"
468+
echo "Error: Trampoline shim not found: $BIN_PATH/$shim"
469469
exit 1
470470
fi
471-
echo "Found .cmd wrapper: $BIN_PATH/$shim"
472-
done
473-
474-
# Verify shell scripts exist (for Git Bash)
475-
for shim in node npm npx vp; do
476-
if [ ! -f "$BIN_PATH/$shim" ]; then
477-
echo "Error: Shell script not found: $BIN_PATH/$shim"
478-
exit 1
479-
fi
480-
echo "Found shell script: $BIN_PATH/$shim"
471+
echo "Found trampoline shim: $BIN_PATH/$shim"
481472
done
482473
483474
# Verify vp env doctor works

Cargo.lock

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

crates/vite_global_cli/src/commands/env/doctor.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ async fn check_bin_dir() -> bool {
239239
fn shim_filename(tool: &str) -> String {
240240
#[cfg(windows)]
241241
{
242-
// All tools use .cmd wrappers on Windows (including node)
243-
format!("{tool}.cmd")
242+
// All tools use trampoline .exe files on Windows
243+
format!("{tool}.exe")
244244
}
245245

246246
#[cfg(not(windows))]
@@ -739,10 +739,10 @@ mod tests {
739739

740740
#[cfg(windows)]
741741
{
742-
// All shims should use .cmd on Windows (matching setup.rs)
743-
assert_eq!(node, "node.cmd");
744-
assert_eq!(npm, "npm.cmd");
745-
assert_eq!(npx, "npx.cmd");
742+
// All shims should use .exe on Windows (trampoline executables)
743+
assert_eq!(node, "node.exe");
744+
assert_eq!(npm, "npm.exe");
745+
assert_eq!(npx, "npx.exe");
746746
}
747747

748748
#[cfg(not(windows))]

0 commit comments

Comments
 (0)