build_helper/ci.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum CiEnv {
/// Not a CI environment.
None,
/// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds.
GitHubActions,
}
impl CiEnv {
/// Obtains the current CI environment.
pub fn current() -> CiEnv {
if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
CiEnv::GitHubActions
} else {
CiEnv::None
}
}
pub fn is_ci() -> bool {
Self::current() != CiEnv::None
}
/// Checks if running in rust-lang/rust managed CI job.
pub fn is_rust_lang_managed_ci_job() -> bool {
Self::is_ci()
// If both are present, we can assume it's an upstream CI job
// as they are always set unconditionally.
&& std::env::var_os("CI_JOB_NAME").is_some()
&& std::env::var_os("TOOLSTATE_REPO").is_some()
}
}
pub mod gha {
use std::sync::Mutex;
static ACTIVE_GROUPS: Mutex<Vec<String>> = Mutex::new(Vec::new());
/// All github actions log messages from this call to the Drop of the return value
/// will be grouped and hidden by default in logs. Note that since github actions doesn't
/// support group nesting, any active group will be first finished when a subgroup is started,
/// and then re-started when the subgroup finishes.
#[track_caller]
pub fn group(name: impl std::fmt::Display) -> Group {
let mut groups = ACTIVE_GROUPS.lock().unwrap();
// A group is currently active. End it first to avoid nesting.
if !groups.is_empty() {
end_group();
}
let name = name.to_string();
start_group(&name);
groups.push(name);
Group(())
}
/// A guard that closes the current github actions log group on drop.
#[must_use]
pub struct Group(());
impl Drop for Group {
fn drop(&mut self) {
end_group();
let mut groups = ACTIVE_GROUPS.lock().unwrap();
// Remove the current group
groups.pop();
// If there was some previous group, restart it
if is_in_gha() {
if let Some(name) = groups.last() {
start_group(format!("{name} (continued)"));
}
}
}
}
fn start_group(name: impl std::fmt::Display) {
if is_in_gha() {
println!("::group::{name}");
} else {
println!("{name}")
}
}
fn end_group() {
if is_in_gha() {
println!("::endgroup::");
}
}
fn is_in_gha() -> bool {
std::env::var_os("GITHUB_ACTIONS").is_some()
}
}