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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ rolldown-notify = "10.2.0"
rolldown-notify-debouncer-full = "0.7.5"
rustc-hash = "2.1.1"
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
same-file = "1.0.6"
schemars = "1.0.0"
self_cell = "1.2.0"
node-semver = "2.2.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"vite-plus/latest": {
"version": "999.0.0",
"dist": {
"tarball": "unused",
"integrity": "sha512-unused"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,18 @@ skip-platforms = ["windows", { os = "linux", libc = "musl" }]
steps = [
{ argv = ["vp", "upgrade", "--check", "--tag", "alpha"], comment = "alpha tag avoids release-day flake (dev version equals npm latest right after a release, hiding the Update-available branch)", continue-on-failure = true },
]

[[case]]
name = "command_upgrade_background_notice"
vp = "global"
local-registry = true
unset-env = ["VP_CLI_TEST"]
comment = "A foreground command launches a detached update check without waiting for it, then later commands show the cached notice at most once per prompt interval."
steps = [
{ argv = ["vp", "env", "list"], comment = "The foreground command launches the detached checker and returns without waiting for registry I/O.", snapshot = false },
{ argv = ["node", "-e", "(async()=>{const fs=require('node:fs');const path=require('node:path');const file=path.join(process.env.VP_HOME,'cache','upgrade-check.json');const deadline=Date.now()+5000;for(;;){try{if(JSON.parse(fs.readFileSync(file,'utf8')).status==='available')return}catch{}if(Date.now()>=deadline)process.exit(1);await new Promise(resolve=>setTimeout(resolve,25))}})()"], snapshot = false },
{ argv = ["vpt", "grep-file", "$VP_HOME/cache/upgrade-check.json", '"status":"available"'], snapshot = false },
{ argv = ["vp", "env", "list", "--json"], comment = "Machine-readable output does not consume the pending notice.", snapshot = false },
{ argv = ["vp", "env", "off"], comment = "The next interactive command displays the cached update notice." },
{ argv = ["vp", "env", "off"], comment = "A subsequent command stays quiet after the notice timestamp is recorded." },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# command_upgrade_background_notice

A foreground command launches a detached update check without waiting for it, then later commands show the cached notice at most once per prompt interval.

## `vp env list`

The foreground command launches the detached checker and returns without waiting for registry I/O.


## `node -e '(async()=>{const fs=require('\''node:fs'\'');const path=require('\''node:path'\'');const file=path.join(process.env.VP_HOME,'\''cache'\'','\''upgrade-check.json'\'');const deadline=Date.now()+5000;for(;;){try{if(JSON.parse(fs.readFileSync(file,'\''utf8'\'')).status==='\''available'\'')return}catch{}if(Date.now()>=deadline)process.exit(1);await new Promise(resolve=>setTimeout(resolve,25))}})()'`


## `vpt grep-file $VP_HOME/cache/upgrade-check.json '"status":"available"'`


## `vp env list --json`

Machine-readable output does not consume the pending notice.


## `vp env off`

The next interactive command displays the cached update notice.

```
VITE+ - The Unified Toolchain for the Web

✓ Node.js management set to system-first.

All vp commands and shims will now prefer system Node.js, falling back to managed if not found.

Run `vp env on` to always use Vite+ managed Node.js.

A new version of vp is available. Run `vp upgrade` to update.
```

## `vp env off`

A subsequent command stays quiet after the notice timestamp is recorded.

```
VITE+ - The Unified Toolchain for the Web

Node.js management is already set to system-first.
All vp commands and shims will prefer system Node.js, falling back to managed if not found.
```
3 changes: 2 additions & 1 deletion crates/vp_global_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ serde_json = { workspace = true }
node-semver = { workspace = true }
thiserror = { workspace = true }
tar = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }
owo-colors = { workspace = true }
same-file = { workspace = true }
oxc_resolver = { workspace = true }
crossterm = { workspace = true }
indexmap = { workspace = true }
Expand All @@ -45,7 +47,6 @@ uuid = { workspace = true, features = ["v4"] }

[dev-dependencies]
serial_test = { workspace = true }
tempfile = { workspace = true }

[lints]
workspace = true
16 changes: 15 additions & 1 deletion crates/vp_global_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ pub enum Commands {
/// Custom npm registry URL
#[arg(long)]
registry: Option<String>,

/// Refresh the cached update status without producing output
#[arg(long, hide = true)]
background_check: bool,
},

/// Remove vp and all related data
Expand Down Expand Up @@ -1093,7 +1097,16 @@ pub async fn run_command_with_options(
Commands::Env(args) => commands::env::execute(cwd, args).await,

// Self-Management
Commands::Upgrade { version, tag, check, rollback, force, silent, registry } => {
Commands::Upgrade {
version,
tag,
check,
rollback,
force,
silent,
registry,
background_check,
} => {
commands::upgrade::execute(commands::upgrade::UpgradeOptions {
version,
tag,
Expand All @@ -1102,6 +1115,7 @@ pub async fn run_command_with_options(
force,
silent,
registry,
background_check,
})
.await
}
Expand Down
7 changes: 7 additions & 0 deletions crates/vp_global_cli/src/commands/upgrade/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,18 @@ pub struct UpgradeOptions {
pub silent: bool,
/// Custom npm registry URL
pub registry: Option<String>,
/// Refresh cached update status in a background helper
pub background_check: bool,
}

/// Execute the upgrade command.
#[allow(clippy::print_stdout, clippy::print_stderr)]
pub async fn execute(options: UpgradeOptions) -> Result<ExitStatus, Error> {
if options.background_check {
crate::upgrade_check::run_background_check().await;
return Ok(ExitStatus::default());
}

let install_dir = get_vp_home()?;

// Handle --rollback
Expand Down
20 changes: 7 additions & 13 deletions crates/vp_global_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,11 @@ async fn main() -> ExitCode {
// Parse CLI arguments (using custom help formatting)
let parse_result = try_parse_args_from(normalized_args);

// Spawn background upgrade check for eligible commands
let upgrade_handle = match &parse_result {
Ok(args) if upgrade_check::should_run_for_command(args) => {
Some(tokio::spawn(upgrade_check::check_for_update()))
}
_ => None,
};
let should_run_upgrade_check =
parse_result.as_ref().is_ok_and(upgrade_check::should_run_for_command);
if should_run_upgrade_check {
upgrade_check::spawn_background_check_if_needed();
}

let exit_code = match parse_result {
Err(e) => {
Expand Down Expand Up @@ -510,12 +508,8 @@ async fn main() -> ExitCode {
},
};

// Display upgrade notice if a newer version is available
if let Some(handle) = upgrade_handle
&& let Ok(Ok(Some(result))) =
tokio::time::timeout(std::time::Duration::from_millis(500), handle).await
{
upgrade_check::display_upgrade_notice(&result);
if should_run_upgrade_check {
upgrade_check::display_cached_upgrade_notice();
}

exit_code
Expand Down
Loading
Loading