zed_extension_api: Add github_release_by_tag_name
(#12172)
This PR adds a new `github_release_by_tag_name` method to the `zed_extension_api` to allow for retrieving a GitHub release by its tag name. Release Notes: - N/A
This commit is contained in:
parent
85ff80f3c0
commit
054c36cc29
4 changed files with 82 additions and 12 deletions
|
@ -147,6 +147,24 @@ impl nodejs::Host for WasmState {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl lsp::Host for WasmState {}
|
impl lsp::Host for WasmState {}
|
||||||
|
|
||||||
|
impl From<http::github::GithubRelease> for github::GithubRelease {
|
||||||
|
fn from(value: http::github::GithubRelease) -> Self {
|
||||||
|
Self {
|
||||||
|
version: value.tag_name,
|
||||||
|
assets: value.assets.into_iter().map(Into::into).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<http::github::GithubReleaseAsset> for github::GithubReleaseAsset {
|
||||||
|
fn from(value: http::github::GithubReleaseAsset) -> Self {
|
||||||
|
Self {
|
||||||
|
name: value.name,
|
||||||
|
download_url: value.browser_download_url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl github::Host for WasmState {
|
impl github::Host for WasmState {
|
||||||
async fn latest_github_release(
|
async fn latest_github_release(
|
||||||
|
@ -162,17 +180,22 @@ impl github::Host for WasmState {
|
||||||
self.host.http_client.clone(),
|
self.host.http_client.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(github::GithubRelease {
|
Ok(release.into())
|
||||||
version: release.tag_name,
|
})
|
||||||
assets: release
|
.await
|
||||||
.assets
|
.to_wasmtime_result()
|
||||||
.into_iter()
|
}
|
||||||
.map(|asset| github::GithubReleaseAsset {
|
|
||||||
name: asset.name,
|
async fn github_release_by_tag_name(
|
||||||
download_url: asset.browser_download_url,
|
&mut self,
|
||||||
})
|
repo: String,
|
||||||
.collect(),
|
tag: String,
|
||||||
})
|
) -> wasmtime::Result<Result<github::GithubRelease, String>> {
|
||||||
|
maybe!(async {
|
||||||
|
let release =
|
||||||
|
http::github::get_release_by_tag_name(&repo, &tag, self.host.http_client.clone())
|
||||||
|
.await?;
|
||||||
|
Ok(release.into())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.to_wasmtime_result()
|
.to_wasmtime_result()
|
||||||
|
|
|
@ -16,7 +16,8 @@ pub use serde_json;
|
||||||
pub use wit::{
|
pub use wit::{
|
||||||
download_file, make_file_executable,
|
download_file, make_file_executable,
|
||||||
zed::extension::github::{
|
zed::extension::github::{
|
||||||
latest_github_release, GithubRelease, GithubReleaseAsset, GithubReleaseOptions,
|
github_release_by_tag_name, latest_github_release, GithubRelease, GithubReleaseAsset,
|
||||||
|
GithubReleaseOptions,
|
||||||
},
|
},
|
||||||
zed::extension::nodejs::{
|
zed::extension::nodejs::{
|
||||||
node_binary_path, npm_install_package, npm_package_installed_version,
|
node_binary_path, npm_install_package, npm_package_installed_version,
|
||||||
|
|
|
@ -25,4 +25,9 @@ interface github {
|
||||||
|
|
||||||
/// Returns the latest release for the given GitHub repository.
|
/// Returns the latest release for the given GitHub repository.
|
||||||
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
|
latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
|
||||||
|
|
||||||
|
/// Returns the GitHub release with the specified tag name for the given GitHub repository.
|
||||||
|
///
|
||||||
|
/// Returns an error if a release with the given tag name does not exist.
|
||||||
|
github-release-by-tag-name: func(repo: string, tag: string) -> result<github-release, string>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,47 @@ pub async fn latest_github_release(
|
||||||
.ok_or(anyhow!("Failed to find a release"))
|
.ok_or(anyhow!("Failed to find a release"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_release_by_tag_name(
|
||||||
|
repo_name_with_owner: &str,
|
||||||
|
tag: &str,
|
||||||
|
http: Arc<dyn HttpClient>,
|
||||||
|
) -> Result<GithubRelease, anyhow::Error> {
|
||||||
|
let mut response = http
|
||||||
|
.get(
|
||||||
|
&format!("https://api.github.com/repos/{repo_name_with_owner}/releases/tags/{tag}"),
|
||||||
|
Default::default(),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("error fetching latest release")?;
|
||||||
|
|
||||||
|
let mut body = Vec::new();
|
||||||
|
response
|
||||||
|
.body_mut()
|
||||||
|
.read_to_end(&mut body)
|
||||||
|
.await
|
||||||
|
.context("error reading latest release")?;
|
||||||
|
|
||||||
|
if response.status().is_client_error() {
|
||||||
|
let text = String::from_utf8_lossy(body.as_slice());
|
||||||
|
bail!(
|
||||||
|
"status error {}, response: {text:?}",
|
||||||
|
response.status().as_u16()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let release = serde_json::from_slice::<GithubRelease>(body.as_slice()).map_err(|err| {
|
||||||
|
log::error!("Error deserializing: {:?}", err);
|
||||||
|
log::error!(
|
||||||
|
"GitHub API response text: {:?}",
|
||||||
|
String::from_utf8_lossy(body.as_slice())
|
||||||
|
);
|
||||||
|
anyhow!("error deserializing GitHub release")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(release)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_tarball_url(repo_name_with_owner: &str, tag: &str) -> Result<String> {
|
pub fn build_tarball_url(repo_name_with_owner: &str, tag: &str) -> Result<String> {
|
||||||
let mut url = Url::parse(&format!(
|
let mut url = Url::parse(&format!(
|
||||||
"https://github.com/{repo_name_with_owner}/archive/refs/tags",
|
"https://github.com/{repo_name_with_owner}/archive/refs/tags",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue