Add nightly release channel for zed2 (#3355)

Release Notes:

- N/A
This commit is contained in:
Mikayla Maki 2023-11-17 22:12:18 -08:00 committed by GitHub
commit e1285b9780
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 914 additions and 97 deletions

View File

@ -0,0 +1,15 @@
name: 'Check formatting'
description: 'Checks code formatting use cargo fmt'
runs:
using: "composite"
steps:
- name: Install Rust
shell: bash -euxo pipefail {0}
run: |
rustup set profile minimal
rustup update stable
- name: cargo fmt
shell: bash -euxo pipefail {0}
run: cargo fmt --all -- --check

34
.github/actions/run_tests/action.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: "Run tests"
description: "Runs the tests"
runs:
using: "composite"
steps:
- name: Install Rust
shell: bash -euxo pipefail {0}
run: |
rustup set profile minimal
rustup update stable
rustup target add wasm32-wasi
cargo install cargo-nextest
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Limit target directory size
shell: bash -euxo pipefail {0}
run: script/clear-target-dir-if-larger-than 70
- name: Run check
env:
RUSTFLAGS: -D warnings
shell: bash -euxo pipefail {0}
run: cargo check --tests --workspace
- name: Run tests
env:
RUSTFLAGS: -D warnings
shell: bash -euxo pipefail {0}
run: cargo nextest run --workspace --no-fail-fast

View File

@ -23,19 +23,14 @@ jobs:
- self-hosted
- test
steps:
- name: Install Rust
run: |
rustup set profile minimal
rustup update stable
- name: Checkout repo
uses: actions/checkout@v3
with:
clean: false
submodules: "recursive"
- name: cargo fmt
run: cargo fmt --all -- --check
- name: Run rustfmt
uses: ./.github/actions/check_formatting
tests:
name: Run tests
@ -43,35 +38,15 @@ jobs:
- self-hosted
- test
needs: rustfmt
env:
RUSTFLAGS: -D warnings
steps:
- name: Install Rust
run: |
rustup set profile minimal
rustup update stable
rustup target add wasm32-wasi
cargo install cargo-nextest
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@v3
with:
clean: false
submodules: "recursive"
- name: Limit target directory size
run: script/clear-target-dir-if-larger-than 70
- name: Run check
run: cargo check --workspace
- name: Run tests
run: cargo nextest run --workspace --no-fail-fast
uses: ./.github/actions/run_tests
- name: Build collab
run: cargo build -p collab
@ -130,6 +105,8 @@ jobs:
expected_tag_name="v${version}";;
preview)
expected_tag_name="v${version}-pre";;
nightly)
expected_tag_name="v${version}-nightly";;
*)
echo "can't publish a release on channel ${channel}"
exit 1;;
@ -154,7 +131,9 @@ jobs:
- uses: softprops/action-gh-release@v1
name: Upload app bundle to release
if: ${{ env.RELEASE_CHANNEL }}
# TODO kb seems that zed.dev relies on GitHub releases for release version tracking.
# Find alternatives for `nightly` or just go on with more releases?
if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
with:
draft: true
prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}

98
.github/workflows/release_nightly.yml vendored Normal file
View File

@ -0,0 +1,98 @@
name: Release Nightly
on:
schedule:
# Fire every night at 1:00am
- cron: "0 1 * * *"
push:
tags:
- "nightly"
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
jobs:
rustfmt:
name: Check formatting
runs-on:
- self-hosted
- test
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
clean: false
submodules: "recursive"
- name: Run rustfmt
uses: ./.github/actions/check_formatting
tests:
name: Run tests
runs-on:
- self-hosted
- test
needs: rustfmt
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
clean: false
submodules: "recursive"
- name: Run tests
uses: ./.github/actions/run_tests
bundle:
name: Bundle app
runs-on:
- self-hosted
- bundle
needs: tests
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps:
- name: Install Rust
run: |
rustup set profile minimal
rustup update stable
rustup target add aarch64-apple-darwin
rustup target add x86_64-apple-darwin
rustup target add wasm32-wasi
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@v3
with:
clean: false
submodules: "recursive"
- name: Limit target directory size
run: script/clear-target-dir-if-larger-than 70
- name: Set release channel to nightly
run: |
set -eu
version=$(git rev-parse --short HEAD)
echo "Publishing version: ${version} on release channel nightly"
echo "nightly" > crates/zed/RELEASE_CHANNEL
- name: Generate license file
run: script/generate-licenses
- name: Create app bundle
run: script/bundle -2
- name: Upload Zed Nightly
run: script/upload-nightly

25
Cargo.lock generated
View File

