greentic-deploy-spec 0.1.0

Greentic deployment object-model schemas (Environment, Revision, TrafficSplit, BundleDeployment, Credentials, PackConfig, RuntimeConfig)
Documentation
use greentic_deploy_spec::{RevisionLifecycle, is_valid_transition};

#[test]
fn matrix_allows_documented_transitions() {
    use RevisionLifecycle::*;
    let allowed = [
        (Inactive, Staged),
        (Inactive, Failed),
        (Staged, Warming),
        (Staged, Failed),
        (Staged, Archived),
        (Warming, Ready),
        (Warming, Failed),
        (Warming, Archived),
        (Ready, Draining),
        (Ready, Failed),
        (Ready, Archived),
        (Draining, Inactive),
        (Failed, Staged),
        (Failed, Archived),
    ];
    for (from, to) in allowed {
        assert!(
            is_valid_transition(from, to),
            "expected {from:?} → {to:?} to be allowed",
        );
    }
}

#[test]
fn matrix_denies_all_other_transitions() {
    use RevisionLifecycle::*;
    let states = [Inactive, Staged, Warming, Ready, Draining, Failed, Archived];
    let allowed_set: std::collections::HashSet<_> = [
        (Inactive, Staged),
        (Inactive, Failed),
        (Staged, Warming),
        (Staged, Failed),
        (Staged, Archived),
        (Warming, Ready),
        (Warming, Failed),
        (Warming, Archived),
        (Ready, Draining),
        (Ready, Failed),
        (Ready, Archived),
        (Draining, Inactive),
        (Failed, Staged),
        (Failed, Archived),
    ]
    .into_iter()
    .collect();

    for &from in &states {
        for &to in &states {
            let want = allowed_set.contains(&(from, to));
            assert_eq!(
                is_valid_transition(from, to),
                want,
                "transition {from:?} → {to:?} mismatch",
            );
        }
    }
}

#[test]
fn archived_is_terminal() {
    use RevisionLifecycle::*;
    for to in [Inactive, Staged, Warming, Ready, Draining, Failed, Archived] {
        assert!(
            !is_valid_transition(Archived, to),
            "archived should not transition to {to:?}",
        );
    }
}

#[test]
fn no_self_transitions() {
    use RevisionLifecycle::*;
    for s in [Inactive, Staged, Warming, Ready, Draining, Failed, Archived] {
        assert!(
            !is_valid_transition(s, s),
            "self-transition should not be allowed for {s:?}",
        );
    }
}