feat(installer): add standalone Windows .exe installer (vp-setup.exe)#1293
feat(installer): add standalone Windows .exe installer (vp-setup.exe)#1293
Conversation
✅ Deploy Preview for viteplus-preview canceled.
|
How to use the Graphite Merge QueueAdd the label auto-merge to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
1b3a6a3 to
4dc36b5
Compare
| fn main() { | ||
| // On Windows, set DEPENDENTLOADFLAG to only search system32 for DLLs at load time. | ||
| // This prevents DLL hijacking when the installer is downloaded to a folder | ||
| // containing malicious DLLs (e.g. Downloads). Matches rustup's approach. |
There was a problem hiding this comment.
672909f to
816d7f1
Compare
|
|
||
| ### Phase 2: Direct Download URL | ||
|
|
||
| Host at `https://vite.plus/vp-setup.exe` with architecture auto-detection (default x64). |
There was a problem hiding this comment.
should use void worker to handle the architecture detect logic.
|
|
||
| ## Code Signing | ||
|
|
||
| Windows Defender SmartScreen flags unsigned executables downloaded from the internet. This is a significant UX problem for a download-and-run installer. |
There was a problem hiding this comment.
@Brooooooklyn @yyx990803 Has the digital signature certificate been approved? This feature requires it.
4fe6fd3 to
a87b42c
Compare
Manual Testing Plan:
|
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a8c95ab916
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Add a standalone `vp-setup.exe` Windows installer binary that installs the vp CLI without requiring PowerShell, complementing the existing `irm https://vite.plus/ps1 | iex` script-based installer. - Create `vite_setup` shared library crate extracting installation logic (platform detection, registry queries, integrity verification, tarball extraction, symlink/junction management) from `vite_global_cli` - Create `vite_installer` binary crate producing `vp-setup.exe` with interactive prompts, silent mode (-y), progress bars, and Windows PATH modification via direct registry API (no PowerShell dependency) - Update `vite_global_cli` to use `vite_setup` instead of inline upgrade modules, ensuring upgrade and installer share identical logic - Add CI build/upload steps for installer in release workflow, attached as GitHub Release assets - Add RFC document at rfcs/windows-installer.md
- Remove dirs_home() and dead fallback in resolve_install_dir(), use get_vp_home() directly - Resolve install dir once in run() and pass through to all functions - Extract read_current_version() into vite_setup as a public function, reuse in save_previous_version() and the installer - Merge Cli/Options structs into single Options struct in cli.rs - Extract replace_windows_exe() helper to eliminate copy-paste in setup_bin_shims() - Remove unused LPWSTR type alias from windows_path.rs - Remove excessive "Step N" comments - Fix mixed path separator in interactive menu display
- Add interactive "Customize installation" submenu (option 2) allowing users to change version, registry, Node.js manager, and PATH settings - Add env file creation via `vp env setup --env-only` when Node.js manager is skipped (ensures shell env files exist in all code paths) - Add build.rs with /DEPENDENTLOADFLAG:0x800 linker flag for DLL hijacking prevention at load time (complements runtime mitigation) - Add test-vp-setup-exe CI job to test-standalone-install.yml testing silent installation from cmd, pwsh, and bash on Windows
The junction crate was moved to vite_setup when extracting the shared installation logic. cargo-shear correctly flagged it as unused.
Replace the flat numbered list with a phased ASCII diagram grouped into Resolve, Download & Verify, Install, Activate, and Configure phases. Add a function-to-crate mapping table and document the failure recovery boundary (pre/post Activate phase). Annotate conditional steps (save_previous_version only on upgrade, modify PATH gated by --no-modify-path).
- Update status from "Draft" to "Implemented" - Fix Code Sharing table: all install functions are in vite_setup::install, not separate submodules - Fix Dependency Graph: remove junction (indirect via vite_setup), add actual deps (vite_path, owo-colors) - Fix Customization submenu to match code (numbered items, no install dir) - Replace winreg code sample with raw FFI description (matches implementation) - Replace windows_sys DLL sample with raw FFI (matches implementation) - Remove winreg from Binary Size Budget, add raw FFI note - Fix Alternatives #4: raw FFI, not winreg - Fix CI snippets: rename vite-init to vp-setup, update test workflow to match actual test-vp-setup-exe job - Mark Implementation Phases 1-3 as done, Phase 4 as future
…ccess The zero-dependency pattern made sense for vite_trampoline (copied 5-10 times as shim files) but not for a single downloadable installer where readability matters more. Switch from 225 lines of unsafe raw Win32 FFI to ~80 lines of safe Rust using the winreg crate (~50-100 KB after LTO). WM_SETTINGCHANGE broadcast still uses a single raw FFI call since winreg doesn't wrap SendMessageTimeoutW.
- Extract VP_BINARY_NAME constant to avoid duplicated cfg!(windows) binary name literals - Remove redundant exists() check in replace_windows_exe — just attempt the rename unconditionally (rename failure is already ignored) - Trim verbose WHAT-comments to concise single-line doc comments
Replace dynamic matrix.shell in shell: field with explicit shell values per step. The matrix.shell expression was not recognized by the GitHub Actions YAML parser when used in the shell: context. Use a single job that verifies installation from pwsh, cmd, and bash sequentially.
- Update interactive menu examples to show "enabled"/"disabled" instead of "auto-detect" (value is now pre-computed) - Add Node.js Manager Auto-Detection section with priority table documenting the full auto-detect logic matching install.ps1/install.sh - Restructure Installation Flow diagram: local version check before HTTP, split resolve_version into resolve_version_string + resolve_platform_package, same-version repair path skips to CONFIGURE, cleanup moved to ACTIVATE - Update Existing Installation Handling: same version now repairs instead of exiting early - Document best-effort post-activation behavior and failure recovery - Update function mapping table with split registry functions - Update Test Workflow snippet to match actual single-job structure - Update Phase 2 description (winreg, pre-computed node manager, repair)
This function follows the same pattern as refresh_shims (spawn vp with different args) and belongs in the shared library alongside it.
… builds Use setup-dev-drive with ReFS (matching ci.yml) to speed up cargo build. Windows Defender skips ReFS dev drives, which significantly reduces build times on GitHub Actions Windows runners.
- Extract VP_BINARY_NAME const to vite_setup::lib.rs, replacing 5
inline cfg!(windows) expressions across vite_setup, vite_installer,
and vite_global_cli
- Fix create_env_files to check exit code and log warning on failure,
matching refresh_shims behavior
- Fix else { if let → else if let (clippy collapsible_else_if)
When double-clicked, the console window closes immediately after installation finishes. Users never see the success/error message. Add a 'Press Enter to close...' prompt in interactive mode so users can read the output. Silent mode (-y, CI) exits immediately.
a8c95ab to
aa5dfc2
Compare
When --install-dir overrides the default location, child vp processes (refresh_shims, create_env_files, install_production_deps) would fall back to ~/.vite-plus because VP_HOME was not set in their environment. Set VP_HOME to the resolved install directory before spawning any child processes so they always use the correct location.
The same-version check now verifies that the binary (current/bin/vp.exe) actually exists, not just that the current symlink points at the target version. If the version directory is corrupted or partially deleted, the installer performs a full reinstall instead of skipping to the best-effort repair steps which cannot restore missing core files.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 998d51d9d8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Prefer vp-shim.exe (lightweight trampoline), fall back to vp.exe | ||
| let src = if tokio::fs::try_exists(&shim_src).await.unwrap_or(false) { | ||
| shim_src | ||
| } else { | ||
| install_dir.join("current").join("bin").join("vp.exe") | ||
| }; |
There was a problem hiding this comment.
Preserve VP_HOME when vp-shim.exe is unavailable
When vp-shim.exe is missing, this path falls back to copying current/bin/vp.exe directly into bin/vp.exe without creating a wrapper that exports VP_HOME. For installs done with --install-dir (especially paths not ending in .vite-plus) and older versions that don’t ship the shim, launching bin/vp.exe later can resolve the home directory incorrectly and fail to use the installed tree. install.ps1 handles this case by generating wrappers that set VP_HOME, so this fallback should do the same.
Useful? React with 👍 / 👎.
| #[allow(clippy::print_stdout)] | ||
| fn show_interactive_menu(opts: &mut cli::Options, install_dir: &str) -> bool { | ||
| loop { | ||
| let version = opts.version.as_deref().unwrap_or("latest"); |
There was a problem hiding this comment.
Show selected dist-tag in interactive version summary
The interactive summary always renders version as opts.version or latest, but installation actually uses opts.version or opts.tag (do_install resolves version_or_tag that way). So running vp-setup --tag alpha still shows Version: latest in the menu while installing alpha, which can mislead users into confirming a different version than the one that will be installed.
Useful? React with 👍 / 👎.



Add a standalone
vp-setup.exeWindows installer binary that installsthe vp CLI without requiring PowerShell, complementing the existing
irm https://vite.plus/ps1 | iexscript-based installer.vite_setupshared library crate extracting installation logic(platform detection, registry queries, integrity verification, tarball
extraction, symlink/junction management) from
vite_global_clivite_installerbinary crate producingvp-setup.exewithinteractive prompts, silent mode (-y), progress bars, and Windows PATH
modification via direct registry API (no PowerShell dependency)
vite_global_clito usevite_setupinstead of inline upgrademodules, ensuring upgrade and installer share identical logic
as GitHub Release assets