ci.yml

  1name: CI
  2
  3on:
  4  push:
  5    branches:
  6      - main
  7      - "v[0-9]+.[0-9]+.x"
  8    tags:
  9      - "v*"
 10
 11  pull_request:
 12    branches:
 13      - "**"
 14
 15concurrency:
 16  # Allow only one workflow per any non-`main` branch.
 17  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
 18  cancel-in-progress: true
 19
 20env:
 21  CARGO_TERM_COLOR: always
 22  CARGO_INCREMENTAL: 0
 23  RUST_BACKTRACE: 1
 24
 25jobs:
 26  job_spec:
 27    name: Decide which jobs to run
 28    if: github.repository_owner == 'zed-industries'
 29    outputs:
 30      run_tests: ${{ steps.filter.outputs.run_tests }}
 31    runs-on:
 32      - ubuntu-latest
 33    steps:
 34      - name: Checkout repo
 35        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 36        with:
 37          # 350 is arbitrary; ~10days of history on main (5secs); full history is ~25secs
 38          fetch-depth: ${{ github.ref == 'refs/heads/main' && 2 || 350 }}
 39      - name: Fetch git history and generate output filters
 40        id: filter
 41        run: |
 42          if [ -z "$GITHUB_BASE_REF" ]; then
 43            echo "Not in a PR context (i.e., push to main/stable/preview)"
 44            COMPARE_REV=$(git rev-parse HEAD~1)
 45          else
 46            echo "In a PR context comparing to pull_request.base.ref"
 47            git fetch origin "$GITHUB_BASE_REF" --depth=350
 48            COMPARE_REV=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD)
 49          fi
 50          if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -v "^docs/") ]]; then
 51            echo "run_tests=true" >> $GITHUB_OUTPUT
 52          else
 53            echo "run_tests=false" >> $GITHUB_OUTPUT
 54          fi
 55          if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^Cargo.lock') ]]; then
 56            echo "run_license=true" >> $GITHUB_OUTPUT
 57          else
 58            echo "run_license=false" >> $GITHUB_OUTPUT
 59          fi
 60
 61  migration_checks:
 62    name: Check Postgres and Protobuf migrations, mergability
 63    needs: [job_spec]
 64    if: |
 65      github.repository_owner == 'zed-industries' &&
 66      needs.job_spec.outputs.run_tests == 'true'
 67    timeout-minutes: 60
 68    runs-on:
 69      - self-hosted
 70      - test
 71    steps:
 72      - name: Checkout repo
 73        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 74        with:
 75          clean: false
 76          fetch-depth: 0 # fetch full history
 77
 78      - name: Remove untracked files
 79        run: git clean -df
 80
 81      - name: Find modified migrations
 82        shell: bash -euxo pipefail {0}
 83        run: |
 84          export SQUAWK_GITHUB_TOKEN=${{ github.token }}
 85          . ./script/squawk
 86
 87      - name: Ensure fresh merge
 88        shell: bash -euxo pipefail {0}
 89        run: |
 90          if [ -z "$GITHUB_BASE_REF" ];
 91          then
 92            echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV
 93          else
 94            git checkout -B temp
 95            git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp"
 96            echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
 97          fi
 98
 99      - uses: bufbuild/buf-setup-action@v1
