#[derive(Debug, PartialEq, Eq, serde::Deserialize)]
pub(crate) struct PrInfo {
pub(crate) number: u64,
#[serde(rename = "baseRefName")]
pub(crate) base_ref_name: String,
#[serde(rename = "baseRefOid")]
pub(crate) base_ref_oid: String,
#[serde(rename = "headRefOid")]
pub(crate) head_ref_oid: String,
}
pub(crate) fn parse_pr_view_json(json: &str) -> anyhow::Result<PrInfo> {
Ok(serde_json::from_str(json)?)
}
pub(crate) fn fetch_pr_info(arg: &str) -> anyhow::Result<PrInfo> {
let output = std::process::Command::new("gh")
.args([
"pr",
"view",
arg,
"--json",
"number,baseRefName,baseRefOid,headRefOid",
])
.output()?;
if !output.status.success() {
anyhow::bail!(
"gh pr view {arg} failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
parse_pr_view_json(&String::from_utf8(output.stdout)?)
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn should_parse_pr_view_json_into_pr_info() {
let json = r#"{"number":123,"baseRefName":"main","baseRefOid":"base789","headRefOid":"abc123def456"}"#;
let actual = parse_pr_view_json(json).expect("expected valid JSON to parse");
assert_eq!(
PrInfo {
number: 123,
base_ref_name: "main".to_string(),
base_ref_oid: "base789".to_string(),
head_ref_oid: "abc123def456".to_string(),
},
actual
);
}
#[test]
fn should_fail_to_parse_pr_view_json_when_a_required_field_is_missing() {
let json = r#"{"number":123,"baseRefName":"main"}"#;
let actual = parse_pr_view_json(json);
assert!(actual.is_err());
}
}