Skip to content

Commit 20c168a

Browse files
authored
refactor: add EnvConfig for centralized env var management (#556)
## Summary Phase 1+2 of env var refactoring. Introduces `EnvConfig` struct that reads all known environment variables once at startup, enabling testable, parallel-safe code. ## Problem - 235 direct `std::env` calls across 7 crates, 140 are `set_var`/`remove_var` - `env::set_var` is `unsafe` since Rust 1.83 - Tests need `#[serial]` or `#[ignore]` due to global env mutation - No single source of truth for supported env vars ## Changes ### New: `vite_shared::EnvConfig` - Central struct documenting all 11 known env vars - `EnvConfig::from_env()` — read from real environment (production) - `EnvConfig::for_test()` — sensible defaults, zero env access - `EnvConfig::for_test_with_home(path)` — convenience for temp dir tests - Supports struct update syntax: `EnvConfig { is_ci: true, ..EnvConfig::for_test() }` ### Updated: `home.rs` - New `get_vite_plus_home_with_config(&EnvConfig)` — config-based, no env access - Legacy `get_vite_plus_home()` preserved for backward compat - Removed `#[ignore]` test, replaced with parallel-safe config test ### Updated: `tracing.rs` - New `init_tracing_with_config(&EnvConfig)` — config-based - Legacy `init_tracing()` preserved - Extracted shared `init_tracing_inner()` ## Test Results - `cargo test -p vite_shared`: 19 passed + 2 doc-tests ✅ - `cargo check` (full project): compiles ✅ ## Next Phases - Phase 3: Thread through `vite_install` + `vite_js_runtime` - Phase 4: Thread through `vite_global_cli` (biggest change) - Phase 5: Remove remaining `unsafe env::set_var`
1 parent c9f414d commit 20c168a

20 files changed

Lines changed: 659 additions & 564 deletions

File tree

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

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,16 @@ impl BinConfig {
112112

113113
#[cfg(test)]
114114
mod tests {
115-
use serial_test::serial;
116115
use tempfile::TempDir;
117116

118117
use super::*;
119118

120119
#[tokio::test]
121-
#[serial]
122120
async fn test_save_and_load() {
123121
let temp_dir = TempDir::new().unwrap();
124-
125-
// SAFETY: This test runs in isolation with serial_test
126-
unsafe {
127-
std::env::set_var("VITE_PLUS_HOME", temp_dir.path());
128-
}
122+
let _guard = vite_shared::EnvConfig::test_guard(
123+
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
124+
);
129125

130126
let config = BinConfig::new(
131127
"tsc".to_string(),
@@ -142,22 +138,14 @@ mod tests {
142138
assert_eq!(loaded.package, "typescript");
143139
assert_eq!(loaded.version, "5.0.0");
144140
assert_eq!(loaded.node_version, "20.18.0");
145-
146-
// Clean up env var
147-
unsafe {
148-
std::env::remove_var("VITE_PLUS_HOME");
149-
}
150141
}
151142

152143
#[tokio::test]
153-
#[serial]
154144
async fn test_find_by_package() {
155145
let temp_dir = TempDir::new().unwrap();
156-
157-
// SAFETY: This test runs in isolation with serial_test
158-
unsafe {
159-
std::env::set_var("VITE_PLUS_HOME", temp_dir.path());
160-
}
146+
let _guard = vite_shared::EnvConfig::test_guard(
147+
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
148+
);
161149

162150
// Create configs for typescript (tsc, tsserver)
163151
let tsc = BinConfig::new(
@@ -197,22 +185,14 @@ mod tests {
197185

198186
let nonexistent_bins = BinConfig::find_by_package("nonexistent").await.unwrap();
199187
assert!(nonexistent_bins.is_empty());
200-
201-
// Clean up env var
202-
unsafe {
203-
std::env::remove_var("VITE_PLUS_HOME");
204-
}
205188
}
206189

207190
#[tokio::test]
208-
#[serial]
209191
async fn test_delete() {
210192
let temp_dir = TempDir::new().unwrap();
211-
212-
// SAFETY: This test runs in isolation with serial_test
213-
unsafe {
214-
std::env::set_var("VITE_PLUS_HOME", temp_dir.path());
215-
}
193+
let _guard = vite_shared::EnvConfig::test_guard(
194+
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
195+
);
216196

217197
let config = BinConfig::new(
218198
"tsc".to_string(),
@@ -235,29 +215,16 @@ mod tests {
235215

236216
// Delete again should not error
237217
BinConfig::delete("tsc").await.unwrap();
238-
239-
// Clean up env var
240-
unsafe {
241-
std::env::remove_var("VITE_PLUS_HOME");
242-
}
243218
}
244219

245220
#[tokio::test]
246-
#[serial]
247221
async fn test_load_nonexistent() {
248222
let temp_dir = TempDir::new().unwrap();
249-
250-
// SAFETY: This test runs in isolation with serial_test
251-
unsafe {
252-
std::env::set_var("VITE_PLUS_HOME", temp_dir.path());
253-
}
223+
let _guard = vite_shared::EnvConfig::test_guard(
224+
vite_shared::EnvConfig::for_test_with_home(temp_dir.path()),
225+
);
254226

255227
let loaded = BinConfig::load("nonexistent").await.unwrap();
256228
assert!(loaded.is_none());
257-
258-
// Clean up env var
259-
unsafe {
260-
std::env::remove_var("VITE_PLUS_HOME");
261-
}
262229
}
263230
}

0 commit comments

Comments
 (0)