diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b8127adb924522e8b37e5ca49135432a8573b4c..8fe069c5e060ce5846cfd493f07148b8e4e8d2a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -563,8 +563,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Create macOS app bundle - run: script/bundle-mac + - name: Create macOS app bundle (aarch64) + run: script/bundle-mac aarch64-apple-darwin + + - name: Create macOS app bundle (x64) + run: script/bundle-mac x86_64-apple-darwin - name: Rename binaries run: | diff --git a/.github/workflows/release_nightly.yml b/.github/workflows/release_nightly.yml index bc31296d2bc05920dfc38f7ead8946ba0a7753ef..c593fea4cdf8538704aa6bab3478c2a3d894af41 100644 --- a/.github/workflows/release_nightly.yml +++ b/.github/workflows/release_nightly.yml @@ -96,7 +96,7 @@ jobs: Remove-Item -Recurse -Path "./../.cargo" -Force -ErrorAction SilentlyContinue shell: pwsh timeout-minutes: 60 - bundle_mac_nightly: + bundle_mac_nightly_x86_64: needs: - check_style - run_tests_mac @@ -131,11 +131,53 @@ jobs: echo "Publishing version: ${version} on release channel nightly" echo "nightly" > crates/zed/RELEASE_CHANNEL shell: bash -euxo pipefail {0} - - name: ./script/bundle-mac - run: ./script/bundle-mac + - name: run_bundling::bundle_mac + run: ./script/bundle-mac x86_64-apple-darwin shell: bash -euxo pipefail {0} - name: release_nightly::upload_zed_nightly - run: script/upload-nightly macos + run: script/upload-nightly macos x86_64 + shell: bash -euxo pipefail {0} + timeout-minutes: 60 + bundle_mac_nightly_aarch64: + needs: + - check_style + - run_tests_mac + if: github.repository_owner == 'zed-industries' + runs-on: self-mini-macos + env: + MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} + APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }} + APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }} + APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }} + steps: + - name: steps::checkout_repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + clean: false + - name: steps::setup_node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: '20' + - name: steps::setup_sentry + uses: matbour/setup-sentry-cli@3e938c54b3018bdd019973689ef984e033b0454b + with: + token: ${{ secrets.SENTRY_AUTH_TOKEN }} + - name: steps::clear_target_dir_if_large + run: ./script/clear-target-dir-if-larger-than 300 + shell: bash -euxo pipefail {0} + - name: release_nightly::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 + shell: bash -euxo pipefail {0} + - name: run_bundling::bundle_mac + run: ./script/bundle-mac aarch64-apple-darwin + shell: bash -euxo pipefail {0} + - name: release_nightly::upload_zed_nightly + run: script/upload-nightly macos aarch64 shell: bash -euxo pipefail {0} timeout-minutes: 60 bundle_linux_nightly_x86_64: @@ -176,7 +218,7 @@ jobs: run: ./script/bundle-linux shell: bash -euxo pipefail {0} - name: release_nightly::upload_zed_nightly - run: script/upload-nightly linux-targz + run: script/upload-nightly linux-targz x86_64 shell: bash -euxo pipefail {0} timeout-minutes: 60 bundle_linux_nightly_aarch64: @@ -214,7 +256,7 @@ jobs: run: ./script/bundle-linux shell: bash -euxo pipefail {0} - name: release_nightly::upload_zed_nightly - run: script/upload-nightly linux-targz + run: script/upload-nightly linux-targz aarch64 shell: bash -euxo pipefail {0} timeout-minutes: 60 bundle_windows_nightly_x86_64: @@ -372,7 +414,8 @@ jobs: continue-on-error: true update_nightly_tag: needs: - - bundle_mac_nightly + - bundle_mac_nightly_x86_64 + - bundle_mac_nightly_aarch64 - bundle_linux_nightly_x86_64 - bundle_linux_nightly_aarch64 - bundle_windows_nightly_x86_64 diff --git a/.github/workflows/run_bundling.yml b/.github/workflows/run_bundling.yml index d78298e69a9c14c8412d789a10b5b2139f76e693..98354d0b7895848196ccd58d0d953d2856cfa8c2 100644 --- a/.github/workflows/run_bundling.yml +++ b/.github/workflows/run_bundling.yml @@ -13,7 +13,7 @@ on: - labeled - synchronize jobs: - bundle_mac: + bundle_mac_x86_64: if: |- (github.event.action == 'labeled' && github.event.label.name == 'run-bundling') || (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'run-bundling')) @@ -40,19 +40,60 @@ jobs: - name: steps::clear_target_dir_if_large run: ./script/clear-target-dir-if-larger-than 300 shell: bash -euxo pipefail {0} - - name: ./script/bundle-mac - run: ./script/bundle-mac + - name: run_bundling::bundle_mac + run: ./script/bundle-mac x86_64-apple-darwin + shell: bash -euxo pipefail {0} + - name: '@actions/upload-artifact Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg' + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + with: + name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg + path: target/x86_64-apple-darwin/release/Zed.dmg + - name: '@actions/upload-artifact zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-macos-x86_64.gz' + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + with: + name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-macos-x86_64.gz + path: target/zed-remote-server-macos-x86_64.gz + timeout-minutes: 60 + bundle_mac_arm64: + if: |- + (github.event.action == 'labeled' && github.event.label.name == 'run-bundling') || + (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'run-bundling')) + runs-on: self-mini-macos + env: + MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} + APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }} + APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }} + APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }} + steps: + - name: steps::checkout_repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + clean: false + - name: steps::setup_node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: '20' + - name: steps::setup_sentry + uses: matbour/setup-sentry-cli@3e938c54b3018bdd019973689ef984e033b0454b + with: + token: ${{ secrets.SENTRY_AUTH_TOKEN }} + - name: steps::clear_target_dir_if_large + run: ./script/clear-target-dir-if-larger-than 300 + shell: bash -euxo pipefail {0} + - name: run_bundling::bundle_mac + run: ./script/bundle-mac aarch64-apple-darwin shell: bash -euxo pipefail {0} - name: '@actions/upload-artifact Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg' uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 with: name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg path: target/aarch64-apple-darwin/release/Zed.dmg - - name: '@actions/upload-artifact Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg' + - name: '@actions/upload-artifact zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-macos-aarch64.gz' uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 with: - name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg - path: target/x86_64-apple-darwin/release/Zed.dmg + name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-macos-aarch64.gz + path: target/zed-remote-server-macos-aarch64.gz timeout-minutes: 60 bundle_linux_x86_64: if: |- diff --git a/Cargo.lock b/Cargo.lock index ceeb849fe5d009067913558c0bdf9b71acc4ebc3..92dd0f747a0808c017bdc4ed65527c0be6e05bc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21670,6 +21670,7 @@ dependencies = [ name = "zeta2_tools" version = "0.1.0" dependencies = [ + "anyhow", "chrono", "clap", "client", diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 2c5f25a29ca3e54e232cb54fbe54080ac37b2419..4108e601d45f29262896cce036abb08acd17b4f3 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -1298,5 +1298,12 @@ "ctrl-enter up": "dev::Zeta2RatePredictionPositive", "ctrl-enter down": "dev::Zeta2RatePredictionNegative" } + }, + { + "context": "Zeta2Context > Editor", + "bindings": { + "alt-left": "dev::Zeta2ContextGoBack", + "alt-right": "dev::Zeta2ContextGoForward" + } } ] diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index f0a165e462a009b826302469e1fc32182c9a4d27..65092df2496cd3c40847a4cbf164e26973648d44 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -1404,5 +1404,12 @@ "cmd-enter up": "dev::Zeta2RatePredictionPositive", "cmd-enter down": "dev::Zeta2RatePredictionNegative" } + }, + { + "context": "Zeta2Context > Editor", + "bindings": { + "alt-left": "dev::Zeta2ContextGoBack", + "alt-right": "dev::Zeta2ContextGoForward" + } } ] diff --git a/assets/keymaps/default-windows.json b/assets/keymaps/default-windows.json index 5c84bb182adf7163d8330828005276405c918f9c..f867517027e12e692683f48723c0f188c5aec48d 100644 --- a/assets/keymaps/default-windows.json +++ b/assets/keymaps/default-windows.json @@ -1327,5 +1327,12 @@ "ctrl-enter up": "dev::Zeta2RatePredictionPositive", "ctrl-enter down": "dev::Zeta2RatePredictionNegative" } + }, + { + "context": "Zeta2Context > Editor", + "bindings": { + "alt-left": "dev::Zeta2ContextGoBack", + "alt-right": "dev::Zeta2ContextGoForward" + } } ] diff --git a/crates/zeta2/src/related_excerpts.rs b/crates/zeta2/src/related_excerpts.rs index 2f30ee15dc72720fca896580febc9fa75b1bc346..7434dbed9e48bb2dcf98131177dc65b2f3930094 100644 --- a/crates/zeta2/src/related_excerpts.rs +++ b/crates/zeta2/src/related_excerpts.rs @@ -1,10 +1,13 @@ -use std::{cmp::Reverse, fmt::Write, ops::Range, path::PathBuf, sync::Arc}; +use std::{cmp::Reverse, fmt::Write, ops::Range, path::PathBuf, sync::Arc, time::Instant}; -use crate::merge_excerpts::write_merged_excerpts; +use crate::{ + ZetaContextRetrievalDebugInfo, ZetaDebugInfo, ZetaSearchQueryDebugInfo, + merge_excerpts::write_merged_excerpts, +}; use anyhow::{Result, anyhow}; use collections::HashMap; use edit_prediction_context::{EditPredictionExcerpt, EditPredictionExcerptOptions, Line}; -use futures::{StreamExt, stream::BoxStream}; +use futures::{StreamExt, channel::mpsc, stream::BoxStream}; use gpui::{App, AsyncApp, Entity, Task}; use indoc::indoc; use language::{Anchor, Bias, Buffer, OffsetRangeExt, Point, TextBufferSnapshot, ToPoint as _}; @@ -61,22 +64,22 @@ const SEARCH_TOOL_NAME: &str = "search"; /// Search for relevant code /// /// For the best results, run multiple queries at once with a single invocation of this tool. -#[derive(Deserialize, JsonSchema)] -struct SearchToolInput { +#[derive(Clone, Deserialize, JsonSchema)] +pub struct SearchToolInput { /// An array of queries to run for gathering context relevant to the next prediction #[schemars(length(max = 5))] - queries: Box<[SearchToolQuery]>, + pub queries: Box<[SearchToolQuery]>, } -#[derive(Deserialize, JsonSchema)] -struct SearchToolQuery { +#[derive(Debug, Clone, Deserialize, JsonSchema)] +pub struct SearchToolQuery { /// A glob pattern to match file paths in the codebase - glob: String, + pub glob: String, /// A regular expression to match content within the files matched by the glob pattern - regex: String, + pub regex: String, /// Whether the regex is case-sensitive. Defaults to false (case-insensitive). #[serde(default)] - case_sensitive: bool, + pub case_sensitive: bool, } const RESULTS_MESSAGE: &str = indoc! {" @@ -124,6 +127,7 @@ pub fn find_related_excerpts<'a>( project: &Entity, events: impl Iterator, options: &LlmContextOptions, + debug_tx: Option>, cx: &App, ) -> Task, Vec>>>> { let language_model_registry = LanguageModelRegistry::global(cx); @@ -304,11 +308,33 @@ pub fn find_related_excerpts<'a>( snapshot: TextBufferSnapshot, } - let mut result_buffers_by_path = HashMap::default(); + let search_queries = search_calls + .iter() + .map(|(_, tool_use)| { + Ok(serde_json::from_value::( + tool_use.input.clone(), + )?) + }) + .collect::>>()?; + + if let Some(debug_tx) = &debug_tx { + debug_tx + .unbounded_send(ZetaDebugInfo::SearchQueriesGenerated( + ZetaSearchQueryDebugInfo { + project: project.clone(), + timestamp: Instant::now(), + queries: search_queries + .iter() + .flat_map(|call| call.queries.iter().cloned()) + .collect(), + }, + )) + .ok(); + } - for (index, tool_use) in search_calls.into_iter().rev() { - let call = serde_json::from_value::(tool_use.input.clone())?; + let mut result_buffers_by_path = HashMap::default(); + for ((index, tool_use), call) in search_calls.into_iter().zip(search_queries).rev() { let mut excerpts_by_buffer = HashMap::default(); for query in call.queries { @@ -392,6 +418,17 @@ pub fn find_related_excerpts<'a>( }, ], ); + + if let Some(debug_tx) = &debug_tx { + debug_tx + .unbounded_send(ZetaDebugInfo::SearchQueriesExecuted( + ZetaContextRetrievalDebugInfo { + project: project.clone(), + timestamp: Instant::now(), + }, + )) + .ok(); + } } if result_buffers_by_path.is_empty() { diff --git a/crates/zeta2/src/zeta2.rs b/crates/zeta2/src/zeta2.rs index ca931048c4bc17c22020379eee33ed6957e318a1..e0a0f6256f50ca554270ba5f410738c4ce69941e 100644 --- a/crates/zeta2/src/zeta2.rs +++ b/crates/zeta2/src/zeta2.rs @@ -45,8 +45,8 @@ mod related_excerpts; use crate::merge_excerpts::merge_excerpts; use crate::prediction::EditPrediction; -pub use crate::related_excerpts::LlmContextOptions; use crate::related_excerpts::find_related_excerpts; +pub use crate::related_excerpts::{LlmContextOptions, SearchToolQuery}; pub use provider::ZetaEditPredictionProvider; const BUFFER_CHANGE_GROUPING_INTERVAL: Duration = Duration::from_secs(1); @@ -107,7 +107,7 @@ pub struct Zeta { projects: HashMap, options: ZetaOptions, update_required: bool, - debug_tx: Option>, + debug_tx: Option>, } #[derive(Debug, Clone, PartialEq)] @@ -134,7 +134,20 @@ impl ContextMode { } } -pub struct PredictionDebugInfo { +pub enum ZetaDebugInfo { + ContextRetrievalStarted(ZetaContextRetrievalDebugInfo), + SearchQueriesGenerated(ZetaSearchQueryDebugInfo), + SearchQueriesExecuted(ZetaContextRetrievalDebugInfo), + ContextRetrievalFinished(ZetaContextRetrievalDebugInfo), + EditPredicted(ZetaEditPredictionDebugInfo), +} + +pub struct ZetaContextRetrievalDebugInfo { + pub project: Entity, + pub timestamp: Instant, +} + +pub struct ZetaEditPredictionDebugInfo { pub request: predict_edits_v3::PredictEditsRequest, pub retrieval_time: TimeDelta, pub buffer: WeakEntity, @@ -143,6 +156,12 @@ pub struct PredictionDebugInfo { pub response_rx: oneshot::Receiver>, } +pub struct ZetaSearchQueryDebugInfo { + pub project: Entity, + pub timestamp: Instant, + pub queries: Vec, +} + pub type RequestDebugInfo = predict_edits_v3::DebugInfo; struct ZetaProject { @@ -303,7 +322,7 @@ impl Zeta { } } - pub fn debug_info(&mut self) -> mpsc::UnboundedReceiver { + pub fn debug_info(&mut self) -> mpsc::UnboundedReceiver { let (debug_watch_tx, debug_watch_rx) = mpsc::unbounded(); self.debug_tx = Some(debug_watch_tx); debug_watch_rx @@ -324,11 +343,30 @@ impl Zeta { } pub fn history_for_project(&self, project: &Entity) -> impl Iterator { - static EMPTY_EVENTS: VecDeque = VecDeque::new(); self.projects .get(&project.entity_id()) - .map_or(&EMPTY_EVENTS, |project| &project.events) - .iter() + .map(|project| project.events.iter()) + .into_iter() + .flatten() + } + + pub fn context_for_project( + &self, + project: &Entity, + ) -> impl Iterator, &[Range])> { + self.projects + .get(&project.entity_id()) + .and_then(|project| { + Some( + project + .context + .as_ref()? + .iter() + .map(|(buffer, ranges)| (buffer.clone(), ranges.as_slice())), + ) + }) + .into_iter() + .flatten() } pub fn usage(&self, cx: &App) -> Option { @@ -781,24 +819,19 @@ impl Zeta { let debug_response_tx = if let Some(debug_tx) = &debug_tx { let (response_tx, response_rx) = oneshot::channel(); - if !request.referenced_declarations.is_empty() || !request.signatures.is_empty() - { - } else { - }; - let local_prompt = build_prompt(&request) .map(|(prompt, _)| prompt) .map_err(|err| err.to_string()); debug_tx - .unbounded_send(PredictionDebugInfo { + .unbounded_send(ZetaDebugInfo::EditPredicted(ZetaEditPredictionDebugInfo { request: request.clone(), retrieval_time, buffer: buffer.downgrade(), local_prompt, position, response_rx, - }) + })) .ok(); Some(response_tx) } else { @@ -1047,7 +1080,20 @@ impl Zeta { return; }; + let debug_tx = self.debug_tx.clone(); + zeta_project.refresh_context_task = Some(cx.spawn(async move |this, cx| { + if let Some(debug_tx) = &debug_tx { + debug_tx + .unbounded_send(ZetaDebugInfo::ContextRetrievalStarted( + ZetaContextRetrievalDebugInfo { + project: project.clone(), + timestamp: Instant::now(), + }, + )) + .ok(); + } + let related_excerpts = this .update(cx, |this, cx| { let Some(zeta_project) = this.projects.get(&project.entity_id()) else { @@ -1064,6 +1110,7 @@ impl Zeta { &project, zeta_project.events.iter(), options, + debug_tx, cx, ) }) @@ -1077,6 +1124,16 @@ impl Zeta { }; zeta_project.context = Some(related_excerpts); zeta_project.refresh_context_task.take(); + if let Some(debug_tx) = &this.debug_tx { + debug_tx + .unbounded_send(ZetaDebugInfo::ContextRetrievalFinished( + ZetaContextRetrievalDebugInfo { + project, + timestamp: Instant::now(), + }, + )) + .ok(); + } }) .ok() })); diff --git a/crates/zeta2_tools/Cargo.toml b/crates/zeta2_tools/Cargo.toml index edd1b1eb242c6c02001bec53120425f9a05e5d1d..0877ee6f4661e7dcdbbae5241702951746b74725 100644 --- a/crates/zeta2_tools/Cargo.toml +++ b/crates/zeta2_tools/Cargo.toml @@ -12,6 +12,7 @@ workspace = true path = "src/zeta2_tools.rs" [dependencies] +anyhow.workspace = true chrono.workspace = true client.workspace = true cloud_llm_client.workspace = true diff --git a/crates/zeta2_tools/src/zeta2_context_view.rs b/crates/zeta2_tools/src/zeta2_context_view.rs new file mode 100644 index 0000000000000000000000000000000000000000..421328df2c3f39d61352290c0ca5fd34ff39bb78 --- /dev/null +++ b/crates/zeta2_tools/src/zeta2_context_view.rs @@ -0,0 +1,412 @@ +use std::{ + any::TypeId, + collections::VecDeque, + ops::Add, + sync::Arc, + time::{Duration, Instant}, +}; + +use anyhow::Result; +use client::{Client, UserStore}; +use editor::{Editor, PathKey}; +use futures::StreamExt as _; +use gpui::{ + Animation, AnimationExt, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, + Focusable, ParentElement as _, SharedString, Styled as _, Task, TextAlign, Window, actions, + pulsating_between, +}; +use multi_buffer::MultiBuffer; +use project::Project; +use text::OffsetRangeExt; +use ui::{ + ButtonCommon, Clickable, Color, Disableable, FluentBuilder as _, Icon, IconButton, IconName, + IconSize, InteractiveElement, IntoElement, ListItem, StyledTypography, div, h_flex, v_flex, +}; +use workspace::{Item, ItemHandle as _}; +use zeta2::{ + SearchToolQuery, Zeta, ZetaContextRetrievalDebugInfo, ZetaDebugInfo, ZetaSearchQueryDebugInfo, +}; + +pub struct Zeta2ContextView { + empty_focus_handle: FocusHandle, + project: Entity, + zeta: Entity, + runs: VecDeque, + current_ix: usize, + _update_task: Task>, +} + +#[derive(Debug)] +pub struct RetrievalRun { + editor: Entity, + search_queries: Vec, + started_at: Instant, + search_results_generated_at: Option, + search_results_executed_at: Option, + finished_at: Option, +} + +actions!( + dev, + [ + /// Go to the previous context retrieval run + Zeta2ContextGoBack, + /// Go to the next context retrieval run + Zeta2ContextGoForward + ] +); + +impl Zeta2ContextView { + pub fn new( + project: Entity, + client: &Arc, + user_store: &Entity, + window: &mut gpui::Window, + cx: &mut Context, + ) -> Self { + let zeta = Zeta::global(client, user_store, cx); + + let mut debug_rx = zeta.update(cx, |zeta, _| zeta.debug_info()); + let _update_task = cx.spawn_in(window, async move |this, cx| { + while let Some(event) = debug_rx.next().await { + this.update_in(cx, |this, window, cx| { + this.handle_zeta_event(event, window, cx) + })?; + } + Ok(()) + }); + + Self { + empty_focus_handle: cx.focus_handle(), + project, + runs: VecDeque::new(), + current_ix: 0, + zeta, + _update_task, + } + } + + fn handle_zeta_event( + &mut self, + event: ZetaDebugInfo, + window: &mut gpui::Window, + cx: &mut Context, + ) { + match event { + ZetaDebugInfo::ContextRetrievalStarted(info) => { + if info.project == self.project { + self.handle_context_retrieval_started(info, window, cx); + } + } + ZetaDebugInfo::SearchQueriesGenerated(info) => { + if info.project == self.project { + self.handle_search_queries_generated(info, window, cx); + } + } + ZetaDebugInfo::SearchQueriesExecuted(info) => { + if info.project == self.project { + self.handle_search_queries_executed(info, window, cx); + } + } + ZetaDebugInfo::ContextRetrievalFinished(info) => { + if info.project == self.project { + self.handle_context_retrieval_finished(info, window, cx); + } + } + ZetaDebugInfo::EditPredicted(_) => {} + } + } + + fn handle_context_retrieval_started( + &mut self, + info: ZetaContextRetrievalDebugInfo, + window: &mut Window, + cx: &mut Context, + ) { + if self + .runs + .back() + .is_some_and(|run| run.search_results_executed_at.is_none()) + { + self.runs.pop_back(); + } + + let multibuffer = cx.new(|_| MultiBuffer::new(language::Capability::ReadOnly)); + let editor = cx + .new(|cx| Editor::for_multibuffer(multibuffer, Some(self.project.clone()), window, cx)); + + if self.runs.len() == 32 { + self.runs.pop_front(); + } + + self.runs.push_back(RetrievalRun { + editor, + search_queries: Vec::new(), + started_at: info.timestamp, + search_results_generated_at: None, + search_results_executed_at: None, + finished_at: None, + }); + + cx.notify(); + } + + fn handle_context_retrieval_finished( + &mut self, + info: ZetaContextRetrievalDebugInfo, + window: &mut Window, + cx: &mut Context, + ) { + let Some(run) = self.runs.back_mut() else { + return; + }; + + run.finished_at = Some(info.timestamp); + + let multibuffer = run.editor.read(cx).buffer().clone(); + multibuffer.update(cx, |multibuffer, cx| { + multibuffer.clear(cx); + + let context = self.zeta.read(cx).context_for_project(&self.project); + let mut paths = Vec::new(); + for (buffer, ranges) in context { + let path = PathKey::for_buffer(&buffer, cx); + let snapshot = buffer.read(cx).snapshot(); + let ranges = ranges + .iter() + .map(|range| range.to_point(&snapshot)) + .collect::>(); + paths.push((path, buffer, ranges)); + } + + for (path, buffer, ranges) in paths { + multibuffer.set_excerpts_for_path(path, buffer, ranges, 0, cx); + } + }); + + run.editor.update(cx, |editor, cx| { + editor.move_to_beginning(&Default::default(), window, cx); + }); + + cx.notify(); + } + + fn handle_search_queries_generated( + &mut self, + info: ZetaSearchQueryDebugInfo, + _window: &mut Window, + cx: &mut Context, + ) { + let Some(run) = self.runs.back_mut() else { + return; + }; + + run.search_results_generated_at = Some(info.timestamp); + run.search_queries = info.queries; + cx.notify(); + } + + fn handle_search_queries_executed( + &mut self, + info: ZetaContextRetrievalDebugInfo, + _window: &mut Window, + cx: &mut Context, + ) { + if self.current_ix + 2 == self.runs.len() { + // Switch to latest when the queries are executed + self.current_ix += 1; + } + + let Some(run) = self.runs.back_mut() else { + return; + }; + + run.search_results_executed_at = Some(info.timestamp); + cx.notify(); + } + + fn handle_go_back( + &mut self, + _: &Zeta2ContextGoBack, + window: &mut Window, + cx: &mut Context, + ) { + self.current_ix = self.current_ix.saturating_sub(1); + cx.focus_self(window); + cx.notify(); + } + + fn handle_go_forward( + &mut self, + _: &Zeta2ContextGoForward, + window: &mut Window, + cx: &mut Context, + ) { + self.current_ix = self + .current_ix + .add(1) + .min(self.runs.len().saturating_sub(1)); + cx.focus_self(window); + cx.notify(); + } + + fn render_informational_footer(&self, cx: &mut Context<'_, Zeta2ContextView>) -> ui::Div { + let is_latest = self.runs.len() == self.current_ix + 1; + let run = &self.runs[self.current_ix]; + + h_flex() + .w_full() + .font_buffer(cx) + .text_xs() + .border_t_1() + .child( + v_flex() + .h_full() + .flex_1() + .children(run.search_queries.iter().enumerate().map(|(ix, query)| { + ListItem::new(ix) + .start_slot( + Icon::new(IconName::MagnifyingGlass) + .color(Color::Muted) + .size(IconSize::Small), + ) + .child(query.regex.clone()) + })), + ) + .child( + v_flex() + .h_full() + .pr_2() + .text_align(TextAlign::Right) + .child( + h_flex() + .justify_end() + .child( + IconButton::new("go-back", IconName::ChevronLeft) + .disabled(self.current_ix == 0 || self.runs.len() < 2) + .tooltip(ui::Tooltip::for_action_title( + "Go to previous run", + &Zeta2ContextGoBack, + )) + .on_click(cx.listener(|this, _, window, cx| { + this.handle_go_back(&Zeta2ContextGoBack, window, cx); + })), + ) + .child( + div() + .child(format!("{}/{}", self.current_ix + 1, self.runs.len())) + .map(|this| { + if self.runs.back().is_some_and(|back| { + back.search_results_executed_at.is_none() + }) { + this.with_animation( + "pulsating-count", + Animation::new(Duration::from_secs(2)) + .repeat() + .with_easing(pulsating_between(0.4, 0.8)), + |label, delta| label.opacity(delta), + ) + .into_any_element() + } else { + this.into_any_element() + } + }), + ) + .child( + IconButton::new("go-forward", IconName::ChevronRight) + .disabled(self.current_ix + 1 == self.runs.len()) + .tooltip(ui::Tooltip::for_action_title( + "Go to next run", + &Zeta2ContextGoBack, + )) + .on_click(cx.listener(|this, _, window, cx| { + this.handle_go_forward(&Zeta2ContextGoForward, window, cx); + })), + ), + ) + .map(|mut div| { + let t0 = run.started_at; + let Some(t1) = run.search_results_generated_at else { + return div.child("Planning search..."); + }; + div = div.child(format!("Planned search: {:>5} ms", (t1 - t0).as_millis())); + + let Some(t2) = run.search_results_executed_at else { + return div.child("Running search..."); + }; + div = div.child(format!("Ran search: {:>5} ms", (t2 - t1).as_millis())); + + let Some(t3) = run.finished_at else { + if is_latest { + return div.child("Filtering results..."); + } else { + return div.child("Canceled"); + } + }; + div.child(format!("Filtered results: {:>5} ms", (t3 - t2).as_millis())) + }), + ) + } +} + +impl Focusable for Zeta2ContextView { + fn focus_handle(&self, cx: &App) -> FocusHandle { + self.runs + .get(self.current_ix) + .map(|run| run.editor.read(cx).focus_handle(cx)) + .unwrap_or_else(|| self.empty_focus_handle.clone()) + } +} + +impl EventEmitter<()> for Zeta2ContextView {} + +impl Item for Zeta2ContextView { + type Event = (); + + fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString { + "Edit Prediction Context".into() + } + + fn buffer_kind(&self, _cx: &App) -> workspace::item::ItemBufferKind { + workspace::item::ItemBufferKind::Multibuffer + } + + fn act_as_type<'a>( + &'a self, + type_id: TypeId, + self_handle: &'a Entity, + _: &'a App, + ) -> Option { + if type_id == TypeId::of::() { + Some(self_handle.to_any()) + } else if type_id == TypeId::of::() { + Some(self.runs.get(self.current_ix)?.editor.to_any()) + } else { + None + } + } +} + +impl gpui::Render for Zeta2ContextView { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl ui::IntoElement { + v_flex() + .key_context("Zeta2Context") + .on_action(cx.listener(Self::handle_go_back)) + .on_action(cx.listener(Self::handle_go_forward)) + .size_full() + .map(|this| { + if self.runs.is_empty() { + this.child( + v_flex() + .size_full() + .justify_center() + .items_center() + .child("No retrieval runs yet"), + ) + } else { + this.child(self.runs[self.current_ix].editor.clone()) + .child(self.render_informational_footer(cx)) + } + }) + } +} diff --git a/crates/zeta2_tools/src/zeta2_tools.rs b/crates/zeta2_tools/src/zeta2_tools.rs index d44852971b3a06b240ab1a827989cf81c0be58de..0b4a59844d7b4a02c2f41ff7654c7df0c4292f7a 100644 --- a/crates/zeta2_tools/src/zeta2_tools.rs +++ b/crates/zeta2_tools/src/zeta2_tools.rs @@ -1,3 +1,5 @@ +mod zeta2_context_view; + use std::{cmp::Reverse, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; use chrono::TimeDelta; @@ -21,16 +23,19 @@ use ui_input::InputField; use util::{ResultExt, paths::PathStyle, rel_path::RelPath}; use workspace::{Item, SplitDirection, Workspace}; use zeta2::{ - ContextMode, DEFAULT_SYNTAX_CONTEXT_OPTIONS, LlmContextOptions, PredictionDebugInfo, Zeta, - Zeta2FeatureFlag, ZetaOptions, + ContextMode, DEFAULT_SYNTAX_CONTEXT_OPTIONS, LlmContextOptions, Zeta, Zeta2FeatureFlag, + ZetaDebugInfo, ZetaEditPredictionDebugInfo, ZetaOptions, }; use edit_prediction_context::{EditPredictionContextOptions, EditPredictionExcerptOptions}; +use zeta2_context_view::Zeta2ContextView; actions!( dev, [ - /// Opens the language server protocol logs viewer. + /// Opens the edit prediction context view. + OpenZeta2ContextView, + /// Opens the edit prediction inspector. OpenZeta2Inspector, /// Rate prediction as positive. Zeta2RatePredictionPositive, @@ -60,6 +65,27 @@ pub fn init(cx: &mut App) { }); }) .detach(); + + cx.observe_new(move |workspace: &mut Workspace, _, _cx| { + workspace.register_action(move |workspace, _: &OpenZeta2ContextView, window, cx| { + let project = workspace.project(); + workspace.split_item( + SplitDirection::Right, + Box::new(cx.new(|cx| { + Zeta2ContextView::new( + project.clone(), + workspace.client(), + workspace.user_store(), + window, + cx, + ) + })), + window, + cx, + ); + }); + }) + .detach(); } // TODO show included diagnostics, and events @@ -320,7 +346,7 @@ impl Zeta2Inspector { fn update_last_prediction( &mut self, - prediction: zeta2::PredictionDebugInfo, + prediction: zeta2::ZetaDebugInfo, window: &mut Window, cx: &mut Context, ) { @@ -340,6 +366,9 @@ impl Zeta2Inspector { let language_registry = self.project.read(cx).languages().clone(); async move |this, cx| { let mut languages = HashMap::default(); + let ZetaDebugInfo::EditPredicted(prediction) = prediction else { + return; + }; for ext in prediction .request .referenced_declarations @@ -450,7 +479,7 @@ impl Zeta2Inspector { editor }); - let PredictionDebugInfo { + let ZetaEditPredictionDebugInfo { response_rx, position, buffer, diff --git a/docs/src/configuring-zed.md b/docs/src/configuring-zed.md index 1b454105d0f96b101fea8a54798ba2d90cbb3359..6eacbe10724d7cd87977d5cf680d5c5ed4ab6dc3 100644 --- a/docs/src/configuring-zed.md +++ b/docs/src/configuring-zed.md @@ -9,7 +9,7 @@ In addition to the settings described here, you may also want to change your [th You can browse through many of the supported settings via the Settings Editor, which can be opened with the {#kb zed::OpenSettings} keybinding, or through the `zed: open settings` action in the command palette. Through it, you can customize your local, user settings as well as project settings. > Note that not all settings that Zed supports are available through the Settings Editor yet. -> Some more intricate ones, such as language formatters, can only be changed through the JSON settings file {#kb: zed::OpenSettingsFile}. +> Some more intricate ones, such as language formatters, can only be changed through the JSON settings file {#kb zed::OpenSettingsFile}. ## User Settings File diff --git a/docs/src/installation.md b/docs/src/installation.md index 4d543cb04cf609299fbd12e31c0ad723a8e14f33..7f8baf0d49bb5ae7873c09424c6f464af044f241 100644 --- a/docs/src/installation.md +++ b/docs/src/installation.md @@ -59,7 +59,7 @@ Zed supports the follow macOS releases: The macOS releases labelled "Partially Supported" (Big Sur and Catalina) do not support screen sharing via Zed Collaboration. These features use the [LiveKit SDK](https://livekit.io) which relies upon [ScreenCaptureKit.framework](https://developer.apple.com/documentation/screencapturekit/) only available on macOS 12 (Monterey) and newer. -**Mac Hardware** +#### Mac Hardware Zed supports machines with Intel (x86_64) or Apple (aarch64) processors that meet the above macOS requirements: @@ -90,7 +90,7 @@ Zed supports the follow Windows releases: | Windows 11 (all releases) | Supported | Supported | | Windows 10 (64-bit) | Supported | Supported | -**Windows Hardware** +#### Windows Hardware Zed supports machines with Intel or AMD 64-bit (x86_64) processors that meet the above Windows requirements: diff --git a/script/bundle-mac b/script/bundle-mac index 8f13b347b84fcc652227ea98633995387684a992..3f895ec14b72522abddb7548a6139729adcdfe8d 100755 --- a/script/bundle-mac +++ b/script/bundle-mac @@ -9,7 +9,6 @@ open_result=false local_arch=false local_only=false local_install=false -bundle_name="" can_code_sign=false # This must match the team in the provisioning profile. @@ -19,12 +18,11 @@ APPLE_NOTARIZATION_TEAM="MQ55VZLNZQ" # Function for displaying help info help_info() { echo " -Usage: ${0##*/} [options] [bundle_name] +Usage: ${0##*/} [options] [architecture=host] Build the application bundle for macOS. Options: -d Compile in debug mode - -l Compile for local architecture only. -o Open dir with the resulting DMG or launch the app itself in local mode. -i Install the resulting DMG into /Applications in local mode. Noop without -l. -h Display this help and exit. @@ -41,12 +39,6 @@ do build_flag=""; target_dir="debug" ;; - l) - export CARGO_INCREMENTAL=true - export CARGO_BUNDLE_SKIP_BUILD=true - local_arch=true - local_only=true - ;; i) local_install=true;; h) help_info @@ -57,11 +49,6 @@ done shift $((OPTIND-1)) -if [[ $# -gt 0 ]]; then - if [ "$1" ]; then - bundle_name=$1 - fi -fi # Get release channel pushd crates/zed @@ -81,24 +68,31 @@ export CXXFLAGS="-stdlib=libc++" version_info=$(rustc --version --verbose) host_line=$(echo "$version_info" | grep host) -local_target_triple=${host_line#*: } +target_triple=${host_line#*: } +if [[ $# -gt 0 && -n "$1" ]]; then + target_triple="$1" +fi +remote_server_arch="" + +if [[ "$target_triple" = "x86_64-apple-darwin" ]]; then + remote_server_arch="x86_64" +elif [[ "$target_triple" = "aarch64-apple-darwin" ]]; then + remote_server_arch="aarch64" +else + echo "Unsupported architecture $target_triple" + exit 1 +fi # Generate the licenses first, so they can be baked into the binaries script/generate-licenses -if [ "$local_arch" = true ]; then - echo "Building for local target only." - cargo build ${build_flag} --package zed --package cli --package remote_server -else - rustup target add aarch64-apple-darwin - rustup target add x86_64-apple-darwin - - echo "Compiling zed binaries" - cargo build ${build_flag} --package zed --package cli --target aarch64-apple-darwin --target x86_64-apple-darwin - # Build remote_server in separate invocation to prevent feature unification from other crates - # from influencing dynamic libraries required by it. - cargo build ${build_flag} --package remote_server --target aarch64-apple-darwin --target x86_64-apple-darwin -fi +rustup target add $target_triple + +echo "Compiling zed binaries" +cargo build ${build_flag} --package zed --package cli --target $target_triple +# Build remote_server in separate invocation to prevent feature unification from other crates +# from influencing dynamic libraries required by it. +cargo build ${build_flag} --package remote_server --target $target_triple echo "Creating application bundle" pushd crates/zed @@ -108,13 +102,7 @@ sed \ "s/package.metadata.bundle-${channel}/package.metadata.bundle/" \ Cargo.toml -if [ "$local_arch" = true ]; then - app_path=$(cargo bundle ${build_flag} --select-workspace-root | xargs) -else - app_path_x64=$(cargo bundle ${build_flag} --target x86_64-apple-darwin --select-workspace-root | xargs) - app_path_aarch64=$(cargo bundle ${build_flag} --target aarch64-apple-darwin --select-workspace-root | xargs) - app_path=$app_path_x64 -fi +app_path=$(cargo bundle ${build_flag} --target $target_triple --select-workspace-root | xargs) mv Cargo.toml.backup Cargo.toml popd @@ -189,26 +177,12 @@ function download_git() { rm -rf "$tmp_dir" } -function prepare_binaries() { - local architecture=$1 - local app_path=$2 - - cp target/${architecture}/${target_dir}/zed "${app_path}/Contents/MacOS/zed" - cp target/${architecture}/${target_dir}/cli "${app_path}/Contents/MacOS/cli" -} - function sign_app_binaries() { - local app_path=$1 - local architecture=$2 - local architecture_dir=$3 rm -rf "${app_path}/Contents/Frameworks" mkdir -p "${app_path}/Contents/Frameworks" - if [ "$local_arch" = true ]; then - cp -R target/${target_dir}/cli "${app_path}/Contents/MacOS/" - fi echo "Downloading git binary" - download_git "${architecture}" "${app_path}/Contents/MacOS/git" + download_git "${target_triple}" "${app_path}/Contents/MacOS/git" # Note: The app identifier for our development builds is the same as the app identifier for nightly. cp crates/zed/contents/$channel/embedded.provisionprofile "${app_path}/Contents/" @@ -251,15 +225,7 @@ function sign_app_binaries() { exit 0 fi - # If bundle_name is not set or empty, use the basename of $app_path - if [ -z "$bundle_name" ]; then - bundle_name=$(basename "$app_path") - else - # If bundle_name doesn't end in .app, append it - if [[ "$bundle_name" != *.app ]]; then - bundle_name="$bundle_name.app" - fi - fi + bundle_name=$(basename "$app_path") if [ "$local_only" = true ]; then if [ "$local_install" = true ]; then @@ -277,7 +243,7 @@ function sign_app_binaries() { fi fi else - dmg_target_directory="target/${architecture_dir}/${target_dir}" + dmg_target_directory="target/${target_triple}/${target_dir}" dmg_source_directory="${dmg_target_directory}/dmg" dmg_file_path="${dmg_target_directory}/Zed.dmg" xcode_bin_dir_path="$(xcode-select -p)/usr/bin" @@ -325,44 +291,29 @@ function sign_binary() { /usr/bin/codesign --deep --force --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "$IDENTITY" "${binary_path}" -v fi } +cp target/${target_triple}/${target_dir}/zed "${app_path}/Contents/MacOS/zed" +cp target/${target_triple}/${target_dir}/cli "${app_path}/Contents/MacOS/cli" +sign_app_binaries -if [ "$local_arch" = true ]; then - sign_app_binaries "$app_path" "$local_target_triple" "$local_target_triple" - - sign_binary "target/release/remote_server" -else - # Create universal binary - prepare_binaries "aarch64-apple-darwin" "$app_path_aarch64" - prepare_binaries "x86_64-apple-darwin" "$app_path_x64" - - - sign_app_binaries "$app_path_x64" "x86_64-apple-darwin" "x86_64-apple-darwin" - sign_app_binaries "$app_path_aarch64" "aarch64-apple-darwin" "aarch64-apple-darwin" - - sign_binary "target/x86_64-apple-darwin/release/remote_server" - sign_binary "target/aarch64-apple-darwin/release/remote_server" - gzip -f --stdout --best target/x86_64-apple-darwin/release/remote_server > target/zed-remote-server-macos-x86_64.gz - gzip -f --stdout --best target/aarch64-apple-darwin/release/remote_server > target/zed-remote-server-macos-aarch64.gz -fi +sign_binary "target/$target_triple/release/remote_server" +gzip -f --stdout --best target/$target_triple/release/remote_server > target/zed-remote-server-macos-$remote_server_arch.gz function upload_debug_info() { - architecture=$1 if [[ -n "${SENTRY_AUTH_TOKEN:-}" ]]; then echo "Uploading zed debug symbols to sentry..." # note: this uploads the unstripped binary which is needed because it contains # .eh_frame data for stack unwinding. see https://github.com/getsentry/symbolic/issues/783 sentry-cli debug-files upload --include-sources --wait -p zed -o zed-dev \ - "target/${architecture}/${target_dir}/zed" \ - "target/${architecture}/${target_dir}/remote_server" \ - "target/${architecture}/${target_dir}/zed.dwarf" + "target/${target_triple}/${target_dir}/zed" \ + "target/${target_triple}/${target_dir}/remote_server" \ + "target/${target_triple}/${target_dir}/zed.dwarf" else echo "missing SENTRY_AUTH_TOKEN. skipping sentry upload." fi } if command -v sentry-cli >/dev/null 2>&1; then - upload_debug_info "aarch64-apple-darwin" - upload_debug_info "x86_64-apple-darwin" + upload_debug_info else echo "sentry-cli not found. skipping sentry upload." echo "install with: 'curl -sL https://sentry.io/get-cli | bash'" diff --git a/script/upload-nightly b/script/upload-nightly index 2fcb2994383842d53ccb8bf6b63f847ef76a7d12..985c43936457f53d1db72e4436434aa0ee59296a 100755 --- a/script/upload-nightly +++ b/script/upload-nightly @@ -14,20 +14,31 @@ is_allowed_target() { return 1 } -if [[ -n "${1:-}" ]]; then - if is_allowed_target "$1"; then - target="$1" - else - echo "Error: Target '$1' is not allowed" - echo "Usage: $0 [${allowed_targets[*]}]" - exit 1 - fi +allowed_arch=("x86_64" "aarch64") +is_allowed_arch() { + for val in "${allowed_arch[@]}"; do + if [[ "$1" == "$val" ]]; then + return 0 + fi + done + return 1 +} + +if is_allowed_target "$1"; then + target="$1" +else + echo "Error: Target '$1' is not allowed" + echo "Usage: $0 [${allowed_targets[*]}] {arch}" + exit 1 +fi +if is_allowed_arch "$2"; then + arch="$2" else -echo "Error: Target is not specified" -echo "Usage: $0 [${allowed_targets[*]}]" -exit 1 + echo "Error: Arch '$2' is not allowed" + echo "Usage: $0 $1 [${allowed_arch[*]}]" + exit 1 fi -echo "Uploading nightly for target: $target" +echo "Uploading nightly for target: $target $arch" bucket_name="zed-nightly-host" @@ -41,10 +52,9 @@ done case "$target" in macos) - upload_to_blob_store $bucket_name "target/aarch64-apple-darwin/release/Zed.dmg" "nightly/Zed-aarch64.dmg" - upload_to_blob_store $bucket_name "target/x86_64-apple-darwin/release/Zed.dmg" "nightly/Zed-x86_64.dmg" + upload_to_blob_store $bucket_name "target/$arch-apple-darwin/release/Zed.dmg" "nightly/Zed-$arch.dmg" upload_to_blob_store $bucket_name "target/latest-sha" "nightly/latest-sha" - rm -f "target/aarch64-apple-darwin/release/Zed.dmg" "target/x86_64-apple-darwin/release/Zed.dmg" "target/release/Zed.dmg" + rm -f "target/$arch-apple-darwin/release/Zed.dmg" "target/release/Zed.dmg" rm -f "target/latest-sha" ;; linux-targz) diff --git a/tooling/xtask/src/tasks/workflows/release_nightly.rs b/tooling/xtask/src/tasks/workflows/release_nightly.rs index 18134fd153244d192207bc7fac011b8854b9ab0a..4e203f6934d50ec869068d237bcf8fd193678736 100644 --- a/tooling/xtask/src/tasks/workflows/release_nightly.rs +++ b/tooling/xtask/src/tasks/workflows/release_nightly.rs @@ -1,5 +1,6 @@ use crate::tasks::workflows::{ nix_build::build_nix, + run_bundling::bundle_mac, runners::{Arch, Platform}, steps::NamedJob, vars::{mac_bundle_envs, windows_bundle_envs}, @@ -33,7 +34,8 @@ pub fn release_nightly() -> Workflow { let style = check_style(); let tests = run_tests(Platform::Mac); let windows_tests = run_tests(Platform::Windows); - let bundle_mac = bundle_mac_nightly(&[&style, &tests]); + let bundle_mac_x86 = bundle_mac_nightly(Arch::X86_64, &[&style, &tests]); + let bundle_mac_arm = bundle_mac_nightly(Arch::ARM64, &[&style, &tests]); let linux_x86 = bundle_linux_nightly(Arch::X86_64, &[&style, &tests]); let linux_arm = bundle_linux_nightly(Arch::ARM64, &[&style, &tests]); let windows_x86 = bundle_windows_nightly(Arch::X86_64, &[&style, &windows_tests]); @@ -54,7 +56,8 @@ pub fn release_nightly() -> Workflow { &[&style, &tests], ); let update_nightly_tag = update_nightly_tag_job(&[ - &bundle_mac, + &bundle_mac_x86, + &bundle_mac_arm, &linux_x86, &linux_arm, &windows_x86, @@ -70,7 +73,8 @@ pub fn release_nightly() -> Workflow { .add_job(style.name, style.job) .add_job(tests.name, tests.job) .add_job(windows_tests.name, windows_tests.job) - .add_job(bundle_mac.name, bundle_mac.job) + .add_job(bundle_mac_x86.name, bundle_mac_x86.job) + .add_job(bundle_mac_arm.name, bundle_mac_arm.job) .add_job(linux_x86.name, linux_x86.job) .add_job(linux_arm.name, linux_arm.job) .add_job(windows_x86.name, windows_x86.job) @@ -127,19 +131,21 @@ fn run_tests(platform: Platform) -> NamedJob { } } -fn bundle_mac_nightly(deps: &[&NamedJob]) -> NamedJob { +fn bundle_mac_nightly(arch: Arch, deps: &[&NamedJob]) -> NamedJob { let platform = Platform::Mac; - let job = release_job(deps) - .runs_on(runners::MAC_DEFAULT) - .envs(mac_bundle_envs()) - .add_step(steps::checkout_repo()) - .add_step(steps::setup_node()) - .add_step(steps::setup_sentry()) - .add_step(steps::clear_target_dir_if_large(platform)) - .add_step(set_release_channel_to_nightly(platform)) - .add_step(steps::script("./script/bundle-mac")) - .add_step(upload_zed_nightly(platform, Arch::ARM64)); - named::job(job) + NamedJob { + name: format!("bundle_mac_nightly_{arch}"), + job: release_job(deps) + .runs_on(runners::MAC_DEFAULT) + .envs(mac_bundle_envs()) + .add_step(steps::checkout_repo()) + .add_step(steps::setup_node()) + .add_step(steps::setup_sentry()) + .add_step(steps::clear_target_dir_if_large(platform)) + .add_step(set_release_channel_to_nightly(platform)) + .add_step(bundle_mac(arch)) + .add_step(upload_zed_nightly(platform, arch)), + } } fn bundle_linux_nightly(arch: Arch, deps: &[&NamedJob]) -> NamedJob { @@ -216,8 +222,8 @@ fn add_rust_to_path() -> Step { fn upload_zed_nightly(platform: Platform, arch: Arch) -> Step { match platform { - Platform::Linux => named::bash("script/upload-nightly linux-targz"), - Platform::Mac => named::bash("script/upload-nightly macos"), + Platform::Linux => named::bash(&format!("script/upload-nightly linux-targz {arch}")), + Platform::Mac => named::bash(&format!("script/upload-nightly macos {arch}")), Platform::Windows => { let cmd = match arch { Arch::X86_64 => "script/upload-nightly.ps1 -Architecture x86_64", diff --git a/tooling/xtask/src/tasks/workflows/run_bundling.rs b/tooling/xtask/src/tasks/workflows/run_bundling.rs index 45e4940e32ef35f8890d17a03b41466f301c9411..ee3d5b2a7558af7b8561952836badcd38d20f01e 100644 --- a/tooling/xtask/src/tasks/workflows/run_bundling.rs +++ b/tooling/xtask/src/tasks/workflows/run_bundling.rs @@ -22,7 +22,8 @@ pub fn run_bundling() -> Workflow { .add_env(("RUST_BACKTRACE", "1")) .add_env(("ZED_CLIENT_CHECKSUM_SEED", vars::ZED_CLIENT_CHECKSUM_SEED)) .add_env(("ZED_MINIDUMP_ENDPOINT", vars::ZED_SENTRY_MINIDUMP_ENDPOINT)) - .add_job("bundle_mac", bundle_mac()) + .add_job("bundle_mac_x86_64", bundle_mac_job(runners::Arch::X86_64)) + .add_job("bundle_mac_arm64", bundle_mac_job(runners::Arch::ARM64)) .add_job("bundle_linux_x86_64", bundle_linux(runners::Arch::X86_64)) .add_job("bundle_linux_arm64", bundle_linux(runners::Arch::ARM64)) .add_job( @@ -44,7 +45,8 @@ fn bundle_job() -> Job { .timeout_minutes(60u32) } -fn bundle_mac() -> Job { +fn bundle_mac_job(arch: runners::Arch) -> Job { + use vars::GITHUB_SHA; bundle_job() .runs_on(runners::MAC_DEFAULT) .envs(mac_bundle_envs()) @@ -52,17 +54,21 @@ fn bundle_mac() -> Job { .add_step(steps::setup_node()) .add_step(steps::setup_sentry()) .add_step(steps::clear_target_dir_if_large(runners::Platform::Mac)) - .add_step(steps::script("./script/bundle-mac")) + .add_step(bundle_mac(arch)) .add_step(steps::upload_artifact( - "Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg", - "target/aarch64-apple-darwin/release/Zed.dmg", + &format!("Zed_{GITHUB_SHA}-{arch}.dmg"), + &format!("target/{arch}-apple-darwin/release/Zed.dmg"), )) .add_step(steps::upload_artifact( - "Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg", - "target/x86_64-apple-darwin/release/Zed.dmg", + &format!("zed-remote-server-{GITHUB_SHA}-macos-{arch}.gz"), + &format!("target/zed-remote-server-macos-{arch}.gz"), )) } +pub fn bundle_mac(arch: runners::Arch) -> Step { + named::bash(&format!("./script/bundle-mac {arch}-apple-darwin")) +} + fn bundle_linux(arch: runners::Arch) -> Job { let artifact_name = format!("zed-{}-{}.tar.gz", vars::GITHUB_SHA, arch.triple()); let remote_server_artifact_name = format!(