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
32 changes: 31 additions & 1 deletion .claude/skills/add-ecosystem-ci/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,42 @@ Present the auto-detected configuration and ask user to confirm or modify:
## Step 4: Verify
Test the clone locally:
### 4.1 Build fresh tgz packages
Always rebuild tgz packages from latest source to avoid using stale cached versions:
```bash
# Rebuild the global CLI first (includes Rust binary + NAPI binding)
pnpm bootstrap-cli

# Pack fresh tgz files into tmp/tgz/
rm -rf tmp/tgz && mkdir -p tmp/tgz
cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../..
cd packages/test && pnpm pack --pack-destination ../../tmp/tgz && cd ../..
cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../..
ls -la tmp/tgz
```

### 4.2 Clone and test locally

```bash
node ecosystem-ci/clone.ts project-name
```

### 4.3 Patch and run commands

```bash
# Run from the ecosystem-ci temp directory
cd $(node -e "const os=require('os'); console.log(os.tmpdir() + '/vite-plus-ecosystem-ci')")

# Migrate the project (uses tgz files from tmp/tgz/)
node /path/to/vite-plus/ecosystem-ci/patch-project.ts project-name

# Run the configured commands
cd project-name
vp run build
```

3. **Add OS exclusion to `.github/workflows/e2e-test.yml`** (if not running on both):

For ubuntu-only:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@ jobs:
node-version: 24
command: |
vp test run
- name: bun-vite-template
node-version: 24
command: |
vp run build
vp run test
exclude:
# frm-stack uses Docker (testcontainers) which doesn't work the same way on Windows
- os: windows-latest
Expand Down
2 changes: 1 addition & 1 deletion crates/vite_global_cli/src/shim/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const RECURSION_ENV_VAR: &str = env_vars::VITE_PLUS_TOOL_RECURSION;

/// Package manager tools that should resolve Node.js version from the project context
/// rather than using the install-time version.
const PACKAGE_MANAGER_TOOLS: &[&str] = &["pnpm", "yarn"];
const PACKAGE_MANAGER_TOOLS: &[&str] = &["pnpm", "yarn", "bun"];

fn is_package_manager_tool(tool: &str) -> bool {
PACKAGE_MANAGER_TOOLS.contains(&tool)
Expand Down
42 changes: 42 additions & 0 deletions crates/vite_install/src/commands/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{collections::HashMap, process::ExitStatus};
use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;
use vite_shared::output;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
Expand Down Expand Up @@ -195,6 +196,47 @@ impl PackageManager {
args.push("--save-exact".into());
}
}
PackageManagerType::Bun => {
bin_name = "bun".into();
args.push("add".into());

if let Some(save_dependency_type) = options.save_dependency_type {
match save_dependency_type {
SaveDependencyType::Production => {
// default, no flag needed
}
SaveDependencyType::Dev => {
args.push("--dev".into());
}
SaveDependencyType::Peer => {
args.push("--peer".into());
}
SaveDependencyType::Optional => {
args.push("--optional".into());
}
}
}
if options.save_exact {
args.push("--exact".into());
}
if let Some(filters) = options.filters {
if !filters.is_empty() {
output::warn("bun add does not support --filter");
}
}
if options.workspace_root {
output::warn("bun add does not support --workspace-root");
}
if options.workspace_only {
output::warn("bun add does not support --workspace-only");
}
if options.save_catalog_name.is_some() {
output::warn("bun add does not support --save-catalog-name");
}
if options.allow_build.is_some() {
output::warn("bun add does not support --allow-build");
}
}
}

if let Some(pass_through_args) = options.pass_through_args {
Expand Down
86 changes: 86 additions & 0 deletions crates/vite_install/src/commands/audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,28 @@ impl PackageManager {
}
}
}
PackageManagerType::Bun => {
bin_name = "bun".into();
args.push("audit".into());

if options.fix {
output::warn("bun audit does not support --fix");
return None;
}

if let Some(level) = options.level {
args.push("--audit-level".into());
args.push(level.to_string());
}

if options.production {
output::warn("--production not supported by bun audit, ignoring flag");
}

if options.json {
args.push("--json".into());
}
}
}

// Add pass-through args
Expand Down Expand Up @@ -320,6 +342,70 @@ mod tests {
assert_eq!(result.args, vec!["audit", "--level", "high"]);
}

#[test]
fn test_bun_audit_basic() {
let pm = create_mock_package_manager(PackageManagerType::Bun, "1.3.11");
let result = pm.resolve_audit_command(&AuditCommandOptions {
fix: false,
json: false,
level: None,
production: false,
pass_through_args: None,
});
assert!(result.is_some());
let result = result.unwrap();
assert_eq!(result.bin_path, "bun");
assert!(result.args.contains(&"audit".to_string()), "should contain 'audit'");
assert!(!result.args.contains(&"pm".to_string()), "should NOT use 'bun pm audit'");
}

