ci: Notarize in parallel (different flavor) (#41392)

Piotr Osiewicz , Conrad Irwin , Ben Kunkle , and Conrad Irwin created

Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Conrad Irwin <conrad@zed.dev>

Change summary

.github/workflows/ci.yml                             |   7 
.github/workflows/release_nightly.yml                |  57 +++++
.github/workflows/run_bundling.yml                   |  53 +++++
script/bundle-mac                                    | 119 ++++---------
script/upload-nightly                                |  40 ++-
tooling/xtask/src/tasks/workflows/release_nightly.rs |  40 ++--
tooling/xtask/src/tasks/workflows/run_bundling.rs    |  20 +
7 files changed, 198 insertions(+), 138 deletions(-)

Detailed changes

.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: |

.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

.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: |-

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'"

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)

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<Run> {
 
 fn upload_zed_nightly(platform: Platform, arch: Arch) -> Step<Run> {
     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",

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<Run> {
+    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!(