(
method: &str,
endpoint: &str,
body: Option<&serde_json::Value>,
token: Option<&str>,
)
| 4682 | } |
| 4683 | |
| 4684 | fn gh_api_json( |
| 4685 | method: &str, |
| 4686 | endpoint: &str, |
| 4687 | body: Option<&serde_json::Value>, |
| 4688 | token: Option<&str>, |
| 4689 | ) -> anyhow::Result<serde_json::Value> { |
| 4690 | let mut cmd = ProcessCommand::new("gh"); |
| 4691 | cmd.arg("api") |
| 4692 | .arg("-X") |
| 4693 | .arg(method) |
| 4694 | .arg(endpoint) |
| 4695 | .arg("-H") |
| 4696 | .arg("Accept: application/vnd.github+json"); |
| 4697 | |
| 4698 | if body.is_some() { |
| 4699 | cmd.arg("--input").arg("-"); |
| 4700 | } |
| 4701 | if let Some(token) = token { |
| 4702 | cmd.env("GH_TOKEN", token); |
| 4703 | } |
| 4704 | |
| 4705 | let mut child = cmd |
| 4706 | .stdin(if body.is_some() { |
| 4707 | Stdio::piped() |
| 4708 | } else { |
| 4709 | Stdio::null() |
| 4710 | }) |
| 4711 | .stdout(Stdio::piped()) |
| 4712 | .stderr(Stdio::piped()) |
| 4713 | .spawn() |
| 4714 | .map_err(|e| anyhow::anyhow!("Failed to run gh api: {}", e))?; |
| 4715 | |
| 4716 | if let Some(body) = body { |
| 4717 | if let Some(mut stdin) = child.stdin.take() { |
| 4718 | stdin.write_all(serde_json::to_string(body)?.as_bytes())?; |
| 4719 | } |
| 4720 | } |
| 4721 | |
| 4722 | let output = child.wait_with_output()?; |
| 4723 | if !output.status.success() { |
| 4724 | let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); |
| 4725 | anyhow::bail!("gh api {} {} failed: {}", method, endpoint, stderr); |
| 4726 | } |
| 4727 | |
| 4728 | let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); |
| 4729 | if stdout.is_empty() { |
| 4730 | return Ok(serde_json::json!({})); |
| 4731 | } |
| 4732 | let parsed = serde_json::from_str::<serde_json::Value>(&stdout) |
| 4733 | .unwrap_or_else(|_| serde_json::json!({ "raw": stdout })); |
| 4734 | Ok(parsed) |
| 4735 | } |
| 4736 | |
| 4737 | fn github_assert_write_permission( |
| 4738 | owner: &str, |
no test coverage detected