Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

xtask/tests/ci_check.rs

//! **The CI check reports red**, injury by injury.
//!
//! `xtask/src/ci_check.rs` asserts rules about `.github/workflows/`. This
//! asserts the checker: every deliberate defect must turn it red, and the
//! shipped workflows must be green.
//!
//! Without this, a check that never fires would be indistinguishable from
//! workflows that hold — which is the exact shape of the thing being fixed. The
//! repository had a `.github/` once before, between `b07ca38` and `e50b962`,
//! and `xtask/src/main.rs` records what happened to it: it *"never executed
//! once"*, and was deleted by a commit that said it touched only prose.

use xtask::ci_check::{check, red, Injury, Workflows};

fn root() -> std::path::PathBuf {
    // `CARGO_MANIFEST_DIR` is `<root>/xtask`.
    std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .expect("xtask has a parent")
        .to_path_buf()
}

fn workflows() -> Workflows {
    Workflows::read(&root()).expect("the repository has CI")
}

/// **There is a CI, and it runs the two things nothing else runs per push.**
///
/// This is the finding, stated as a test. The 0-known-CVE gate was a step of a
/// command a human types and a door inside one machine's deploy script; the
/// suite was the same. Both were therefore proved per deploy and per remembered
/// invocation, and a branch that went straight to a tag was asserted by
/// nothing.
#[test]
fn the_shipped_workflows_are_green() {
    let violations = check(&workflows());
    assert!(
        violations.is_empty(),
        "the CI broke its own rules:\n{}",
        violations
            .iter()
            .map(|v| format!("  {}: {}", v.where_, v.what))
            .collect::<Vec<_>>()
            .join("\n")
    );
}

/// **Every injury turns it red.** Named individually, so a failure says which
/// check stopped biting rather than that "the sweep failed".
#[test]
fn every_injury_is_caught() {
    let workflows = workflows();
    let survived = red(&workflows);
    assert!(
        survived.is_empty(),
        "these defects were not caught, so those checks do not bite: {}",
        survived
            .iter()
            .map(|injury| injury.label())
            .collect::<Vec<_>>()
            .join(", ")
    );
    assert_eq!(
        Injury::ALL.len(),
        5,
        "the injury list changed; a new rule in `check` needs an injury proving it fires, \
         and a removed one needs its injury removed with it"
    );
}

/// The injuries are not all the same injury.
///
/// A sweep where every variant happened to break the same rule would pass
/// `every_injury_is_caught` while proving one check and nothing else.
#[test]
fn each_injury_breaks_a_different_rule() {
    let workflows = workflows();
    let mut seen: Vec<String> = Vec::new();
    for injury in Injury::ALL {
        let violations = check(&workflows.injured(*injury));
        let first = violations
            .first()
            .unwrap_or_else(|| panic!("{} was not caught at all", injury.label()));
        let signature = format!(
            "{}::{}",
            first.where_,
            &first.what[..40.min(first.what.len())]
        );
        assert!(
            !seen.contains(&signature),
            "{} broke the same rule as an earlier injury ({signature}); the sweep proves \
             fewer checks than it appears to",
            injury.label()
        );
        seen.push(signature);
    }
}

/// The reader has to be reading more than one file.
///
/// Every rule above is written against the SET of workflows, and a reader that
/// silently found one of them — or none, and reported an empty set as clean —
/// would satisfy all three tests above while checking almost nothing. The
/// repository has the mirror-safety workflow as well as the CI one, so the
/// count is a real observation rather than a restatement.
#[test]
fn the_reader_sees_every_workflow_in_the_directory() {
    let workflows = workflows();
    let on_disk = std::fs::read_dir(root().join(xtask::ci_check::DIR))
        .expect("the workflow directory")
        .flatten()
        .filter(|e| {
            e.path()
                .extension()
                .and_then(|x| x.to_str())
                .is_some_and(|x| x == "yml" || x == "yaml")
        })
        .count();
    assert!(
        on_disk >= 2,
        "expected more than one workflow; found {on_disk}"
    );
    assert_eq!(
        workflows.files.len(),
        on_disk,
        "the reader found {} of {on_disk} workflows, so the rules above are being applied \
         to a subset nobody chose",
        workflows.files.len()
    );
}

/// ★ **The workflow's suite runs with the features `cargo xtask ci` runs it with**
/// (OX-WIRED4). `gunnar-cli/http` is default-off and gates `tests/http_transport.rs` and
/// `tests/shallow_delta_blob.rs`: without it the workflow's suite never compiled them, so
/// they ran only where somebody typed `cargo xtask ci`.
#[test]
fn the_workflows_suite_names_the_features_xtask_ci_names() {
    let workflows = workflows();
    let all: String = workflows
        .files
        .iter()
        .map(|(_, t)| t.as_str())
        .collect::<Vec<_>>()
        .join("\n");
    assert!(
        all.contains(&format!("--features {}", xtask::ci_check::SUITE_FEATURES)),
        "the workflow's `cargo test --workspace` must carry `--features {}`",
        xtask::ci_check::SUITE_FEATURES
    );
    for gated in [
        "crates/gunnar-cli/tests/http_transport.rs",
        "crates/gunnar-cli/tests/shallow_delta_blob.rs",
    ] {
        let text = std::fs::read_to_string(root().join(gated)).unwrap();
        assert!(
            text.contains("#![cfg(feature = \"http\")]"),
            "{gated} is gated on `http`"
        );
    }
    assert!(xtask::ci_check::SUITE_FEATURES
        .split(',')
        .any(|f| f == "gunnar-cli/http"));
    let main = std::fs::read_to_string(root().join("xtask/src/main.rs")).unwrap();
    assert!(
        main.contains("xtask::ci_check::SUITE_FEATURES"),
        "`cargo xtask ci`'s test step reads the one list, so the two cannot drift"
    );
}