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
4 changes: 2 additions & 2 deletions crates/local-deployment/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ impl LocalContainerService {
}

async fn cleanup_expired_workspaces(&self) -> Result<(), DeploymentError> {
if std::env::var("DISABLE_WORKTREE_CLEANUP").is_ok() {
if utils::env::disable_flag_set("DISABLE_WORKTREE_CLEANUP") {
tracing::info!(
"Expired workspace cleanup is disabled via DISABLE_WORKTREE_CLEANUP environment variable"
);
Expand Down Expand Up @@ -348,7 +348,7 @@ impl LocalContainerService {
const IDLE_REAP_HOURS: i64 = 48;
const ACTIVITY_GRACE_SECS: i64 = 60;

if std::env::var("DISABLE_CLI_SESSION_REAP").is_ok() {
if utils::env::disable_flag_set("DISABLE_CLI_SESSION_REAP") {
return;
}
let sessions = match crate::pty::list_cli_tmux_sessions().await {
Expand Down
2 changes: 1 addition & 1 deletion crates/local-deployment/src/loop_supervisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ pub struct LoopSupervisor;
impl LoopSupervisor {
pub fn spawn(db: DBService) {
tokio::spawn(async move {
if std::env::var(DISABLE_ENV).is_ok() {
if utils::env::disable_flag_set(DISABLE_ENV) {
tracing::info!("{DISABLE_ENV} set; loop automation supervisor disabled");
return;
}
Expand Down
56 changes: 56 additions & 0 deletions crates/utils/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,40 @@ pub(crate) fn normalize_path_override(name: &str, value: Option<OsString>) -> Op
}
}

/// Check a `DISABLE_*` style opt-out flag.
///
/// Any value — including `0`, `false` and the empty string — disables the gated
/// behaviour. That is deliberately unchanged from the original
/// `std::env::var(..).is_ok()` gate: several of these flags guard destructive
/// cleanup, so tightening them such that `DISABLE_X=0` means "enabled" would
/// silently switch worktree deletion back on for anyone relying on the previous
/// behaviour. The surprising case is reported instead of reinterpreted.
pub fn disable_flag_set(name: &str) -> bool {
evaluate_disable_flag(name, std::env::var(name).ok())
}

/// Evaluate an opt-out flag without reading the environment, so the warning
/// behaviour is testable.
pub(crate) fn evaluate_disable_flag(name: &str, value: Option<String>) -> bool {
let Some(value) = value else {
return false;
};

if matches!(
value.trim().to_ascii_lowercase().as_str(),
"" | "0" | "false" | "no" | "off"
) {
tracing::warn!(
variable = name,
value = %value,
"Opt-out flag is set to a falsy-looking value but still DISABLES the \
gated behaviour; unset the variable entirely to re-enable it"
);
}

true
}

fn select_env_var_with_legacy<F>(lookup: F, new_name: &str, legacy_name: &str) -> Option<String>
where
F: Fn(&str) -> Option<String>,
Expand All @@ -86,6 +120,28 @@ mod tests {
)
}

#[test]
fn disable_flag_is_unset_when_variable_is_absent() {
assert!(!evaluate_disable_flag("DISABLE_X", None));
}

#[test]
fn disable_flag_is_set_for_a_truthy_value() {
assert!(evaluate_disable_flag("DISABLE_X", Some("1".to_string())));
}

/// The whole point of the helper: falsy-looking values still disable, so a
/// bug fix can never silently re-enable destructive cleanup.
#[test]
fn falsy_looking_values_still_disable() {
for value in ["0", "false", "no", "off", "", " FALSE "] {
assert!(
evaluate_disable_flag("DISABLE_X", Some(value.to_string())),
"{value:?} should still disable"
);
}
}

#[test]
fn returns_legacy_value_when_only_legacy_is_set() {
assert_eq!(
Expand Down
2 changes: 1 addition & 1 deletion crates/workspace-manager/src/workspace_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl WorkspaceManager {
}

pub async fn cleanup_orphan_workspaces(&self) {
if std::env::var("DISABLE_WORKTREE_CLEANUP").is_ok() {
if utils::env::disable_flag_set("DISABLE_WORKTREE_CLEANUP") {
info!(
"Orphan workspace cleanup is disabled via DISABLE_WORKTREE_CLEANUP environment variable"
);
Expand Down
Loading