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