@ -724,6 +724,30 @@ dependencies = [
"workspace",
]
[[package]]
name = "auto_update2"
version = "0.1.0"
dependencies = [
"anyhow",
"client2",
"db2",
"gpui2",
"isahc",
"lazy_static",
"log",
"menu2",
"project2",
"serde",
"serde_derive",
"serde_json",
"settings2",
"smol",
"tempdir",
"theme2",
"util",
"workspace2",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -11571,6 +11595,7 @@ dependencies = [
"async-recursion 0.3.2",
"async-tar",
"async-trait",
"auto_update2",
"backtrace",
"call2",
"chrono",

View File

@ -6,6 +6,7 @@ members = [
"crates/audio",
"crates/audio2",
"crates/auto_update",
"crates/auto_update2",
"crates/breadcrumbs",
"crates/call",
"crates/call2",

View File

@ -118,14 +118,18 @@ fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) {
let auto_updater = auto_updater.read(cx);
let server_url = &auto_updater.server_url;
let current_version = auto_updater.current_version;
let latest_release_url = if cx.has_global::<ReleaseChannel>()
&& *cx.global::<ReleaseChannel>() == ReleaseChannel::Preview
{
format!("{server_url}/releases/preview/{current_version}")
} else {
format!("{server_url}/releases/stable/{current_version}")
};
cx.platform().open_url(&latest_release_url);
if cx.has_global::<ReleaseChannel>() {
match cx.global::<ReleaseChannel>() {
ReleaseChannel::Dev => {}
ReleaseChannel::Nightly => {}
ReleaseChannel::Preview => cx
.platform()
.open_url(&format!("{server_url}/releases/preview/{current_version}")),
ReleaseChannel::Stable => cx
.platform()
.open_url(&format!("{server_url}/releases/stable/{current_version}")),
}
}
}
}
@ -224,22 +228,19 @@ impl AutoUpdater {
)
});
let preview_param = cx.read(|cx| {
let mut url_string = format!(
"{server_url}/api/releases/latest?token={ZED_SECRET_CLIENT_TOKEN}&asset=Zed.dmg"
);
cx.read(|cx| {
if cx.has_global::<ReleaseChannel>() {
if *cx.global::<ReleaseChannel>() == ReleaseChannel::Preview {
return "&preview=1";
if let Some(param) = cx.global::<ReleaseChannel>().release_query_param() {
url_string += "&";
url_string += param;
}
}
""
});
let mut response = client
.get(
&format!("{server_url}/api/releases/latest?token={ZED_SECRET_CLIENT_TOKEN}&asset=Zed.dmg{preview_param}"),
Default::default(),
true,
)
.await?;
let mut response = client.get(&url_string, Default::default(), true).await?;
let mut body = Vec::new();
response

View File

@ -0,0 +1,29 @@
[package]
name = "auto_update2"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
path = "src/auto_update.rs"
doctest = false
[dependencies]
db = { package = "db2", path = "../db2" }
client = { package = "client2", path = "../client2" }
gpui = { package = "gpui2", path = "../gpui2" }
menu = { package = "menu2", path = "../menu2" }
project = { package = "project2", path = "../project2" }
settings = { package = "settings2", path = "../settings2" }
theme = { package = "theme2", path = "../theme2" }
workspace = { package = "workspace2", path = "../workspace2" }
util = { path = "../util" }
anyhow.workspace = true
isahc.workspace = true
lazy_static.workspace = true
log.workspace = true
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
smol.workspace = true
tempdir.workspace = true

View File

@ -0,0 +1,392 @@
mod update_notification;
use anyhow::{anyhow, Context, Result};
use client::{Client, TelemetrySettings, ZED_APP_PATH, ZED_APP_VERSION, ZED_SECRET_CLIENT_TOKEN};
use db::kvp::KEY_VALUE_STORE;
use db::RELEASE_CHANNEL;
use gpui::{
actions, AppContext, AsyncAppContext, Context as _, Model, ModelContext, SemanticVersion, Task,
ViewContext, VisualContext,
};
use isahc::AsyncBody;
use serde::Deserialize;
use serde_derive::Serialize;
use smol::io::AsyncReadExt;
use settings::{Settings, SettingsStore};
use smol::{fs::File, process::Command};
use std::{ffi::OsString, sync::Arc, time::Duration};
use update_notification::UpdateNotification;
use util::channel::{AppCommitSha, ReleaseChannel};
use util::http::HttpClient;
use workspace::Workspace;
const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification";
const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60);
actions!(Check, DismissErrorMessage, ViewReleaseNotes);
#[derive(Serialize)]
struct UpdateRequestBody {
installation_id: Option<Arc<str>>,
release_channel: Option<&'static str>,
telemetry: bool,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AutoUpdateStatus {
Idle,
Checking,
Downloading,
Installing,
Updated,
Errored,
}
pub struct AutoUpdater {
status: AutoUpdateStatus,
current_version: SemanticVersion,
http_client: Arc<dyn HttpClient>,
pending_poll: Option<Task<Option<()>>>,
server_url: String,
}
#[derive(Deserialize)]
struct JsonRelease {
version: String,
url: String,
}
struct AutoUpdateSetting(bool);
impl Settings for AutoUpdateSetting {
const KEY: Option<&'static str> = Some("auto_update");
type FileContent = Option<bool>;
fn load(
default_value: &Option<bool>,
user_values: &[&Option<bool>],
_: &mut AppContext,
) -> Result<Self> {
Ok(Self(
Self::json_merge(default_value, user_values)?.ok_or_else(Self::missing_default)?,
))
}
}
pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppContext) {
AutoUpdateSetting::register(cx);
cx.observe_new_views(|wokrspace: &mut Workspace, _cx| {
wokrspace.register_action(|_, action: &Check, cx| check(action, cx));
})
.detach();
if let Some(version) = *ZED_APP_VERSION {
let auto_updater = cx.build_model(|cx| {
let updater = AutoUpdater::new(version, http_client, server_url);
let mut update_subscription = AutoUpdateSetting::get_global(cx)
.0
.then(|| updater.start_polling(cx));
cx.observe_global::<SettingsStore>(move |updater, cx| {
if AutoUpdateSetting::get_global(cx).0 {
if update_subscription.is_none() {
update_subscription = Some(updater.start_polling(cx))
}
} else {
update_subscription.take();
}
})
.detach();
updater
});
cx.set_global(Some(auto_updater));
//todo!(action)
// cx.add_global_action(view_release_notes);
// cx.add_action(UpdateNotification::dismiss);
}
}
pub fn check(_: &Check, cx: &mut AppContext) {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
}
}
fn _view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) {
if let Some(auto_updater) = AutoUpdater::get(cx) {
let auto_updater = auto_updater.read(cx);
let server_url = &auto_updater.server_url;
let current_version = auto_updater.current_version;
if cx.has_global::<ReleaseChannel>() {
match cx.global::<ReleaseChannel>() {
ReleaseChannel::Dev => {}
ReleaseChannel::Nightly => {}
ReleaseChannel::Preview => {
cx.open_url(&format!("{server_url}/releases/preview/{current_version}"))
}
ReleaseChannel::Stable => {
cx.open_url(&format!("{server_url}/releases/stable/{current_version}"))
}
}
}
}
}
pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
let updater = AutoUpdater::get(cx)?;
let version = updater.read(cx).current_version;
let should_show_notification = updater.read(cx).should_show_update_notification(cx);
cx.spawn(|workspace, mut cx| async move {
let should_show_notification = should_show_notification.await?;
if should_show_notification {
workspace.update(&mut cx, |workspace, cx| {
workspace.show_notification(0, cx, |cx| {
cx.build_view(|_| UpdateNotification::new(version))
});
updater
.read(cx)
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
})?;
}
anyhow::Ok(())
})
.detach();
None
}
impl AutoUpdater {
pub fn get(cx: &mut AppContext) -> Option<Model<Self>> {
cx.default_global::<Option<Model<Self>>>().clone()
}
fn new(
current_version: SemanticVersion,
http_client: Arc<dyn HttpClient>,
server_url: String,
) -> Self {
Self {
status: AutoUpdateStatus::Idle,
current_version,
http_client,
server_url,
pending_poll: None,
}
}
pub fn start_polling(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
cx.spawn(|this, mut cx| async move {
loop {
this.update(&mut cx, |this, cx| this.poll(cx))?;
cx.background_executor().timer(POLL_INTERVAL).await;
}
})
}
pub fn poll(&mut self, cx: &mut ModelContext<Self>) {
if self.pending_poll.is_some() || self.status == AutoUpdateStatus::Updated {
return;
}
self.status = AutoUpdateStatus::Checking;
cx.notify();
self.pending_poll = Some(cx.spawn(|this, mut cx| async move {
let result = Self::update(this.upgrade()?, cx.clone()).await;
this.update(&mut cx, |this, cx| {
this.pending_poll = None;
if let Err(error) = result {
log::error!("auto-update failed: error:{:?}", error);
this.status = AutoUpdateStatus::Errored;
cx.notify();
}
})
.ok()
}));
}
pub fn status(&self) -> AutoUpdateStatus {
self.status
}
pub fn dismiss_error(&mut self, cx: &mut ModelContext<Self>) {
self.status = AutoUpdateStatus::Idle;
cx.notify();
}
async fn update(this: Model<Self>, mut cx: AsyncAppContext) -> Result<()> {
let (client, server_url, current_version) = this.read_with(&cx, |this, _| {
(
this.http_client.clone(),
this.server_url.clone(),
this.current_version,
)
})?;
let mut url_string = format!(
"{server_url}/api/releases/latest?token={ZED_SECRET_CLIENT_TOKEN}&asset=Zed.dmg"
);
cx.update(|cx| {
if cx.has_global::<ReleaseChannel>() {
if let Some(param) = cx.global::<ReleaseChannel>().release_query_param() {
url_string += "&";
url_string += param;
}
}
})?;
let mut response = client.get(&url_string, Default::default(), true).await?;
let mut body = Vec::new();
response
.body_mut()
.read_to_end(&mut body)
.await
.context("error reading release")?;
let release: JsonRelease =
serde_json::from_slice(body.as_slice()).context("error deserializing release")?;
let should_download = match *RELEASE_CHANNEL {
ReleaseChannel::Nightly => cx
.try_read_global::<AppCommitSha, _>(|sha, _| release.version != sha.0)
.unwrap_or(true),
_ => release.version.parse::<SemanticVersion>()? <= current_version,
};
if !should_download {
this.update(&mut cx, |this, cx| {
this.status = AutoUpdateStatus::Idle;
cx.notify();
})?;
return Ok(());
}
this.update(&mut cx, |this, cx| {
this.status = AutoUpdateStatus::Downloading;
cx.notify();
})?;
let temp_dir = tempdir::TempDir::new("zed-auto-update")?;
let dmg_path = temp_dir.path().join("Zed.dmg");
let mount_path = temp_dir.path().join("Zed");
let running_app_path = ZED_APP_PATH
.clone()
.map_or_else(|| cx.update(|cx| cx.app_path())?, Ok)?;
let running_app_filename = running_app_path
.file_name()
.ok_or_else(|| anyhow!("invalid running app path"))?;
let mut mounted_app_path: OsString = mount_path.join(running_app_filename).into();
mounted_app_path.push("/");
let mut dmg_file = File::create(&dmg_path).await?;
let (installation_id, release_channel, telemetry) = cx.update(|cx| {
let installation_id = cx.global::<Arc<Client>>().telemetry().installation_id();
let release_channel = cx
.has_global::<ReleaseChannel>()
.then(|| cx.global::<ReleaseChannel>().display_name());
let telemetry = TelemetrySettings::get_global(cx).metrics;
(installation_id, release_channel, telemetry)
})?;
let request_body = AsyncBody::from(serde_json::to_string(&UpdateRequestBody {
installation_id,
release_channel,
telemetry,
})?);
let mut response = client.get(&release.url, request_body, true).await?;
smol::io::copy(response.body_mut(), &mut dmg_file).await?;
log::info!("downloaded update. path:{:?}", dmg_path);
this.update(&mut cx, |this, cx| {
this.status = AutoUpdateStatus::Installing;
cx.notify();
})?;
let output = Command::new("hdiutil")
.args(&["attach", "-nobrowse"])
.arg(&dmg_path)
.arg("-mountroot")
.arg(&temp_dir.path())
.output()
.await?;
if !output.status.success() {
Err(anyhow!(
"failed to mount: {:?}",
String::from_utf8_lossy(&output.stderr)
))?;
}
let output = Command::new("rsync")
.args(&["-av", "--delete"])
.arg(&mounted_app_path)
.arg(&running_app_path)
.output()
.await?;
if !output.status.success() {
Err(anyhow!(
"failed to copy app: {:?}",
String::from_utf8_lossy(&output.stderr)
))?;
}
let output = Command::new("hdiutil")
.args(&["detach"])
.arg(&mount_path)
.output()
.await?;
if !output.status.success() {
Err(anyhow!(
"failed to unmount: {:?}",
String::from_utf8_lossy(&output.stderr)
))?;
}
this.update(&mut cx, |this, cx| {
this.set_should_show_update_notification(true, cx)
.detach_and_log_err(cx);
this.status = AutoUpdateStatus::Updated;
cx.notify();
})?;
Ok(())
}
fn set_should_show_update_notification(
&self,
should_show: bool,
cx: &AppContext,
) -> Task<Result<()>> {
cx.background_executor().spawn(async move {
if should_show {
KEY_VALUE_STORE
.write_kvp(
SHOULD_SHOW_UPDATE_NOTIFICATION_KEY.to_string(),
"".to_string(),
)
.await?;
} else {
KEY_VALUE_STORE
.delete_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY.to_string())
.await?;
}
Ok(())
})
}
fn should_show_update_notification(&self, cx: &AppContext) -> Task<Result<bool>> {
cx.background_executor().spawn(async move {
Ok(KEY_VALUE_STORE
.read_kvp(SHOULD_SHOW_UPDATE_NOTIFICATION_KEY)?
.is_some())
})
}
}

