From fbe30c6f2e1e13088417837b6342482845a36058 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 19 Jul 2024 15:08:10 -0700 Subject: [PATCH] Fixes for SSH remoting infrastructure (#14844) * Fixed mis-named macOS remote server archives in actions and packaging scripts * Fixed an issue with the ask pass script on linux * Download nightly versions of remote servers in dev mode (not stable) Release Notes: - N/A --- .github/workflows/ci.yml | 4 +-- crates/auto_update/src/auto_update.rs | 48 +++++++++++++++++++-------- crates/remote/src/ssh_session.rs | 32 ++++++++++-------- crates/zed/src/zed/open_listener.rs | 2 +- script/bundle-mac | 4 +-- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6aeb9bc1f9..109e4b7719 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -251,8 +251,8 @@ jobs: draft: true prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }} files: | - target/zed-remote-server-mac-x86_64.gz - target/zed-remote-server-mac-aarch64.gz + target/zed-remote-server-macos-x86_64.gz + target/zed-remote-server-macos-aarch64.gz target/aarch64-apple-darwin/release/Zed-aarch64.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg target/release/Zed.dmg diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index 08fddff1b0..4ab57bd45d 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -401,7 +401,15 @@ impl AutoUpdater { release_channel = ReleaseChannel::Nightly; } - let release = Self::get_latest_release(&this, "zed-remote-server", os, arch, cx).await?; + let release = Self::get_latest_release( + &this, + "zed-remote-server", + os, + arch, + Some(release_channel), + cx, + ) + .await?; let servers_dir = paths::remote_servers_dir(); let channel_dir = servers_dir.join(release_channel.dev_name()); @@ -423,6 +431,7 @@ impl AutoUpdater { asset: &str, os: &str, arch: &str, + release_channel: Option, cx: &mut AsyncAppContext, ) -> Result { let client = this.read_with(cx, |this, _| this.http_client.clone())?; @@ -430,14 +439,10 @@ impl AutoUpdater { "/api/releases/latest?asset={}&os={}&arch={}", asset, os, arch )); - cx.update(|cx| { - if let Some(param) = ReleaseChannel::try_global(cx) - .and_then(|release_channel| release_channel.release_query_param()) - { - url_string += "&"; - url_string += param; - } - })?; + if let Some(param) = release_channel.and_then(|c| c.release_query_param()) { + url_string += "&"; + url_string += param; + } let mut response = client.get(&url_string, Default::default(), true).await?; @@ -448,17 +453,34 @@ impl AutoUpdater { .await .context("error reading release")?; - serde_json::from_slice(body.as_slice()).context("error deserializing release") + if !response.status().is_success() { + Err(anyhow!( + "failed to fetch release: {:?}", + String::from_utf8_lossy(&body), + ))?; + } + + serde_json::from_slice(body.as_slice()).with_context(|| { + format!( + "error deserializing release {:?}", + String::from_utf8_lossy(&body), + ) + }) } async fn update(this: Model, mut cx: AsyncAppContext) -> Result<()> { - let (client, current_version) = this.update(&mut cx, |this, cx| { + let (client, current_version, release_channel) = this.update(&mut cx, |this, cx| { this.status = AutoUpdateStatus::Checking; cx.notify(); - (this.http_client.clone(), this.current_version) + ( + this.http_client.clone(), + this.current_version, + ReleaseChannel::try_global(cx), + ) })?; - let release = Self::get_latest_release(&this, "zed", OS, ARCH, &mut cx).await?; + let release = + Self::get_latest_release(&this, "zed", OS, ARCH, release_channel, &mut cx).await?; let should_download = match *RELEASE_CHANNEL { ReleaseChannel::Nightly => cx diff --git a/crates/remote/src/ssh_session.rs b/crates/remote/src/ssh_session.rs index 5ea9618d05..42f624aa1d 100644 --- a/crates/remote/src/ssh_session.rs +++ b/crates/remote/src/ssh_session.rs @@ -426,7 +426,8 @@ impl SshClientState { delegate: Arc, cx: &AsyncAppContext, ) -> Result { - use smol::fs::unix::PermissionsExt as _; + use futures::{io::BufReader, AsyncBufReadExt as _}; + use smol::{fs::unix::PermissionsExt as _, net::unix::UnixListener}; use util::ResultExt as _; let url = format!("{user}@{host}"); @@ -434,15 +435,16 @@ impl SshClientState { .prefix("zed-ssh-session") .tempdir()?; - // Create a TCP listener to handle requests from the askpass program. - let listener = smol::net::TcpListener::bind("127.0.0.1:0") - .await - .expect("failed to find open port"); - let askpass_port = listener.local_addr().unwrap().port(); + // Create a domain socket listener to handle requests from the askpass program. + let askpass_socket = temp_dir.path().join("askpass.sock"); + let listener = + UnixListener::bind(&askpass_socket).context("failed to create askpass socket")?; + let askpass_task = cx.spawn(|mut cx| async move { while let Ok((mut stream, _)) = listener.accept().await { let mut buffer = Vec::new(); - if stream.read_to_end(&mut buffer).await.is_err() { + let mut reader = BufReader::new(&mut stream); + if reader.read_until(b'\0', &mut buffer).await.is_err() { buffer.clear(); } let password_prompt = String::from_utf8_lossy(&buffer); @@ -458,10 +460,12 @@ impl SshClientState { } }); - // Create an askpass script that communicates back to this process using TCP. + // Create an askpass script that communicates back to this process. let askpass_script = format!( - "{shebang}\n echo \"$@\" | nc 127.0.0.1 {askpass_port} 2> /dev/null", - shebang = "#!/bin/sh" + "{shebang}\n{print_args} | nc -U {askpass_socket} 2> /dev/null \n", + askpass_socket = askpass_socket.display(), + print_args = "printf '%s\\0' \"$@\"", + shebang = "#!/bin/sh", ); let askpass_script_path = temp_dir.path().join("askpass.sh"); fs::write(&askpass_script_path, askpass_script).await?; @@ -501,11 +505,11 @@ impl SshClientState { } Ok(Self { - _master_process: master_process, - port, - _temp_dir: temp_dir, - socket_path, url, + port, + socket_path, + _master_process: master_process, + _temp_dir: temp_dir, }) } diff --git a/crates/zed/src/zed/open_listener.rs b/crates/zed/src/zed/open_listener.rs index 3483e2dd6b..37ebb3b52c 100644 --- a/crates/zed/src/zed/open_listener.rs +++ b/crates/zed/src/zed/open_listener.rs @@ -177,7 +177,7 @@ impl remote::SshClientDelegate for SshClientDelegate { workspace.toggle_modal(cx, |cx| PasswordPrompt::new(prompt, tx, cx)); } }) - .unwrap(); + .ok(); rx } diff --git a/script/bundle-mac b/script/bundle-mac index d327a9b1d6..0df1d3e430 100755 --- a/script/bundle-mac +++ b/script/bundle-mac @@ -390,6 +390,6 @@ else sign_binary "target/x86_64-apple-darwin/release/remote_server" sign_binary "target/aarch64-apple-darwin/release/remote_server" - gzip --stdout --best target/x86_64-apple-darwin/release/remote_server > target/zed-remote-server-mac-x86_64.gz - gzip --stdout --best target/aarch64-apple-darwin/release/remote_server > target/zed-remote-server-mac-aarch64.gz + gzip --stdout --best target/x86_64-apple-darwin/release/remote_server > target/zed-remote-server-macos-x86_64.gz + gzip --stdout --best target/aarch64-apple-darwin/release/remote_server > target/zed-remote-server-macos-aarch64.gz fi