Parse version from GitHub tag name instead of release name (#7423)

Jason Lee and Marshall Bowers created

If we not change this, some release will parse error.

https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28

```json
{
  "name": {
    "type": [
      "string",
      "null"
    ]
  }
}
```

<img width="1188" alt="image"
src="https://github.com/zed-industries/zed/assets/5518/bd53dbc4-ae2c-4f19-afd7-58e70b4f87d8">

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

crates/copilot/src/copilot.rs          |  2 +-
crates/util/src/github.rs              |  7 ++++---
crates/zed/src/languages/c.rs          |  4 ++--
crates/zed/src/languages/csharp.rs     |  2 +-
crates/zed/src/languages/deno.rs       |  2 +-
crates/zed/src/languages/elixir.rs     | 11 +++--------
crates/zed/src/languages/gleam.rs      |  4 ++--
crates/zed/src/languages/go.rs         |  6 +++---
crates/zed/src/languages/lua.rs        |  4 ++--
crates/zed/src/languages/rust.rs       |  2 +-
crates/zed/src/languages/toml.rs       |  2 +-
crates/zed/src/languages/typescript.rs |  2 +-
crates/zed/src/languages/zig.rs        |  2 +-
13 files changed, 23 insertions(+), 27 deletions(-)

Detailed changes

crates/copilot/src/copilot.rs 🔗

@@ -979,7 +979,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
         let release =
             latest_github_release("zed-industries/copilot", true, false, http.clone()).await?;
 
-        let version_dir = &*paths::COPILOT_DIR.join(format!("copilot-{}", release.name));
+        let version_dir = &*paths::COPILOT_DIR.join(format!("copilot-{}", release.tag_name));
 
         fs::create_dir_all(version_dir).await?;
         let server_path = version_dir.join(SERVER_PATH);

crates/util/src/github.rs 🔗

@@ -11,7 +11,7 @@ pub struct GitHubLspBinaryVersion {
 
 #[derive(Deserialize, Debug)]
 pub struct GithubRelease {
-    pub name: String,
+    pub tag_name: String,
     #[serde(rename = "prerelease")]
     pub pre_release: bool,
     pub assets: Vec<GithubReleaseAsset>,
@@ -58,9 +58,10 @@ pub async fn latest_github_release(
     let releases = match serde_json::from_slice::<Vec<GithubRelease>>(body.as_slice()) {
         Ok(releases) => releases,
 
-        Err(_) => {
+        Err(err) => {
+            log::error!("Error deserializing: {:?}", err);
             log::error!(
-                "Error deserializing GitHub API response text: {:?}",
+                "GitHub API response text: {:?}",
                 String::from_utf8_lossy(body.as_slice())
             );
             return Err(anyhow!("error deserializing latest release"));

crates/zed/src/languages/c.rs 🔗

@@ -30,14 +30,14 @@ impl super::LspAdapter for CLspAdapter {
     ) -> Result<Box<dyn 'static + Send + Any>> {
         let release =
             latest_github_release("clangd/clangd", true, false, delegate.http_client()).await?;
-        let asset_name = format!("clangd-mac-{}.zip", release.name);
+        let asset_name = format!("clangd-mac-{}.zip", release.tag_name);
         let asset = release
             .assets
             .iter()
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         let version = GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         };
         Ok(Box::new(version) as Box<_>)

crates/zed/src/languages/csharp.rs 🔗

@@ -52,7 +52,7 @@ impl super::LspAdapter for OmniSharpAdapter {
                     .find(|asset| asset.name == asset_name)
                     .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
                 let version = GitHubLspBinaryVersion {
-                    name: release.name,
+                    name: release.tag_name,
                     url: asset.browser_download_url.clone(),
                 };
 

crates/zed/src/languages/deno.rs 🔗

@@ -79,7 +79,7 @@ impl LspAdapter for DenoLspAdapter {
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         let version = GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         };
         Ok(Box::new(version) as Box<_>)

crates/zed/src/languages/elixir.rs 🔗

@@ -112,13 +112,8 @@ impl LspAdapter for ElixirLspAdapter {
     ) -> Result<Box<dyn 'static + Send + Any>> {
         let http = delegate.http_client();
         let release = latest_github_release("elixir-lsp/elixir-ls", true, false, http).await?;
-        let version_name = release
-            .name
-            .strip_prefix("Release ")
-            .context("Elixir-ls release name does not start with prefix")?
-            .to_owned();
 
-        let asset_name = format!("elixir-ls-{version_name}.zip");
+        let asset_name = format!("elixir-ls-{}.zip", &release.tag_name);
         let asset = release
             .assets
             .iter()
@@ -126,7 +121,7 @@ impl LspAdapter for ElixirLspAdapter {
             .ok_or_else(|| anyhow!("no asset found matching {asset_name:?}"))?;
 
         let version = GitHubLspBinaryVersion {
-            name: version_name,
+            name: release.tag_name.clone(),
             url: asset.browser_download_url.clone(),
         };
         Ok(Box::new(version) as Box<_>)
@@ -321,7 +316,7 @@ impl LspAdapter for NextLspAdapter {
         let release =
             latest_github_release("elixir-tools/next-ls", true, false, delegate.http_client())
                 .await?;
-        let version = release.name;
+        let version = release.tag_name;
         let asset_name = format!("next_ls_{platform}");
         let asset = release
             .assets

crates/zed/src/languages/gleam.rs 🔗

@@ -39,7 +39,7 @@ impl LspAdapter for GleamLspAdapter {
 
         let asset_name = format!(
             "gleam-{version}-{arch}-apple-darwin.tar.gz",
-            version = release.name,
+            version = release.tag_name,
             arch = std::env::consts::ARCH
         );
         let asset = release
@@ -48,7 +48,7 @@ impl LspAdapter for GleamLspAdapter {
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         Ok(Box::new(GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         }))
     }

crates/zed/src/languages/go.rs 🔗

@@ -47,11 +47,11 @@ impl super::LspAdapter for GoLspAdapter {
     ) -> Result<Box<dyn 'static + Send + Any>> {
         let release =
             latest_github_release("golang/tools", false, false, delegate.http_client()).await?;
-        let version: Option<String> = release.name.strip_prefix("gopls/v").map(str::to_string);
+        let version: Option<String> = release.tag_name.strip_prefix("gopls/v").map(str::to_string);
         if version.is_none() {
             log::warn!(
-                "couldn't infer gopls version from github release name '{}'",
-                release.name
+                "couldn't infer gopls version from GitHub release tag name '{}'",
+                release.tag_name
             );
         }
         Ok(Box::new(version) as Box<_>)

crates/zed/src/languages/lua.rs 🔗

@@ -42,7 +42,7 @@ impl super::LspAdapter for LuaLspAdapter {
             delegate.http_client(),
         )
         .await?;
-        let version = &release.name;
+        let version = &release.tag_name;
         let asset_name = format!("lua-language-server-{version}-darwin-{platform}.tar.gz");
         let asset = release
             .assets
@@ -50,7 +50,7 @@ impl super::LspAdapter for LuaLspAdapter {
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         let version = GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         };
         Ok(Box::new(version) as Box<_>)

crates/zed/src/languages/rust.rs 🔗

@@ -45,7 +45,7 @@ impl LspAdapter for RustLspAdapter {
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         Ok(Box::new(GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         }))
     }

crates/zed/src/languages/toml.rs 🔗

@@ -37,7 +37,7 @@ impl LspAdapter for TaploLspAdapter {
             .context(format!("no asset found matching {asset_name:?}"))?;
 
         Ok(Box::new(GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         }))
     }

crates/zed/src/languages/typescript.rs 🔗

@@ -254,7 +254,7 @@ impl LspAdapter for EsLintLspAdapter {
         )
         .await?;
         Ok(Box::new(GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: release.tarball_url,
         }))
     }

crates/zed/src/languages/zig.rs 🔗

@@ -37,7 +37,7 @@ impl LspAdapter for ZlsAdapter {
             .find(|asset| asset.name == asset_name)
             .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
         let version = GitHubLspBinaryVersion {
-            name: release.name,
+            name: release.tag_name,
             url: asset.browser_download_url.clone(),
         };