Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e3e697d
feat(global-cli): add monorepo release workflow with publish safety c…
ubugeeei Mar 28, 2026
3e87d73
refactor
ubugeeei Mar 28, 2026
002b1ef
test: more conventional commit perser tests
ubugeeei Mar 28, 2026
49f00eb
refactor: first publishing guidance template
ubugeeei Mar 28, 2026
980d551
more docs
ubugeeei Mar 28, 2026
f9331a6
remove tokio
ubugeeei Mar 28, 2026
dcfeb28
refactor
ubugeeei Mar 28, 2026
98a3551
refactor
ubugeeei Mar 28, 2026
b2b6e1b
refactor
ubugeeei Mar 28, 2026
5bd23c7
refactor
ubugeeei Mar 28, 2026
e3865b6
feat(release): harden vp release flow
ubugeeei Mar 28, 2026
6830726
fix(release): keep repo manifests unchanged
ubugeeei Mar 28, 2026
a3d70a1
fix(release): restore CI buildability
ubugeeei Mar 28, 2026
dd27d20
fix(release): resolve remaining compile errors
ubugeeei Mar 28, 2026
70de607
fix(release): use standard success exit statuses
ubugeeei Mar 28, 2026
b0cfbe5
fix(release): drop unused runner helper
ubugeeei Mar 28, 2026
47b123b
fix(release): handle invalid tags in tests
ubugeeei Mar 28, 2026
9e42a62
test(versioning): align invalid patch expectation
ubugeeei Mar 28, 2026
cb918a3
fix(release): keep publish workflow template parseable
ubugeeei Mar 28, 2026
c33d4cf
chore(global): drop checked-in binaries
ubugeeei Mar 28, 2026
c5265c0
fix ci
ubugeeei Mar 29, 2026
34288e5
fix ci
ubugeeei Mar 29, 2026
c646a39
fix ci
ubugeeei Mar 29, 2026
42bff2d
fix vp release tagging and verification
ubugeeei Mar 30, 2026
d389ab9
fix ci
ubugeeei Mar 30, 2026
a7f3491
fix: align rolldown workspace deps
ubugeeei Mar 31, 2026
9f1cbad
fix: stabilize windows script test and fixture format
ubugeeei Mar 31, 2026
dc0f280
test: isolate env exec runtime cache
ubugeeei Mar 31, 2026
8a99d47
docs(release): add release guide and RFC
ubugeeei Apr 3, 2026
71e5ed8
chore(release): use checkout v6 in publish template
ubugeeei Apr 3, 2026
2e940cf
chore(release): defer node version to project config
ubugeeei Apr 3, 2026
7ac9a3e
docs(readme): shorten top-level command summaries
ubugeeei Apr 3, 2026
512fb7f
docs(readme): limit README changes to vp release
ubugeeei Apr 3, 2026
427378b
docs(readme): shorten release summary
ubugeeei Apr 3, 2026
c4fa112
feat(release): confirm custom prerelease channels
ubugeeei Apr 3, 2026
036a609
fix(release): expose prerelease helpers to tests
ubugeeei Apr 4, 2026
16bbb52
docs(rfc): clarify release config source
ubugeeei Apr 9, 2026
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
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Vite+ is the unified entry point for local web development. It combines [Vite](h
- **`vp build`:** Build applications for production with Vite + Rolldown
- **`vp run`:** Execute monorepo tasks with caching and dependency-aware scheduling
- **`vp pack`:** Build libraries for npm publishing or standalone app binaries
- **`vp release`:** Publish workspace releases
- **`vp create` / `vp migrate`:** Scaffold new projects and migrate existing ones

All of this is configured from your project root and works across Vite's framework ecosystem.
Expand Down Expand Up @@ -120,6 +121,7 @@ Use `vp migrate` to migrate to Vite+. It merges tool-specific config files such

- **build** - Build for production
- **pack** - Build libraries
- **release** - Publish workspace releases
- **preview** - Preview production build

#### Manage Dependencies
Expand Down
2 changes: 2 additions & 0 deletions crates/vite_global_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ tracing = { workspace = true }
owo-colors = { workspace = true }
oxc_resolver = { workspace = true }
crossterm = { workspace = true }
glob = { workspace = true }
petgraph = { workspace = true }
vite_error = { workspace = true }
vite_install = { workspace = true }
vite_js_runtime = { workspace = true }
Expand Down
107 changes: 107 additions & 0 deletions crates/vite_global_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,74 @@ pub enum Commands {
args: Vec<String>,
},

/// Version workspace packages locally, then publish them from trusted-publishing CI with readiness checks and optional changelog generation
Release {
/// Preview the release plan without changing files or publishing
#[arg(long)]
dry_run: bool,

/// During dry-runs, omit publish simulation and show only versioning/changelog actions
#[arg(long)]
skip_publish: bool,

/// Treat this release as the first one and ignore existing release tags
#[arg(long)]
first_release: bool,

/// Generate root and per-package changelogs
#[arg(long, overrides_with = "no_changelog")]
changelog: bool,

/// Skip changelog generation
#[arg(long, overrides_with = "changelog")]
no_changelog: bool,

/// Override the computed release version. Useful when retrying a partial publish.
#[arg(long, value_name = "VERSION")]
version: Option<String>,

/// Publish a prerelease using the provided identifier (for example: alpha, beta, rc)
#[arg(long, value_name = "TAG")]
preid: Option<String>,

/// Legacy TOTP code for npm 2FA publish flows. Prefer trusted publishing or passkey/security-key auth when possible.
#[arg(long, value_name = "OTP")]
otp: Option<String>,

/// Release only matching workspace packages. When multiple values are provided,
/// their order is used as a tie-breaker between independent packages.
#[arg(long, value_name = "PATTERN", value_delimiter = ',')]
projects: Option<Vec<String>>,

/// Create git tags for released packages
#[arg(long, overrides_with = "no_git_tag")]
git_tag: bool,

/// Skip git tag creation in preview mode
#[arg(long, overrides_with = "git_tag")]
no_git_tag: bool,

/// Create a git commit for release changes
#[arg(long, overrides_with = "no_git_commit")]
git_commit: bool,

/// Skip the release commit
#[arg(long, overrides_with = "git_commit")]
no_git_commit: bool,

/// Run detected release checks before publishing. Real releases do this by default.
#[arg(long, overrides_with = "no_run_checks")]
run_checks: bool,

/// Skip release checks before publishing
#[arg(long, overrides_with = "run_checks")]
no_run_checks: bool,

/// Skip the final confirmation prompt
#[arg(long, short = 'y', alias = "force")]
yes: bool,
},

/// Run tasks
#[command(disable_help_flag = true)]
Run {
Expand Down Expand Up @@ -2032,6 +2100,45 @@ pub async fn run_command_with_options(
commands::delegate::execute(cwd, "pack", &args).await
}

Commands::Release {
dry_run,
skip_publish,
first_release,
changelog,
no_changelog,
version,
preid,
otp,
projects,
git_tag: _,
no_git_tag,
git_commit: _,
no_git_commit,
run_checks,
no_run_checks,
yes,
} => {
let run_checks = if dry_run { run_checks } else { !no_run_checks || run_checks };
commands::release::execute(
cwd,
commands::release::ReleaseOptions {
dry_run,
skip_publish,
first_release,
changelog: changelog && !no_changelog,
version,
preid,
otp,
projects,
git_tag: !no_git_tag,
git_commit: !no_git_commit,
run_checks,
yes,
},
)
.await
}

Commands::Run { args } => {
if help::maybe_print_unified_delegate_help("run", &args, render_options.show_header) {
return Ok(ExitStatus::default());
Expand Down
6 changes: 6 additions & 0 deletions crates/vite_global_cli/src/command_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ const COMMANDS: &[CommandEntry] = &[
append_help: false,
},
CommandEntry { label: "pack", command: "pack", summary: "Build library.", append_help: false },
CommandEntry {
label: "release",
command: "release",
summary: "Version and publish workspace packages with readiness checks, confirmation, and optional changelog generation.",
append_help: false,
},
CommandEntry {
label: "preview",
command: "preview",
Expand Down
36 changes: 35 additions & 1 deletion crates/vite_global_cli/src/commands/env/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,43 @@ fn exit_status(code: i32) -> ExitStatus {

#[cfg(test)]
mod tests {
use std::ffi::OsString;

use serial_test::serial;
use tempfile::TempDir;

use super::*;

struct VpHomeGuard {
original_vp_home: Option<OsString>,
_temp_dir: TempDir,
}

impl VpHomeGuard {
fn new() -> Self {
let temp_dir = TempDir::new().unwrap();
let original_vp_home = std::env::var_os(env_vars::VP_HOME);
// SAFETY: This test helper is only used from serial tests and restores the
// process-global environment before dropping.
unsafe {
std::env::set_var(env_vars::VP_HOME, temp_dir.path());
}
Self { original_vp_home, _temp_dir: temp_dir }
}
}

impl Drop for VpHomeGuard {
fn drop(&mut self) {
// SAFETY: We restore the original process-global environment captured in new().
unsafe {
match &self.original_vp_home {
Some(value) => std::env::set_var(env_vars::VP_HOME, value),
None => std::env::remove_var(env_vars::VP_HOME),
}
}
}
}

#[tokio::test]
async fn test_execute_missing_command() {
let result = execute(Some("20.18.0"), None, &[]).await;
Expand All @@ -208,10 +241,11 @@ mod tests {
#[tokio::test]
#[serial]
async fn test_execute_node_version() {
let _guard = VpHomeGuard::new();
// Run 'node --version' with a specific Node.js version
let command = vec!["node".to_string(), "--version".to_string()];
let result = execute(Some("20.18.0"), None, &command).await;
assert!(result.is_ok());
assert!(result.is_ok(), "{result:?}");
let status = result.unwrap();
assert!(status.success());
}
Expand Down
1 change: 1 addition & 0 deletions crates/vite_global_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ pub mod install;
pub mod link;
pub mod outdated;
pub mod pm;
pub mod release;
pub mod remove;
pub mod unlink;
pub mod update;
Expand Down
1 change: 1 addition & 0 deletions crates/vite_global_cli/src/commands/pm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ pub async fn execute_pm_subcommand(
tag: tag.as_deref(),
access: access.as_deref(),
otp: otp.as_deref(),
provenance: None,
no_git_checks,
publish_branch: publish_branch.as_deref(),
report_summary,
Expand Down
Loading
Loading