use crate::deploy::Outcome;
use crate::error::Error;
const ROLLED_BACK: u8 = 12;
const STRANDED: u8 = 13;
pub const fn code_for_outcome(outcome: &Outcome) -> u8 {
match outcome {
Outcome::UpToDate | Outcome::Deployed { .. } => 0,
Outcome::RolledBack { .. } => ROLLED_BACK,
}
}
pub fn code_for(err: &Error) -> u8 {
match err {
Error::RolledBack { .. } => ROLLED_BACK,
Error::Stranded { .. } => STRANDED,
Error::Config(_) | Error::NotCutOver { .. } => 4,
Error::Connect(_) | Error::Refused { .. } => 5,
_ => 1,
}
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use super::*;
#[test]
fn a_rollback_has_its_own_code_distinct_from_failure_and_success() {
let rolled_back = Error::RolledBack {
to: "old-sha".to_owned(),
source: Box::new(Error::Build { status: Some(1) }),
};
assert_eq!(code_for(&rolled_back), ROLLED_BACK);
assert_ne!(ROLLED_BACK, 0);
assert_ne!(
code_for(&rolled_back),
code_for(&Error::Build { status: Some(1) })
);
}
#[test]
fn a_rollback_that_did_not_come_up_is_not_the_rolled_back_code() {
let unverified = Error::RollbackUnverified {
sheep: "web".to_owned(),
to: "old-sha".to_owned(),
why: "it did not come up".to_owned(),
found: "the shepherd has no sheep called web".to_owned(),
};
assert_eq!(code_for(&unverified), 1);
assert_ne!(code_for(&unverified), ROLLED_BACK);
}
#[test]
fn a_stranded_cutover_is_neither_a_success_nor_an_ordinary_failure() {
let stranded = Error::Stranded {
sheep: "web".to_owned(),
sha: "abc1234".to_owned(),
ids: vec![3],
};
assert_eq!(code_for(&stranded), STRANDED);
assert_ne!(STRANDED, 0);
assert_ne!(
code_for(&stranded),
code_for(&Error::Build { status: Some(1) })
);
assert_ne!(code_for(&stranded), ROLLED_BACK);
}
#[test]
fn the_shared_causes_use_sheps_own_numbers() {
assert_eq!(code_for(&Error::Config("bad".to_owned())), 4);
assert_eq!(code_for(&Error::Protocol("odd".to_owned())), 1);
assert_eq!(
code_for(&Error::Git {
command: "git fetch".to_owned(),
status: Some(128),
stderr: String::new(),
}),
1
);
assert_eq!(code_for(&Error::Build { status: Some(3) }), 1);
assert_eq!(
code_for(&Error::Connect(shep_client::ConnectError::HandshakeClosed)),
5
);
assert_eq!(
code_for(&Error::NotCutOver {
sheep: "web".to_owned(),
tree: PathBuf::from("/srv/shep/deploy/web"),
}),
4
);
}
#[test]
fn the_ok_rollback_path_reports_the_same_code() {
let outcome = Outcome::RolledBack {
to: "old-sha".to_owned(),
why: "it did not come up".to_owned(),
};
assert_eq!(code_for_outcome(&outcome), ROLLED_BACK);
assert_eq!(code_for_outcome(&Outcome::UpToDate), 0);
assert_eq!(
code_for_outcome(&Outcome::Deployed {
sha: "new".to_owned()
}),
0
);
}
#[test]
fn a_refused_handshake_exits_on_the_no_daemon_code() {
let refused = Error::Refused {
daemon_version: Some("0.4.0".to_owned()),
message: "protocol mismatch".to_owned(),
};
assert_eq!(code_for(&refused), 5);
assert_eq!(
code_for(&refused),
code_for(&Error::Connect(shep_client::ConnectError::HandshakeClosed))
);
}
}