View File

@ -0,0 +1,87 @@
use gpui::{div, Div, EventEmitter, ParentComponent, Render, SemanticVersion, ViewContext};
use menu::Cancel;
use workspace::notifications::NotificationEvent;
pub struct UpdateNotification {
_version: SemanticVersion,
}
impl EventEmitter<NotificationEvent> for UpdateNotification {}
impl Render for UpdateNotification {
type Element = Div<Self>;
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div().child("Updated zed!")
// let theme = theme::current(cx).clone();
// let theme = &theme.update_notification;
// let app_name = cx.global::<ReleaseChannel>().display_name();
// MouseEventHandler::new::<ViewReleaseNotes, _>(0, cx, |state, cx| {
// Flex::column()
// .with_child(
// Flex::row()
// .with_child(
// Text::new(
// format!("Updated to {app_name} {}", self.version),
// theme.message.text.clone(),
// )
// .contained()
// .with_style(theme.message.container)
// .aligned()
// .top()
// .left()
// .flex(1., true),
// )
// .with_child(
// MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
// let style = theme.dismiss_button.style_for(state);
// Svg::new("icons/x.svg")
// .with_color(style.color)
// .constrained()
// .with_width(style.icon_width)
// .aligned()
// .contained()
// .with_style(style.container)
// .constrained()
// .with_width(style.button_width)
// .with_height(style.button_width)
// })
// .with_padding(Padding::uniform(5.))
// .on_click(MouseButton::Left, move |_, this, cx| {
// this.dismiss(&Default::default(), cx)
// })
// .aligned()
// .constrained()
// .with_height(cx.font_cache().line_height(theme.message.text.font_size))
// .aligned()
// .top()
// .flex_float(),
// ),
// )
// .with_child({
// let style = theme.action_message.style_for(state);
// Text::new("View the release notes", style.text.clone())
// .contained()
// .with_style(style.container)
// })
// .contained()
// })
// .with_cursor_style(CursorStyle::PointingHand)
// .on_click(MouseButton::Left, |_, _, cx| {
// crate::view_release_notes(&Default::default(), cx)
// })
// .into_any_named("update notification")
}
}
impl UpdateNotification {
pub fn new(version: SemanticVersion) -> Self {
Self { _version: version }
}
pub fn _dismiss(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
cx.emit(NotificationEvent::Dismiss);
}
}