#[test]
fn test_bun_audit_level() {
let pm = create_mock_package_manager(PackageManagerType::Bun, "1.3.11");
let result = pm.resolve_audit_command(&AuditCommandOptions {
fix: false,
json: false,
level: Some("high"),
production: false,
pass_through_args: None,
});
assert!(result.is_some());
let result = result.unwrap();
assert!(
result.args.contains(&"--audit-level".to_string()),
"should use --audit-level not --level"
);
assert!(result.args.contains(&"high".to_string()));
}

#[test]
fn test_bun_audit_fix_not_supported() {
let pm = create_mock_package_manager(PackageManagerType::Bun, "1.3.11");
let result = pm.resolve_audit_command(&AuditCommandOptions {
fix: true,
json: false,
level: None,
production: false,
pass_through_args: None,
});
assert!(result.is_none());
}

#[test]
fn test_bun_audit_json() {
let pm = create_mock_package_manager(PackageManagerType::Bun, "1.3.11");
let result = pm.resolve_audit_command(&AuditCommandOptions {
fix: false,
json: true,
level: None,
production: false,
pass_through_args: None,
});
assert!(result.is_some());
let result = result.unwrap();
assert_eq!(result.args, vec!["audit", "--json"]);
}

#[test]
fn test_audit_with_level_yarn2() {
let pm = create_mock_package_manager(PackageManagerType::Yarn, "4.0.0");
Expand Down
22 changes: 22 additions & 0 deletions crates/vite_install/src/commands/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,28 @@ impl PackageManager {
}
}
}
PackageManagerType::Bun => {
bin_name = "bun".into();

match options.subcommand {
"dir" | "path" => {
args.push("pm".into());
args.push("cache".into());
}
"clean" => {
args.push("pm".into());
args.push("cache".into());
args.push("rm".into());
}
_ => {
output::warn(&format!(
"bun pm cache subcommand '{}' not supported",
options.subcommand
));
return None;
}
}
}
}

// Add pass-through args
Expand Down
26 changes: 26 additions & 0 deletions crates/vite_install/src/commands/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,32 @@ impl PackageManager {
}
}
}
PackageManagerType::Bun => {
output::warn(
"bun uses bunfig.toml for configuration, not a config command. Falling back to npm config.",
);

// Fall back to npm config
args.push("config".into());
args.push(options.subcommand.to_string());

if let Some(key) = options.key {
args.push(key.to_string());
}

if let Some(value) = options.value {
args.push(value.to_string());
}

if options.json {
args.push("--json".into());
}

if let Some(location) = options.location {
args.push("--location".into());
args.push(location.to_string());
}
}
}

// Add pass-through args
Expand Down
6 changes: 6 additions & 0 deletions crates/vite_install/src/commands/dedupe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{collections::HashMap, process::ExitStatus};
use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;
use vite_shared::output;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
Expand Down Expand Up @@ -63,6 +64,11 @@ impl PackageManager {
args.push("--dry-run".into());
}
}
PackageManagerType::Bun => {
bin_name = "bun".into();
output::warn("bun does not support dedupe, falling back to bun install");
args.push("install".into());
}
}

// Add pass-through args
Expand Down
12 changes: 11 additions & 1 deletion crates/vite_install/src/commands/deprecate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ use std::{collections::HashMap, process::ExitStatus};
use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;
use vite_shared::output;

use crate::package_manager::{PackageManager, ResolveCommandResult, format_path_env};
use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the deprecate command.
#[derive(Debug, Default)]
Expand All @@ -31,6 +34,7 @@ impl PackageManager {

/// Resolve the deprecate command.
/// All package managers delegate to npm deprecate.
/// Bun does not support deprecate, falls back to npm.
#[must_use]
pub fn resolve_deprecate_command(
&self,
Expand All @@ -40,6 +44,12 @@ impl PackageManager {
let envs = HashMap::from([("PATH".to_string(), format_path_env(self.get_bin_prefix()))]);
let mut args: Vec<String> = Vec::new();

if self.client == PackageManagerType::Bun {
output::warn(
"bun does not support the deprecate command, falling back to npm deprecate",
);
}

args.push("deprecate".into());
args.push(options.package.to_string());
args.push(options.message.to_string());
Expand Down
6 changes: 6 additions & 0 deletions crates/vite_install/src/commands/dist_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{collections::HashMap, process::ExitStatus};
use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;
use vite_shared::output;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
Expand Down Expand Up @@ -64,6 +65,11 @@ impl PackageManager {
args.push("tag".into());
}
}
PackageManagerType::Bun => {
output::warn("bun does not support dist-tag, falling back to npm dist-tag");
bin_name = "npm".into();
args.push("dist-tag".into());
}
}

match &options.subcommand {
Expand Down
Loading
Loading