1use crate::http::HttpClient;
2use anyhow::{Context, Result};
3use futures::AsyncReadExt;
4use serde::Deserialize;
5use std::sync::Arc;
6
7#[derive(Deserialize)]
8pub struct GithubRelease {
9 pub name: String,
10 pub assets: Vec<GithubReleaseAsset>,
11}
12
13#[derive(Deserialize)]
14pub struct GithubReleaseAsset {
15 pub name: String,
16 pub browser_download_url: String,
17}
18
19pub async fn latest_github_release(
20 repo_name_with_owner: &str,
21 http: Arc<dyn HttpClient>,
22) -> Result<GithubRelease, anyhow::Error> {
23 let mut response = http
24 .get(
25 &format!("https://api.github.com/repos/{repo_name_with_owner}/releases/latest"),
26 Default::default(),
27 true,
28 )
29 .await
30 .context("error fetching latest release")?;
31 let mut body = Vec::new();
32 response
33 .body_mut()
34 .read_to_end(&mut body)
35 .await
36 .context("error reading latest release")?;
37 let release: GithubRelease =
38 serde_json::from_slice(body.as_slice()).context("error deserializing latest release")?;
39 Ok(release)
40}