100        with:
101          version: v1.29.0
102      - uses: bufbuild/buf-breaking-action@v1
103        with:
104          input: "crates/proto/proto/"
105          against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=${BUF_BASE_BRANCH},subdir=crates/proto/proto/"
106
107  style:
108    timeout-minutes: 60
109    name: Check formatting and spelling
110    needs: [job_spec]
111    if: github.repository_owner == 'zed-industries'
112    runs-on:
113      - buildjet-8vcpu-ubuntu-2204
114    steps:
115      - name: Checkout repo
116        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
117
118      - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
119        with:
120          version: 9
121
122      - name: Prettier Check on /docs
123        working-directory: ./docs
124        run: |
125          pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
126            echo "To fix, run from the root of the zed repo:"
127            echo "  cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
128            false
129          }
130        env:
131          PRETTIER_VERSION: 3.5.0
132
133      # To support writing comments that they will certainly be revisited.
134      - name: Check for todo! and FIXME comments
135        run: script/check-todos
136
137      - name: Run style checks
138        uses: ./.github/actions/check_style
139
140      - name: Check for typos
141        uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
142        with:
143          config: ./typos.toml
144
145  macos_tests:
146    timeout-minutes: 60
147    name: (macOS) Run Clippy and tests
148    needs: [job_spec]
149    if: |
150      github.repository_owner == 'zed-industries' &&
151      needs.job_spec.outputs.run_tests == 'true'
152    runs-on:
153      - self-hosted
154      - test
155    steps:
156      - name: Checkout repo
157        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
158        with:
159          clean: false
160
161      - name: Configure CI
162        run: |
163          mkdir -p ./../.cargo
164          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
165
166      - name: cargo clippy
167        run: ./script/clippy
168
169      - name: Install cargo-machete
170        uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386 # v2
171        with:
172          command: install
173          args: cargo-machete@0.7.0
174
175      - name: Check unused dependencies
176        uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386 # v2
177        with:
178          command: machete
179
180      - name: Check licenses
181        run: |
182          script/check-licenses
183          if [[ "${{ needs.job_spec.outputs.run_license }}" == "true" ]]; then
184            script/generate-licenses /tmp/zed_licenses_output
185          fi
186
187      - name: Check for new vulnerable dependencies
188        if: github.event_name == 'pull_request'
189        uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4
190        with:
191          license-check: false
192
193      - name: Run tests
194        uses: ./.github/actions/run_tests
195
196      - name: Build collab
197        run: cargo build -p collab
198
199      - name: Build other binaries and features
200        run: |
201          cargo build --workspace --bins --all-features
202          cargo check -p gpui --features "macos-blade"
203          cargo check -p workspace
204          cargo build -p remote_server
205          cargo check -p gpui --examples
206          script/check-rust-livekit-macos
207
208      # Since the macOS runners are stateful, so we need to remove the config file to prevent potential bug.
209      - name: Clean CI config file
210        if: always()
211        run: rm -rf ./../.cargo
212
213  linux_tests:
214    timeout-minutes: 60
215    name: (Linux) Run Clippy and tests
216    needs: [job_spec]
217    if: |
218      github.repository_owner == 'zed-industries' &&
219      needs.job_spec.outputs.run_tests == 'true'
220    runs-on:
221      - buildjet-16vcpu-ubuntu-2204
222    steps:
223      - name: Add Rust to the PATH
224        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
225
226      - name: Checkout repo
227        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
228        with:
229          clean: false
230
231      - name: Cache dependencies
232        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
233        with:
234          save-if: ${{ github.ref == 'refs/heads/main' }}
235          cache-provider: "buildjet"
236
237      - name: Install Linux dependencies
238        run: ./script/linux
239
240      - name: Configure CI
241        run: |
242          mkdir -p ./../.cargo
243          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
244
245      - name: cargo clippy
246        run: ./script/clippy
247
248      - name: Run tests
249        uses: ./.github/actions/run_tests
250
251      - name: Build other binaries and features
252        run: |
253          cargo build -p zed
254          cargo check -p workspace
255          cargo check -p gpui --examples
256
257      # Even the Linux runner is not stateful, in theory there is no need to do this cleanup.
258      # But, to avoid potential issues in the future if we choose to use a stateful Linux runner and forget to add code
259      # to clean up the config file, I’ve included the cleanup code here as a precaution.
260      # While it’s not strictly necessary at this moment, I believe it’s better to err on the side of caution.
261      - name: Clean CI config file
262        if: always()
263        run: rm -rf ./../.cargo
264
265  build_remote_server:
266    timeout-minutes: 60
267    name: (Linux) Build Remote Server
268    needs: [job_spec]
269    if: |
270      github.repository_owner == 'zed-industries' &&
271      needs.job_spec.outputs.run_tests == 'true'
272    runs-on:
273      - buildjet-8vcpu-ubuntu-2204
274    steps:
275      - name: Add Rust to the PATH
276        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
277
278      - name: Checkout repo
279        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
280        with:
281          clean: false
282
283      - name: Cache dependencies
284        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
285        with:
286          save-if: ${{ github.ref == 'refs/heads/main' }}
287          cache-provider: "buildjet"
288
289      - name: Install Clang & Mold
290        run: ./script/remote-server && ./script/install-mold 2.34.0
291
292      - name: Configure CI
293        run: |
294          mkdir -p ./../.cargo
295          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
296
297      - name: Build Remote Server
298        run: cargo build -p remote_server
299
300      - name: Clean CI config file
301        if: always()
302        run: rm -rf ./../.cargo
303
304  windows_clippy:
305    timeout-minutes: 60
306    name: (Windows) Run Clippy
307    needs: [job_spec]
308    if: |
309      github.repository_owner == 'zed-industries' &&
310      needs.job_spec.outputs.run_tests == 'true'
311    runs-on: windows-2025-16
312    steps:
313      # more info here:- https://github.com/rust-lang/cargo/issues/13020
314      - name: Enable longer pathnames for git
315        run: git config --system core.longpaths true
316
317      - name: Checkout repo
318        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
319        with:
320          clean: false
321
322      - name: Create Dev Drive using ReFS
323        run: ./script/setup-dev-driver.ps1
324
325      # actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
326      - name: Copy Git Repo to Dev Drive
327        run: |
328          Copy-Item -Path "${{ github.workspace }}" -Destination "${{ env.ZED_WORKSPACE }}" -Recurse
329
330      - name: Cache dependencies
331        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
332        with:
333          save-if: ${{ github.ref == 'refs/heads/main' }}
334          workspaces: ${{ env.ZED_WORKSPACE }}
335          cache-provider: "github"
336
337      - name: Configure CI
338        run: |
339          mkdir -p ${{ env.CARGO_HOME }} -ErrorAction Ignore
340          cp ./.cargo/ci-config.toml ${{ env.CARGO_HOME }}/config.toml
341
342      - name: cargo clippy
343        working-directory: ${{ env.ZED_WORKSPACE }}
344        run: ./script/clippy.ps1
345
346      - name: Check dev drive space
347        working-directory: ${{ env.ZED_WORKSPACE }}
348        # `setup-dev-driver.ps1` creates a 100GB drive, with CI taking up ~45GB of the drive.
349        run: ./script/exit-ci-if-dev-drive-is-full.ps1 95
350
351      # Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
352      - name: Clean CI config file
353        if: always()
354        run: |
355          if (Test-Path "${{ env.CARGO_HOME }}/config.toml") {
356            Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml"  -Force
357          }
358
359  # Windows CI takes twice as long as our other platforms and fast github hosted runners are expensive.
360  # But we still want to do CI, so let's only run tests on main and come back to this when we're
361  # ready to self host our Windows CI (e.g. during the push for full Windows support)
362  windows_tests:
363    timeout-minutes: 60
364    name: (Windows) Run Tests
365    needs: [job_spec]
366    if: |
367      github.repository_owner == 'zed-industries' &&
368      needs.job_spec.outputs.run_tests == 'true'
369    # Use bigger runners for PRs (speed); smaller for async (cost)
370    runs-on: ${{ github.event_name == 'pull_request' && 'windows-2025-32' || 'windows-2025-16' }}
371    steps:
372      # more info here:- https://github.com/rust-lang/cargo/issues/13020
373      - name: Enable longer pathnames for git
374        run: git config --system core.longpaths true
375
376      - name: Checkout repo
377        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
378        with:
379          clean: false
380
381      - name: Create Dev Drive using ReFS
382        run: ./script/setup-dev-driver.ps1
383
384      # actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
385      - name: Copy Git Repo to Dev Drive
386        run: |
387          Copy-Item -Path "${{ github.workspace }}" -Destination "${{ env.ZED_WORKSPACE }}" -Recurse
388
389      - name: Cache dependencies
390        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
391        with:
392          save-if: ${{ github.ref == 'refs/heads/main' }}
393          workspaces: ${{ env.ZED_WORKSPACE }}
394          cache-provider: "github"
395
396      - name: Configure CI
397        run: |
398          mkdir -p ${{ env.CARGO_HOME }} -ErrorAction Ignore
399          cp ./.cargo/ci-config.toml ${{ env.CARGO_HOME }}/config.toml
400
401      - name: Run tests
402        uses: ./.github/actions/run_tests_windows
403        with:
404          working-directory: ${{ env.ZED_WORKSPACE }}
405
406      - name: Build Zed
407        working-directory: ${{ env.ZED_WORKSPACE }}
408        run: cargo build
409
410      - name: Check dev drive space
411        working-directory: ${{ env.ZED_WORKSPACE }}
412        # `setup-dev-driver.ps1` creates a 100GB drive, with CI taking up ~45GB of the drive.
413        run: ./script/exit-ci-if-dev-drive-is-full.ps1 95
414
415      # Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
416      - name: Clean CI config file
417        if: always()
418        run: |
419          if (Test-Path "${{ env.CARGO_HOME }}/config.toml") {
420            Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml"  -Force
421          }
422
423  tests_pass:
424    name: Tests Pass
425    runs-on: ubuntu-latest
426    needs:
427      - job_spec
428      - style
429      - migration_checks
430      - linux_tests
431      - build_remote_server
432      - macos_tests
433      - windows_clippy
434      - windows_tests
435    if: always()
436    steps:
437      - name: Check all tests passed
438        run: |
439          # Check dependent jobs...
440          RET_CODE=0
441          # Always check style
442          [[ "${{ needs.style.result }}" != 'success' ]] && { RET_CODE=1; echo "style tests failed"; }
443
444          # Only check test jobs if they were supposed to run
445          if [[ "${{ needs.job_spec.outputs.run_tests }}" == "true" ]]; then
446            [[ "${{ needs.macos_tests.result }}"          != 'success' ]] && { RET_CODE=1; echo "macOS tests failed"; }
447            [[ "${{ needs.linux_tests.result }}"          != 'success' ]] && { RET_CODE=1; echo "Linux tests failed"; }
448            [[ "${{ needs.windows_tests.result }}"        != 'success' ]] && { RET_CODE=1; echo "Windows tests failed"; }
449            [[ "${{ needs.windows_clippy.result }}"       != 'success' ]] && { RET_CODE=1; echo "Windows clippy failed"; }
450            [[ "${{ needs.migration_checks.result }}"     != 'success' ]] && { RET_CODE=1; echo "Migration checks failed"; }
451            [[ "${{ needs.build_remote_server.result }}"  != 'success' ]] && { RET_CODE=1; echo "Remote server build failed"; }
452          fi
453          if [[ "$RET_CODE" -eq 0 ]]; then
454            echo "All tests passed successfully!"
455          fi
456          exit $RET_CODE
457
458  bundle-mac:
459    timeout-minutes: 120
460    name: Create a macOS bundle
461    runs-on:
462      - self-hosted
463      - bundle
464    if: |
465      startsWith(github.ref, 'refs/tags/v')
466      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
467    needs: [macos_tests]
468    env:
469      MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
470      MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
471      APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
472      APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
473      APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
474      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
475      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
476      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
477      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
478    steps:
479      - name: Install Node
480        uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
481        with:
482          node-version: "18"
483
484      - name: Checkout repo
485        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
486        with:
487          # We need to fetch more than one commit so that `script/draft-release-notes`
488          # is able to diff between the current and previous tag.
489          #
490          # 25 was chosen arbitrarily.
491          fetch-depth: 25
492          clean: false
493          ref: ${{ github.ref }}
494
495      - name: Limit target directory size
496        run: script/clear-target-dir-if-larger-than 100
497
498      - name: Determine version and release channel
499        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
500        run: |
501          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
502          script/determine-release-channel
503
504      - name: Draft release notes
505        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
506        run: |
507          mkdir -p target/
508          # Ignore any errors that occur while drafting release notes to not fail the build.
509          script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md || true
510          script/create-draft-release target/release-notes.md
511        env:
512          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
513
514      - name: Create macOS app bundle
515        run: script/bundle-mac
516
517      - name: Rename binaries
518        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
519        run: |
520          mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
521          mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
522
523      - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
524        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
525        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
526        with:
527          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
528          path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
529
530      - name: Upload app bundle (x86_64) to workflow run if main branch or specific label
531        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
532        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
533        with:
534          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
535          path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
536
537      - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
538        name: Upload app bundle to release
539        if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
540        with:
541          draft: true
542          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
543          files: |
544            target/zed-remote-server-macos-x86_64.gz
545            target/zed-remote-server-macos-aarch64.gz
546            target/aarch64-apple-darwin/release/Zed-aarch64.dmg
547            target/x86_64-apple-darwin/release/Zed-x86_64.dmg
548        env:
549          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
550
551  bundle-linux-x86_x64:
552    timeout-minutes: 60
553    name: Linux x86_x64 release bundle
554    runs-on:
555      - buildjet-16vcpu-ubuntu-2004
556    if: |
557      startsWith(github.ref, 'refs/tags/v')
558      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
559    needs: [linux_tests]
560    env:
561      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
562      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
563      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
564      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
565    steps:
566      - name: Checkout repo
567        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
568        with:
569          clean: false
570
571      - name: Install Linux dependencies
572        run: ./script/linux && ./script/install-mold 2.34.0
573
574      - name: Determine version and release channel
575        if: startsWith(github.ref, 'refs/tags/v')
576        run: |
577          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
578          script/determine-release-channel
579
580      - name: Create Linux .tar.gz bundle
581        run: script/bundle-linux
582
583      - name: Upload Linux bundle to workflow run if main branch or specific label
584        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
585        if: |
586          github.ref == 'refs/heads/main'
587          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
588        with:
589          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
590          path: target/release/zed-*.tar.gz
591
592      - name: Upload Linux remote server to workflow run if main branch or specific label
593        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
594        if: |
595          github.ref == 'refs/heads/main'
596          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
597        with:
598          name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.gz
599          path: target/zed-remote-server-linux-x86_64.gz
600
601      - name: Upload app bundle to release
602        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
603        with:
604          draft: true
605          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
606          files: |
607            target/zed-remote-server-linux-x86_64.gz
608            target/release/zed-linux-x86_64.tar.gz
609        env:
610          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
611
612  bundle-linux-aarch64: # this runs on ubuntu22.04
613    timeout-minutes: 60
614    name: Linux arm64 release bundle
615    runs-on:
616      - buildjet-16vcpu-ubuntu-2204-arm
617    if: |
618      startsWith(github.ref, 'refs/tags/v')
619      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
620    needs: [linux_tests]
621    env:
622      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
623      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
624      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
625      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
626    steps:
627      - name: Checkout repo
628        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
629        with:
630          clean: false
631
632      - name: Install Linux dependencies
633        run: ./script/linux
634
635      - name: Determine version and release channel
636        if: startsWith(github.ref, 'refs/tags/v')
637        run: |
638          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
639          script/determine-release-channel
640
641      - name: Create and upload Linux .tar.gz bundle
642        run: script/bundle-linux
643
644      - name: Upload Linux bundle to workflow run if main branch or specific label
645        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
646        if: |
647          github.ref == 'refs/heads/main'
648          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
649        with:
650          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
651          path: target/release/zed-*.tar.gz
652
653      - name: Upload Linux remote server to workflow run if main branch or specific label
654        uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
655        if: |
656          github.ref == 'refs/heads/main'
657          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
658        with:
659          name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.gz
660          path: target/zed-remote-server-linux-aarch64.gz
661
662      - name: Upload app bundle to release
663        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
664        with:
665          draft: true
666          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
667          files: |
668            target/zed-remote-server-linux-aarch64.gz
669            target/release/zed-linux-aarch64.tar.gz
670        env:
671          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
672
673  auto-release-preview:
674    name: Auto release preview
675    if: |
676      startsWith(github.ref, 'refs/tags/v')
677      && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre')
678    needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64]
679    runs-on:
680      - self-hosted
681      - bundle
682    steps:
683      - name: gh release
684        run: gh release edit $GITHUB_REF_NAME --draft=true
685        env:
686          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}