View File

@ -987,9 +987,17 @@ impl Client {
self.establish_websocket_connection(credentials, cx)
}
async fn get_rpc_url(http: Arc<dyn HttpClient>, is_preview: bool) -> Result<Url> {
let preview_param = if is_preview { "?preview=1" } else { "" };
let url = format!("{}/rpc{preview_param}", *ZED_SERVER_URL);
async fn get_rpc_url(
http: Arc<dyn HttpClient>,
release_channel: Option<ReleaseChannel>,
) -> Result<Url> {
let mut url = format!("{}/rpc", *ZED_SERVER_URL);
if let Some(preview_param) =
release_channel.and_then(|channel| channel.release_query_param())
{
url += "?";
url += preview_param;
}
let response = http.get(&url, Default::default(), false).await?;
// Normally, ZED_SERVER_URL is set to the URL of zed.dev website.
@ -1024,11 +1032,11 @@ impl Client {
credentials: &Credentials,
cx: &AsyncAppContext,
) -> Task<Result<Connection, EstablishConnectionError>> {
let use_preview_server = cx.read(|cx| {
let release_channel = cx.read(|cx| {
if cx.has_global::<ReleaseChannel>() {
*cx.global::<ReleaseChannel>() != ReleaseChannel::Stable
Some(*cx.global::<ReleaseChannel>())
} else {
false
None
}
});
@ -1041,7 +1049,7 @@ impl Client {
let http = self.http.clone();
cx.background().spawn(async move {
let mut rpc_url = Self::get_rpc_url(http, use_preview_server).await?;
let mut rpc_url = Self::get_rpc_url(http, release_channel).await?;
let rpc_host = rpc_url
.host_str()
.zip(rpc_url.port_or_known_default())
@ -1191,7 +1199,7 @@ impl Client {
// Use the collab server's admin API to retrieve the id
// of the impersonated user.
let mut url = Self::get_rpc_url(http.clone(), false).await?;
let mut url = Self::get_rpc_url(http.clone(), None).await?;
url.set_path("/user");
url.set_query(Some(&format!("github_login={login}")));
let request = Request::get(url.as_str())

View File

@ -20,7 +20,7 @@ pub struct Telemetry {
#[derive(Default)]
struct TelemetryState {
metrics_id: Option<Arc<str>>, // Per logged-in user
installation_id: Option<Arc<str>>, // Per app installation (different for dev, preview, and stable)
installation_id: Option<Arc<str>>, // Per app installation (different for dev, nightly, preview, and stable)
session_id: Option<Arc<str>>, // Per app launch
app_version: Option<Arc<str>>,
release_channel: Option<&'static str>,

View File

@ -923,9 +923,17 @@ impl Client {
self.establish_websocket_connection(credentials, cx)
}
async fn get_rpc_url(http: Arc<dyn HttpClient>, is_preview: bool) -> Result<Url> {
let preview_param = if is_preview { "?preview=1" } else { "" };
let url = format!("{}/rpc{preview_param}", *ZED_SERVER_URL);
async fn get_rpc_url(
http: Arc<dyn HttpClient>,
release_channel: Option<ReleaseChannel>,
) -> Result<Url> {
let mut url = format!("{}/rpc", *ZED_SERVER_URL);
if let Some(preview_param) =
release_channel.and_then(|channel| channel.release_query_param())
{
url += "?";
url += preview_param;
}
let response = http.get(&url, Default::default(), false).await?;
// Normally, ZED_SERVER_URL is set to the URL of zed.dev website.
@ -960,9 +968,7 @@ impl Client {
credentials: &Credentials,
cx: &AsyncAppContext,
) -> Task<Result<Connection, EstablishConnectionError>> {
let use_preview_server = cx
.try_read_global(|channel: &ReleaseChannel, _| *channel != ReleaseChannel::Stable)
.unwrap_or(false);
let release_channel = cx.try_read_global(|channel: &ReleaseChannel, _| *channel);
let request = Request::builder()
.header(
@ -973,7 +979,7 @@ impl Client {
let http = self.http.clone();
cx.background_executor().spawn(async move {
let mut rpc_url = Self::get_rpc_url(http, use_preview_server).await?;
let mut rpc_url = Self::get_rpc_url(http, release_channel).await?;
let rpc_host = rpc_url
.host_str()
.zip(rpc_url.port_or_known_default())
@ -1120,7 +1126,7 @@ impl Client {
// Use the collab server's admin API to retrieve the id
// of the impersonated user.
let mut url = Self::get_rpc_url(http.clone(), false).await?;
let mut url = Self::get_rpc_url(http.clone(), None).await?;
url.set_path("/user");
url.set_query(Some(&format!("github_login={login}")));
let request = Request::get(url.as_str())

View File

@ -20,7 +20,7 @@ pub struct Telemetry {
struct TelemetryState {
metrics_id: Option<Arc<str>>, // Per logged-in user
installation_id: Option<Arc<str>>, // Per app installation (different for dev, preview, and stable)
installation_id: Option<Arc<str>>, // Per app installation (different for dev, nightly, preview, and stable)
session_id: Option<Arc<str>>, // Per app launch
release_channel: Option<&'static str>,
app_metadata: AppMetadata,

View File

@ -492,6 +492,10 @@ impl AppContext {
self.platform.open_url(url);
}
pub fn app_path(&self) -> Result<PathBuf> {
self.platform.app_path()
}
pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
self.platform.path_for_auxiliary_executable(name)
}

View File

@ -1,6 +1,5 @@
use std::env;
use lazy_static::lazy_static;
use std::env;
lazy_static! {
pub static ref RELEASE_CHANNEL_NAME: String = if cfg!(debug_assertions) {
@ -9,18 +8,22 @@ lazy_static! {
} else {
include_str!("../../zed/RELEASE_CHANNEL").to_string()
};
pub static ref RELEASE_CHANNEL: ReleaseChannel = match RELEASE_CHANNEL_NAME.as_str() {
pub static ref RELEASE_CHANNEL: ReleaseChannel = match RELEASE_CHANNEL_NAME.as_str().trim() {
"dev" => ReleaseChannel::Dev,
"nightly" => ReleaseChannel::Nightly,
"preview" => ReleaseChannel::Preview,
"stable" => ReleaseChannel::Stable,
_ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
};
}
pub struct AppCommitSha(pub String);
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub enum ReleaseChannel {
#[default]
Dev,
Nightly,
Preview,
Stable,
}
@ -29,6 +32,7 @@ impl ReleaseChannel {
pub fn display_name(&self) -> &'static str {
match self {
ReleaseChannel::Dev => "Zed Dev",
ReleaseChannel::Nightly => "Zed Nightly",
ReleaseChannel::Preview => "Zed Preview",
ReleaseChannel::Stable => "Zed",
}
@ -37,6 +41,7 @@ impl ReleaseChannel {
pub fn dev_name(&self) -> &'static str {
match self {
ReleaseChannel::Dev => "dev",
ReleaseChannel::Nightly => "nightly",
ReleaseChannel::Preview => "preview",
ReleaseChannel::Stable => "stable",
}
@ -45,6 +50,7 @@ impl ReleaseChannel {
pub fn url_scheme(&self) -> &'static str {
match self {
ReleaseChannel::Dev => "zed-dev://",
ReleaseChannel::Nightly => "zed-nightly://",
ReleaseChannel::Preview => "zed-preview://",
ReleaseChannel::Stable => "zed://",
}
@ -53,15 +59,27 @@ impl ReleaseChannel {
pub fn link_prefix(&self) -> &'static str {
match self {
ReleaseChannel::Dev => "https://zed.dev/dev/",
// TODO kb need to add server handling
ReleaseChannel::Nightly => "https://zed.dev/nightly/",
ReleaseChannel::Preview => "https://zed.dev/preview/",
ReleaseChannel::Stable => "https://zed.dev/",
}
}
pub fn release_query_param(&self) -> Option<&'static str> {
match self {
Self::Dev => None,
Self::Nightly => Some("nightly=1"),
Self::Preview => Some("preview=1"),
Self::Stable => None,
}
}
}
pub fn parse_zed_link(link: &str) -> Option<&str> {
for release in [
ReleaseChannel::Dev,
ReleaseChannel::Nightly,
ReleaseChannel::Preview,
ReleaseChannel::Stable,
] {

View File

@ -15,6 +15,8 @@ pub enum NotificationEvent {
pub trait Notification: EventEmitter<NotificationEvent> + Render {}
impl<V: EventEmitter<NotificationEvent> + Render> Notification for V {}
pub trait NotificationHandle: Send {
fn id(&self) -> EntityId;
fn to_any(&self) -> AnyView;
@ -164,7 +166,7 @@ impl Workspace {
}
pub mod simple_message_notification {
use super::{Notification, NotificationEvent};
use super::NotificationEvent;
use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
use serde::Deserialize;
use std::{borrow::Cow, sync::Arc};
@ -359,7 +361,6 @@ pub mod simple_message_notification {
// }
impl EventEmitter<NotificationEvent> for MessageNotification {}
impl Notification for MessageNotification {}
}
pub trait NotifyResultExt {

View File

@ -170,6 +170,15 @@ osx_minimum_system_version = "10.15.7"
osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed-dev"]
[package.metadata.bundle-nightly]
# TODO kb different icon?
icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"]
identifier = "dev.zed.Zed-Nightly"
name = "Zed Nightly"
osx_minimum_system_version = "10.15.7"
osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed-nightly"]
[package.metadata.bundle-preview]
icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"]
identifier = "dev.zed.Zed-Preview"
@ -178,7 +187,6 @@ osx_minimum_system_version = "10.15.7"
osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed-preview"]
[package.metadata.bundle-stable]
icon = ["resources/app-icon@2x.png", "resources/app-icon.png"]
identifier = "dev.zed.Zed"

Binary file not shown.

View File

@ -17,6 +17,7 @@ fn address() -> SocketAddr {
ReleaseChannel::Dev => 43737,
ReleaseChannel::Preview => 43738,
ReleaseChannel::Stable => 43739,
ReleaseChannel::Nightly => 43740,
};
SocketAddr::V4(SocketAddrV4::new(LOCALHOST, port))
@ -25,6 +26,7 @@ fn address() -> SocketAddr {
fn instance_handshake() -> &'static str {
match *util::channel::RELEASE_CHANNEL {
ReleaseChannel::Dev => "Zed Editor Dev Instance Running",
ReleaseChannel::Nightly => "Zed Editor Nightly Instance Running",
ReleaseChannel::Preview => "Zed Editor Preview Instance Running",
ReleaseChannel::Stable => "Zed Editor Stable Instance Running",
}

View File

@ -11,14 +11,14 @@ path = "src/zed2.rs"
doctest = false
[[bin]]
name = "Zed2"
name = "zed2"
path = "src/main.rs"
[dependencies]
ai = { package = "ai2", path = "../ai2"}
# audio = { path = "../audio" }
# activity_indicator = { path = "../activity_indicator" }
# auto_update = { path = "../auto_update" }
auto_update = { package = "auto_update2", path = "../auto_update2" }
# breadcrumbs = { path = "../breadcrumbs" }
call = { package = "call2", path = "../call2" }
# channel = { path = "../channel" }
@ -166,6 +166,14 @@ osx_minimum_system_version = "10.15.7"
osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed-dev"]
[package.metadata.bundle-nightly]
icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"]
identifier = "dev.zed.Zed-Dev"
name = "Zed Nightly"
osx_minimum_system_version = "10.15.7"
osx_info_plist_exts = ["resources/info/*"]
osx_url_schemes = ["zed-dev"]
[package.metadata.bundle-preview]
icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"]
identifier = "dev.zed.Zed-Preview"

View File

@ -1,3 +1,5 @@
use std::process::Command;
fn main() {
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15.7");
@ -21,4 +23,14 @@ fn main() {
// Register exported Objective-C selectors, protocols, etc
println!("cargo:rustc-link-arg=-Wl,-ObjC");
// Populate git sha environment variable if git is available
if let Ok(output) = Command::new("git").args(["rev-parse", "HEAD"]).output() {
if output.status.success() {
println!(
"cargo:rustc-env=ZED_COMMIT_SHA={}",
String::from_utf8_lossy(&output.stdout).trim()
);
}
}
}

Binary file not shown.

View File

@ -43,7 +43,7 @@ use std::{
use theme::ActiveTheme;
use util::{
async_maybe,
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
channel::{parse_zed_link, AppCommitSha, ReleaseChannel, RELEASE_CHANNEL},
http::{self, HttpClient},
paths, ResultExt,
};
@ -113,6 +113,10 @@ fn main() {
app.run(move |cx| {
cx.set_global(*RELEASE_CHANNEL);
if let Some(build_sha) = option_env!("ZED_COMMIT_SHA") {
cx.set_global(AppCommitSha(build_sha.into()))
}
cx.set_global(listener.clone());
load_embedded_fonts(cx);
@ -183,7 +187,7 @@ fn main() {
cx.set_global(Arc::downgrade(&app_state));
// audio::init(Assets, cx);
// auto_update::init(http.clone(), client::ZED_SERVER_URL.clone(), cx);
auto_update::init(http.clone(), client::ZED_SERVER_URL.clone(), cx);
workspace::init(app_state.clone(), cx);
// recent_projects::init(cx);

View File

@ -17,6 +17,7 @@ fn address() -> SocketAddr {
ReleaseChannel::Dev => 43737,
ReleaseChannel::Preview => 43738,
ReleaseChannel::Stable => 43739,
ReleaseChannel::Nightly => 43740,
};
SocketAddr::V4(SocketAddrV4::new(LOCALHOST, port))
@ -25,6 +26,7 @@ fn address() -> SocketAddr {
fn instance_handshake() -> &'static str {
match *util::channel::RELEASE_CHANNEL {
ReleaseChannel::Dev => "Zed Editor Dev Instance Running",
ReleaseChannel::Nightly => "Zed Editor Nightly Instance Running",
ReleaseChannel::Preview => "Zed Editor Preview Instance Running",
ReleaseChannel::Stable => "Zed Editor Stable Instance Running",
}

View File

@ -23,7 +23,7 @@ use std::{borrow::Cow, ops::Deref, sync::Arc};
use terminal_view::terminal_panel::TerminalPanel;
use util::{
asset_str,
channel::ReleaseChannel,
channel::{AppCommitSha, ReleaseChannel},
paths::{self, LOCAL_SETTINGS_RELATIVE_PATH},
ResultExt,
};
@ -162,7 +162,7 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
// status_bar.add_right_item(cursor_position, cx);
});
// auto_update::notify_of_any_new_update(cx.weak_handle(), cx);
auto_update::notify_of_any_new_update(cx);
// vim::observe_keystrokes(cx);
@ -432,9 +432,16 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
}
fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext<Workspace>) {
use std::fmt::Write as _;
let app_name = cx.global::<ReleaseChannel>().display_name();
let version = env!("CARGO_PKG_VERSION");
let prompt = cx.prompt(PromptLevel::Info, &format!("{app_name} {version}"), &["OK"]);
let mut message = format!("{app_name} {version}");
if let Some(sha) = cx.try_global::<AppCommitSha>() {
write!(&mut message, "\n\n{}", sha.0).unwrap();
}
let prompt = cx.prompt(PromptLevel::Info, &message, &["OK"]);
cx.foreground_executor()
.spawn(async {
prompt.await.ok();

11
script/bump-nightly Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" != "main" ]; then
echo "You must be on main to run this script"
exit 1
fi
git pull --ff-only origin main
git tag -f nightly
git push -f origin nightly

View File

@ -43,8 +43,8 @@ if [[ $patch != 0 ]]; then
echo "patch version on main should be zero"
exit 1
fi
if [[ $(cat crates/zed/RELEASE_CHANNEL) != dev ]]; then
echo "release channel on main should be dev"
if [[ $(cat crates/zed/RELEASE_CHANNEL) != dev && $(cat crates/zed/RELEASE_CHANNEL) != nightly ]]; then
echo "release channel on main should be dev or nightly"
exit 1
fi
if git show-ref --quiet refs/tags/${preview_tag_name}; then
@ -59,6 +59,7 @@ if ! git show-ref --quiet refs/heads/${prev_minor_branch_name}; then
echo "previous branch ${minor_branch_name} doesn't exist"
exit 1
fi
# TODO kb anything else for RELEASE_CHANNEL == nightly needs to be done below?
if [[ $(git show ${prev_minor_branch_name}:crates/zed/RELEASE_CHANNEL) != preview ]]; then
echo "release channel on branch ${prev_minor_branch_name} should be preview"
exit 1

View File

@ -9,8 +9,11 @@ case $channel in
preview)
tag_suffix="-pre"
;;
nightly)
tag_suffix="-nightly"
;;
*)
echo "this must be run on a stable or preview release branch" >&2
echo "this must be run on either of stable|preview|nightly release branches" >&2
exit 1
;;
esac

View File

@ -9,6 +9,7 @@ local_arch=false
local_only=false
overwrite_local_app=false
bundle_name=""
zed_crate="zed"
# This must match the team in the provsiioning profile.
APPLE_NOTORIZATION_TEAM="MQ55VZLNZQ"
@ -25,13 +26,11 @@ Options:
-o Open the resulting DMG or the app itself in local mode.
-f Overwrite the local app bundle if it exists.
-h Display this help and exit.
-2 Build zed 2 instead of zed 1.
"
}
# If -o option is specified, the folder of the resulting dmg will be opened in finder
# If -d is specified, Zed will be compiled in debug mode and the application's path printed
# If -od or -do is specified Zed will be bundled in debug and the application will be run.
while getopts 'dlfoh' flag
while getopts 'dlfoh2' flag
do
case "${flag}" in
o) open_result=true;;
@ -51,6 +50,7 @@ do
target_dir="debug"
;;
f) overwrite_local_app=true;;
2) zed_crate="zed2";;
h)
help_info
exit 0
@ -83,16 +83,19 @@ local_target_triple=${host_line#*: }
if [ "$local_arch" = true ]; then
echo "Building for local target only."
cargo build ${build_flag} --package zed
cargo build ${build_flag} --package ${zed_crate}
cargo build ${build_flag} --package cli
else
echo "Compiling zed binaries"
cargo build ${build_flag} --package zed --package cli --target aarch64-apple-darwin --target x86_64-apple-darwin
cargo build ${build_flag} --package ${zed_crate} --package cli --target aarch64-apple-darwin --target x86_64-apple-darwin
fi
echo "Creating application bundle"
pushd crates/zed
channel=$(<RELEASE_CHANNEL)
popd
pushd crates/${zed_crate}
cp Cargo.toml Cargo.toml.backup
sed \
-i .backup \
@ -131,7 +134,8 @@ else
cp -R target/${target_dir}/WebRTC.framework "${app_path}/Contents/Frameworks/"
fi
cp crates/zed/contents/$channel/embedded.provisionprofile "${app_path}/Contents/"
#todo!(The app identifier has been set to 'Dev', but the channel is nightly, RATIONALIZE ALL OF THIS MESS)
cp crates/${zed_crate}/contents/$channel/embedded.provisionprofile "${app_path}/Contents/"
if [[ -n $MACOS_CERTIFICATE && -n $MACOS_CERTIFICATE_PASSWORD && -n $APPLE_NOTARIZATION_USERNAME && -n $APPLE_NOTARIZATION_PASSWORD ]]; then
echo "Signing bundle with Apple-issued certificate"
@ -145,9 +149,14 @@ if [[ -n $MACOS_CERTIFICATE && -n $MACOS_CERTIFICATE_PASSWORD && -n $APPLE_NOTAR
# sequence of codesign commands modeled after this example: https://developer.apple.com/forums/thread/701514
/usr/bin/codesign --deep --force --timestamp --sign "Zed Industries, Inc." "${app_path}/Contents/Frameworks/WebRTC.framework" -v
/usr/bin/codesign --deep --force --timestamp --options runtime --sign "Zed Industries, Inc." "${app_path}/Contents/MacOS/cli" -v
/usr/bin/codesign --deep --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "Zed Industries, Inc." "${app_path}/Contents/MacOS/zed" -v
/usr/bin/codesign --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "Zed Industries, Inc." "${app_path}" -v
# todo!(restore cli to zed2)
if [[ "$zed_crate" == "zed" ]]; then
/usr/bin/codesign --deep --force --timestamp --options runtime --sign "Zed Industries, Inc." "${app_path}/Contents/MacOS/cli" -v
fi
/usr/bin/codesign --deep --force --timestamp --options runtime --entitlements crates/${zed_crate}/resources/zed.entitlements --sign "Zed Industries, Inc." "${app_path}/Contents/MacOS/${zed_crate}" -v
/usr/bin/codesign --force --timestamp --options runtime --entitlements crates/${zed_crate}/resources/zed.entitlements --sign "Zed Industries, Inc." "${app_path}" -v
security default-keychain -s login.keychain
else
@ -166,7 +175,7 @@ else
# - get a signing key for the MQ55VZLNZQ team from Nathan.
# - create your own signing key, and update references to MQ55VZLNZQ to your own team ID
# then comment out this line.
cat crates/zed/resources/zed.entitlements | sed '/com.apple.developer.associated-domains/,+1d' > "${app_path}/Contents/Resources/zed.entitlements"
cat crates/${zed_crate}/resources/zed.entitlements | sed '/com.apple.developer.associated-domains/,+1d' > "${app_path}/Contents/Resources/zed.entitlements"
codesign --force --deep --entitlements "${app_path}/Contents/Resources/zed.entitlements" --sign ${MACOS_SIGNING_KEY:- -} "${app_path}" -v
fi

View File

@ -4,12 +4,17 @@ set -eu
source script/lib/deploy-helpers.sh
if [[ $# < 2 ]]; then
echo "Usage: $0 <production|staging|preview> <tag-name>"
echo "Usage: $0 <production|staging|preview> <tag-name> (nightly is not yet supported)"
exit 1
fi
environment=$1
version=$2
if [[ ${environment} == "nightly" ]]; then
echo "nightly is not yet supported"
exit 1
fi
export_vars_for_environment ${environment}
image_id=$(image_id_for_version ${version})

View File

@ -4,12 +4,17 @@ set -eu
source script/lib/deploy-helpers.sh
if [[ $# < 2 ]]; then
echo "Usage: $0 <production|staging|preview> <tag-name>"
echo "Usage: $0 <production|staging|preview> <tag-name> (nightly is not yet supported)"
exit 1
fi
environment=$1
version=$2
if [[ ${environment} == "nightly" ]]; then
echo "nightly is not yet supported"
exit 1
fi
export_vars_for_environment ${environment}
image_id=$(image_id_for_version ${version})
@ -23,4 +28,4 @@ envsubst < crates/collab/k8s/migrate.template.yml | kubectl apply -f -
pod=$(kubectl --namespace=${environment} get pods --selector=job-name=${ZED_MIGRATE_JOB_NAME} --output=jsonpath='{.items[0].metadata.name}')
echo "Job pod:" $pod
kubectl --namespace=${environment} logs -f ${pod}
kubectl --namespace=${environment} logs -f ${pod}

37
script/upload-nightly Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Based on the template in: https://docs.digitalocean.com/reference/api/spaces-api/
set -ux
# Step 1: Define the parameters for the Space you want to upload to.
SPACE="zed-nightly-host" # Find your endpoint in the control panel, under Settings.
REGION="nyc3" # Must be "us-east-1" when creating new Spaces. Otherwise, use the region in your endpoint (e.g. nyc3).
# Step 2: Define a function that uploads your object via cURL.
function uploadToSpaces
{
file_to_upload="$1"
file_name="$2"
space_path="nightly"
date=$(date +"%a, %d %b %Y %T %z")
acl="x-amz-acl:private"
content_type="application/octet-stream"
storage_type="x-amz-storage-class:STANDARD"
string="PUT\n\n${content_type}\n${date}\n${acl}\n${storage_type}\n/${SPACE}/${space_path}/${file_name}"
signature=$(echo -en "${string}" | openssl sha1 -hmac "${DIGITALOCEAN_SPACES_SECRET_KEY}" -binary | base64)
curl -vv -s -X PUT -T "$file_to_upload" \
-H "Host: ${SPACE}.${REGION}.digitaloceanspaces.com" \
-H "Date: $date" \
-H "Content-Type: $content_type" \
-H "$storage_type" \
-H "$acl" \
-H "Authorization: AWS ${DIGITALOCEAN_SPACES_ACCESS_KEY}:$signature" \
"https://${SPACE}.${REGION}.digitaloceanspaces.com/${space_path}/${file_name}"
}
sha=$(git rev-parse HEAD)
echo ${sha} > target/latest-sha
uploadToSpaces "target/release/Zed.dmg" "Zed.dmg"
uploadToSpaces "target/latest-sha" "latest-sha"

View File

@ -4,11 +4,16 @@ set -eu
source script/lib/deploy-helpers.sh
if [[ $# < 1 ]]; then
echo "Usage: $0 <production|staging|preview>"
echo "Usage: $0 <production|staging|preview> (nightly is not yet supported)"
exit 1
fi
environment=$1
if [[ ${environment} == "nightly" ]]; then
echo "nightly is not yet supported"
exit 1
fi
export_vars_for_environment ${environment}
target_zed_kube_cluster