Create preview channel

Max Brunsfeld created

Change summary

.github/workflows/ci.yml                   | 18 ++++++++++++++++--
.github/workflows/publish_collab_image.yml | 10 +++++-----
crates/auto_update/src/auto_update.rs      | 15 +++++++--------
crates/client/src/client.rs                |  8 ++++++++
crates/collab/k8s/environments/preview.sh  |  3 +++
crates/zed/build.rs                        | 11 +++++++----
crates/zed/src/main.rs                     |  2 +-
script/get-crate-version                   | 17 +++++++++++++++++
script/validate-version                    | 17 -----------------
9 files changed, 64 insertions(+), 37 deletions(-)

Detailed changes

.github/workflows/ci.yml 🔗

@@ -79,9 +79,22 @@ jobs:
           clean: false
           submodules: 'recursive'
 
-      - name: Validate version
+      - name: Check that tag version matches package version
         if: ${{ startsWith(github.ref, 'refs/tags/v') }}
-        run: script/validate-version
+        run: |
+          set -eu
+          crate_version=$(script/get-crate-version zed)
+          tag_version=$(echo $GITHUB_REF_NAME | sed -e 's/^v//' -e 's/-pre$//')
+          if [[ $tag_version != $crate_version ]]; then
+            echo "zed crate version $crate_version does not match git tag version $tag_version"
+            exit 1
+          fi
+          echo "Publishing zed version: $crate_version"
+
+      - name: Enable the preview channel
+        if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') }}
+        run: |
+          echo "ZED_PREVIEW_CHANNEL=1 >> $GITHUB_ENV
 
       - name: Create app bundle
         run: script/bundle
@@ -98,6 +111,7 @@ jobs:
         if: ${{ startsWith(github.ref, 'refs/tags/v') }}
         with:
           draft: true
+          prerelease: ${{ endsWith(github.ref, '-pre') }}
           files: target/release/Zed.dmg
           overwrite: true
           body: ""

.github/workflows/publish_collab_image.yml 🔗

@@ -31,14 +31,14 @@ jobs:
       - name: Check that tag version matches package version
         run: |
           set -eu
-          package_version=$(cargo metadata --no-deps --format-version=1 | jq --raw-output '.packages[] | select(.name == "collab") | .version')
+          crate_version=$(script/get-crate-version collab)
           tag_version=$(echo $GITHUB_REF_NAME | sed -e 's/collab-v//')
-          if [[ $tag_version != $package_version ]]; then
-            echo "collab package version $package_version does not match git tag version $tag_version"
+          if [[ $tag_version != $crate_version ]]; then
+            echo "collab crate version $crate_version does not match git tag version $tag_version"
             exit 1
           fi
-          echo "Publishing image version: $package_version"
-          echo "COLLAB_VERSION=$package_version" >> $GITHUB_ENV
+          echo "Publishing collab version: $crate_version"
+          echo "COLLAB_VERSION=$crate_version" >> $GITHUB_ENV
 
       - name: Build docker image
         run: docker build . --tag registry.digitalocean.com/zed/collab:v${COLLAB_VERSION}

crates/auto_update/src/auto_update.rs 🔗

@@ -1,7 +1,7 @@
 mod update_notification;
 
 use anyhow::{anyhow, Context, Result};
