Skip to main content

qk_executor/
env_flags.rs

1//! What the environment says about where qk runs: in CI, and whether colour
2//! is forced, read as Nx reads them.
3
4/// Whether this runs in CI, as Nx's `isCI` decides it: `CI` set to anything
5/// but `false` (`0` included), or a variable a known CI provider sets.
6pub fn is_ci() -> bool {
7    is_ci_with(|name| std::env::var(name).ok())
8}
9
10/// [`is_ci`], reading variables through `variable`.
11pub fn is_ci_with(variable: impl Fn(&str) -> Option<String>) -> bool {
12    let ci = variable("CI");
13    if ci.as_deref() == Some("false") {
14        return false;
15    }
16    let set = |name: &str| variable(name).is_some_and(|value| !value.is_empty());
17    let is_true = |name: &str| variable(name).as_deref() == Some("true");
18    ci.is_some_and(|value| !value.is_empty())
19        || [
20            "TF_BUILD",
21            "GITHUB_ACTIONS",
22            "BUILDKITE",
23            "CIRCLECI",
24            "CIRRUS_CI",
25            "TRAVIS",
26        ]
27        .into_iter()
28        .any(is_true)
29        || [
30            "bamboo.buildKey",
31            "bamboo_buildKey",
32            "CODEBUILD_BUILD_ID",
33            "GITLAB_CI",
34            "HEROKU_TEST_RUN_ID",
35            "BUILD_ID",
36            "BUILD_NUMBER",
37            "BUILD_BUILDID",
38            "TEAMCITY_VERSION",
39            "JENKINS_URL",
40            "HUDSON_URL",
41        ]
42        .into_iter()
43        .any(set)
44}
45
46/// What `FORCE_COLOR` asks of qk's own output: colour when it is set, none
47/// when it is `0` or `false`, and nothing when it is unset. Tasks receive
48/// the variable as it is.
49pub fn force_colour() -> Option<bool> {
50    let value = std::env::var_os("FORCE_COLOR")?;
51    Some(value != "0" && value != "false")
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    fn ci(variables: &[(&str, &str)]) -> bool {
59        is_ci_with(|name| {
60            variables
61                .iter()
62                .find(|(key, _)| *key == name)
63                .map(|(_, value)| (*value).to_owned())
64        })
65    }
66
67    #[test]
68    fn reads_ci_as_nx_does() {
69        assert!(ci(&[("CI", "0")]));
70        assert!(ci(&[("CI", "1")]));
71        assert!(!ci(&[("CI", "false")]));
72        assert!(!ci(&[("CI", "false"), ("GITHUB_ACTIONS", "true")]));
73        assert!(!ci(&[]));
74        assert!(!ci(&[("CI", "")]));
75        assert!(ci(&[("GITHUB_ACTIONS", "true")]));
76        assert!(!ci(&[("GITHUB_ACTIONS", "1")]));
77        assert!(ci(&[("GITLAB_CI", "1")]));
78        assert!(ci(&[("JENKINS_URL", "http://ci")]));
79    }
80}