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
27 changes: 1 addition & 26 deletions crates/mergify-ci/src/detector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,32 +144,7 @@ fn read_github_event_pull_request_number() -> Result<Option<u64>, CliError> {
#[cfg(test)]
mod tests {
use super::*;

/// Clear every CI-provider env var the detector inspects, then
/// apply the test-specific overrides on top. Without this, a
/// test running on a real CI host inherits provider state and
/// the detector picks the wrong branch.
pub(crate) fn with_ci_env<F: FnOnce() -> R, R>(extra: &[(&str, Option<&str>)], f: F) -> R {
let mut vars: Vec<(String, Option<String>)> = [
"JENKINS_URL",
"GITHUB_ACTIONS",
"GITHUB_REPOSITORY",
"GITHUB_EVENT_PATH",
"CIRCLECI",
"CIRCLE_REPOSITORY_URL",
"BUILDKITE",
"BUILDKITE_REPO",
"BUILDKITE_PULL_REQUEST",
"GIT_URL",
]
.into_iter()
.map(|k| (k.to_string(), None))
.collect();
for (k, v) in extra {
vars.push((k.to_string(), v.map(ToString::to_string)));
}
temp_env::with_vars(vars, f)
}
use crate::testing::with_ci_env;

#[test]
fn ci_provider_jenkins_takes_precedence() {
Expand Down
3 changes: 3 additions & 0 deletions crates/mergify-ci/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ pub mod github_event;
pub mod queue_info;
pub mod queue_metadata;
pub mod scopes_send;

#[cfg(test)]
mod testing;
54 changes: 2 additions & 52 deletions crates/mergify-ci/src/scopes_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,58 +156,8 @@ mod tests {
use wiremock::matchers::path;

use super::*;

/// Clear every CI-provider env var the resolver inspects, then
/// apply the test-specific overrides on top. Without this, a test
/// running on a real CI host (Buildkite, Actions, …) inherits
/// provider env vars and the new provider-aware resolver picks
/// the wrong branch.
fn with_ci_env<F: FnOnce() -> R, R>(extra: &[(&str, Option<&str>)], f: F) -> R {
let mut vars: Vec<(String, Option<String>)> = [
"JENKINS_URL",
"GITHUB_ACTIONS",
"GITHUB_REPOSITORY",
"GITHUB_EVENT_PATH",
"CIRCLECI",
"CIRCLE_REPOSITORY_URL",
"BUILDKITE",
"BUILDKITE_REPO",
"BUILDKITE_PULL_REQUEST",
"GIT_URL",
]
.into_iter()
.map(|k| (k.to_string(), None))
.collect();
for (k, v) in extra {
vars.push((k.to_string(), v.map(ToString::to_string)));
}
temp_env::with_vars(vars, f)
}

async fn with_ci_env_async<F: std::future::Future<Output = R>, R>(
extra: &[(&str, Option<&str>)],
f: F,
) -> R {
let mut vars: Vec<(String, Option<String>)> = [
"JENKINS_URL",
"GITHUB_ACTIONS",
"GITHUB_REPOSITORY",
"GITHUB_EVENT_PATH",
"CIRCLECI",
"CIRCLE_REPOSITORY_URL",
"BUILDKITE",
"BUILDKITE_REPO",
"BUILDKITE_PULL_REQUEST",
"GIT_URL",
]
.into_iter()
.map(|k| (k.to_string(), None))
.collect();
for (k, v) in extra {
vars.push((k.to_string(), v.map(ToString::to_string)));
}
temp_env::async_with_vars(vars, f).await
}
use crate::testing::with_ci_env;
use crate::testing::with_ci_env_async;

#[test]
fn resolve_repository_prefers_flag_over_env() {
Expand Down
56 changes: 56 additions & 0 deletions crates/mergify-ci/src/testing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Test-only helpers shared between `detector` and `scopes_send`.
//!
//! Both modules test CI-provider-aware code paths and need to scrub
//! the host's CI env vars before running each case — otherwise a
//! test running on a real Buildkite/Actions/Circle/Jenkins host
//! inherits provider state and the detector picks the wrong branch.
//! Two flavors: a sync `with_ci_env` and an async `with_ci_env_async`
//! (used by the `#[tokio::test]` cases in `scopes_send`).

use std::future::Future;

/// Env vars the CI-provider detection chain inspects. Clear every
/// one of them before applying the test-specific overrides, so the
/// host environment can't leak into the test.
const CI_ENV_VARS: &[&str] = &[
"JENKINS_URL",
"GITHUB_ACTIONS",
"GITHUB_REPOSITORY",
"GITHUB_EVENT_PATH",
"CIRCLECI",
"CIRCLE_REPOSITORY_URL",
"BUILDKITE",
"BUILDKITE_REPO",
"BUILDKITE_PULL_REQUEST",
"GIT_URL",
];

fn merged_overrides(extra: &[(&str, Option<&str>)]) -> Vec<(String, Option<String>)> {
let mut vars: Vec<(String, Option<String>)> = CI_ENV_VARS
.iter()
.map(|k| ((*k).to_string(), None))
.collect();
for (k, v) in extra {
vars.push(((*k).to_string(), v.map(ToString::to_string)));
}
vars
}

/// Run `f` with the CI-provider env vars cleared, plus the
/// `extra` overrides applied on top.
pub(crate) fn with_ci_env<F, R>(extra: &[(&str, Option<&str>)], f: F) -> R
where
F: FnOnce() -> R,
{
temp_env::with_vars(merged_overrides(extra), f)
}

/// Async counterpart to [`with_ci_env`]. Used by `#[tokio::test]`
/// cases in `scopes_send` — the sync variant can't bridge `.await`
/// points.
pub(crate) async fn with_ci_env_async<F, R>(extra: &[(&str, Option<&str>)], f: F) -> R
where
F: Future<Output = R>,
{
temp_env::async_with_vars(merged_overrides(extra), f).await
}
Loading