-use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN};
+use client::{http::HttpClient, PREVIEW_CHANNEL, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
 use gpui::{
     actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
     MutableAppContext, Task, WeakViewHandle,
@@ -54,13 +54,9 @@ impl Entity for AutoUpdater {
     type Event = ();
 }
 
-pub fn init(
-    db: project::Db,
-    http_client: Arc<dyn HttpClient>,
-    server_url: String,
-    cx: &mut MutableAppContext,
-) {
+pub fn init(db: project::Db, http_client: Arc<dyn HttpClient>, cx: &mut MutableAppContext) {
     if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) {
+        let server_url = ZED_SERVER_URL.to_string();
         let auto_updater = cx.add_model(|cx| {
             let updater = AutoUpdater::new(version, db.clone(), http_client, server_url.clone());
             updater.start_polling(cx).detach();
@@ -177,9 +173,12 @@ impl AutoUpdater {
                 this.current_version,
             )
         });
+
+        let preview_param = if *PREVIEW_CHANNEL { "&preview=1" } else { "" };
+
         let mut response = client
             .get(
-                &format!("{server_url}/api/releases/latest?token={ZED_SECRET_CLIENT_TOKEN}&asset=Zed.dmg"),
+                &format!("{server_url}/api/releases/latest?token={ZED_SECRET_CLIENT_TOKEN}&asset=Zed.dmg{preview_param}"),
                 Default::default(),
                 true,
             )

crates/client/src/client.rs 🔗

@@ -50,6 +50,9 @@ pub use rpc::*;
 pub use user::*;
 
 lazy_static! {
+    pub static ref PREVIEW_CHANNEL: bool = std::env::var("ZED_PREVIEW_CHANNEL")
+        .map_or(false, |var| !var.is_empty())
+        || option_env!("ZED_PREVIEW_CHANNEL").map_or(false, |var| !var.is_empty());
     pub static ref ZED_SERVER_URL: String =
         std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string());
     pub static ref IMPERSONATE_LOGIN: Option<String> = std::env::var("ZED_IMPERSONATE")
@@ -988,6 +991,11 @@ impl Client {
             match rpc_url.scheme() {
                 "https" => {
                     rpc_url.set_scheme("wss").unwrap();
+                    rpc_url.set_query(if *PREVIEW_CHANNEL {
+                        Some("preview=1")
+                    } else {
+                        None
+                    });
                     let request = request.uri(rpc_url.as_str()).body(())?;
                     let (stream, _) =
                         async_tungstenite::async_tls::client_async_tls(request, stream).await?;

crates/zed/build.rs 🔗

@@ -3,11 +3,14 @@ use std::process::Command;
 fn main() {
     println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15.7");
 
-    if let Ok(api_key) = std::env::var("ZED_MIXPANEL_TOKEN") {
-        println!("cargo:rustc-env=ZED_MIXPANEL_TOKEN={api_key}");
+    if let Ok(value) = std::env::var("ZED_MIXPANEL_TOKEN") {
+        println!("cargo:rustc-env=ZED_MIXPANEL_TOKEN={value}");
     }
-    if let Ok(api_key) = std::env::var("ZED_AMPLITUDE_API_KEY") {
-        println!("cargo:rustc-env=ZED_AMPLITUDE_API_KEY={api_key}");
+    if let Ok(value) = std::env::var("ZED_AMPLITUDE_API_KEY") {
+        println!("cargo:rustc-env=ZED_AMPLITUDE_API_KEY={value}");
+    }
+    if let Ok(value) = std::env::var("ZED_PREVIEW_CHANNEL") {
+        println!("cargo:rustc-env=ZED_PREVIEW_CHANNEL={value}");
     }
 
     if std::env::var("ZED_BUNDLE").ok().as_deref() == Some("true") {

crates/zed/src/main.rs 🔗

@@ -158,7 +158,7 @@ fn main() {
             initialize_workspace,
             default_item_factory,
         });
-        auto_update::init(db, http, client::ZED_SERVER_URL.clone(), cx);
+        auto_update::init(db, http, cx);
         workspace::init(app_state.clone(), cx);
         journal::init(app_state.clone(), cx);
         theme_selector::init(app_state.clone(), cx);

script/get-crate-version 🔗

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -eu
+
+if [[ $# < 1 ]]; then
+  echo "Usage: $0 <crate_name>" >&2
+  exit 1
+fi
+
+CRATE_NAME=$1
+
+cargo metadata \
+    --no-deps \
+    --format-version=1 \
+    | jq \
+        --raw-output \
+        ".packages[] | select(.name == \"${CRATE_NAME}\") | .version"

script/validate-version 🔗

@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -e
-
-mkdir -p vendor/bin
-if [[ ! -f vendor/bin/jq ]]; then
-    curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-osx-amd64 > vendor/bin/jq
-    chmod +x vendor/bin/jq
-fi
-
-package_version="v$(cargo metadata --format-version=1 | vendor/bin/jq --raw-output '.packages[] | select(.name == "zed") | .version')"
-git_tag=$(git tag --points-at HEAD)
-
-if [[ $package_version != $git_tag ]]; then
-    echo "Version $package_version of zed package does not match git tag $git_tag"
-    exit 1
-fi