ci.yml

  1name: CI
  2
  3on:
  4  push:
  5    branches:
  6      - main
  7      - "v[0-9]+.[0-9]+.x"
  8    tags:
  9      - "v*"
 10  pull_request:
 11    branches:
 12      - "**"
 13  merge_group:
 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  RUSTFLAGS: "-D warnings"
 25
 26jobs:
 27  check_docs_only:
 28    runs-on: ubuntu-latest
 29    outputs:
 30      docs_only: ${{ steps.check_changes.outputs.docs_only }}
 31    steps:
 32      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 33        with:
 34          fetch-depth: 0
 35      - name: Check for non-docs changes
 36        id: check_changes
 37        run: |
 38          if [ "${{ github.event_name }}" == "merge_group" ]; then
 39            # When we're running in a merge queue, never assume that the changes
 40            # are docs-only, as there could be other PRs in the group that
 41            # contain non-docs changes.
 42            echo "docs_only=false" >> $GITHUB_OUTPUT
 43          elif git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -qvE '^docs/'; then
 44            echo "docs_only=false" >> $GITHUB_OUTPUT
 45          else
 46            echo "docs_only=true" >> $GITHUB_OUTPUT
 47          fi
 48
 49  migration_checks:
 50    name: Check Postgres and Protobuf migrations, mergability
 51    if: github.repository_owner == 'zed-industries'
 52    timeout-minutes: 60
 53    runs-on:
 54      - self-hosted
 55      - test
 56    steps:
 57      - name: Checkout repo
 58        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 59        with:
 60          clean: false
 61          fetch-depth: 0 # fetch full history
 62
 63      - name: Remove untracked files
 64        run: git clean -df
 65
 66      - name: Find modified migrations
 67        shell: bash -euxo pipefail {0}
 68        run: |
 69          export SQUAWK_GITHUB_TOKEN=${{ github.token }}
 70          . ./script/squawk
 71
 72      - name: Ensure fresh merge
 73        shell: bash -euxo pipefail {0}
 74        run: |
 75          if [ -z "$GITHUB_BASE_REF" ];
 76          then
 77            echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV
 78          else
 79            git checkout -B temp
 80            git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp"
 81            echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
 82          fi
 83
 84      - uses: bufbuild/buf-setup-action@v1
 85        with:
 86          version: v1.29.0
 87      - uses: bufbuild/buf-breaking-action@v1
 88        with:
 89          input: "crates/proto/proto/"
 90          against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=${BUF_BASE_BRANCH},subdir=crates/proto/proto/"
 91
 92  style:
 93    timeout-minutes: 60
 94    name: Check formatting and spelling
 95    if: github.repository_owner == 'zed-industries'
 96    runs-on:
 97      - buildjet-8vcpu-ubuntu-2204
 98    steps:
 99      - name: Checkout repo
100        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
101
102      # To support writing comments that they will certainly be revisited.
103      - name: Check for todo​! and FIX​ME comments
104        run: script/check-todos
105
106      - name: Run style checks
107        uses: ./.github/actions/check_style
108
109      - name: Check for typos
110        uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
111        with:
112          config: ./typos.toml
113
114  macos_tests:
115    timeout-minutes: 60
116    name: (macOS) Run Clippy and tests
117    if: github.repository_owner == 'zed-industries'
118    runs-on:
119      - self-hosted
120      - test
121    needs: check_docs_only
122    steps:
123      - name: Checkout repo
124        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
125        with:
126          clean: false
127
128      - name: cargo clippy
129        if: needs.check_docs_only.outputs.docs_only == 'false'
130        run: ./script/clippy
131
132      - name: Check unused dependencies
133        if: needs.check_docs_only.outputs.docs_only == 'false'
134        uses: bnjbvr/cargo-machete@main
135
136      - name: Check licenses
137        if: needs.check_docs_only.outputs.docs_only == 'false'
138        run: |
139          script/check-licenses
140          script/generate-licenses /tmp/zed_licenses_output
141
142      - name: Check for new vulnerable dependencies
143        if: github.event_name == 'pull_request' && needs.check_docs_only.outputs.docs_only == 'false'
144        uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4
145        with:
146          license-check: false
147
148      - name: Run tests
149        if: needs.check_docs_only.outputs.docs_only == 'false'
150        uses: ./.github/actions/run_tests
151
152      - name: Build collab
153        if: needs.check_docs_only.outputs.docs_only == 'false'
154        run: cargo build -p collab
155
156      - name: Build other binaries and features
157        if: needs.check_docs_only.outputs.docs_only == 'false'
158        run: |
159          cargo build --workspace --bins --all-features
160          cargo check -p gpui --features "macos-blade"
161          cargo check -p workspace
162          cargo build -p remote_server
163          script/check-rust-livekit-macos
164
165  linux_tests:
166    timeout-minutes: 60
167    name: (Linux) Run Clippy and tests
168    if: github.repository_owner == 'zed-industries'
169    runs-on:
170      - buildjet-16vcpu-ubuntu-2204
171    needs: check_docs_only
172    steps:
173      - name: Add Rust to the PATH
174        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
175
176      - name: Checkout repo
177        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
178        with:
179          clean: false
180
181      - name: Cache dependencies
182        if: needs.check_docs_only.outputs.docs_only == 'false'
183        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
184        with:
185          save-if: ${{ github.ref == 'refs/heads/main' }}
186          cache-provider: "buildjet"
187
188      - name: Install Linux dependencies
189        if: needs.check_docs_only.outputs.docs_only == 'false'
190        run: ./script/linux
191
192      - name: cargo clippy
193        if: needs.check_docs_only.outputs.docs_only == 'false'
194        run: ./script/clippy
195
196      - name: Run tests
197        if: needs.check_docs_only.outputs.docs_only == 'false'
198        uses: ./.github/actions/run_tests
199
200      - name: Build other binaries and features
201        if: needs.check_docs_only.outputs.docs_only == 'false'
202        run: |
203          cargo build -p zed
204          cargo check -p workspace
205
206  build_remote_server:
207    timeout-minutes: 60
208    name: (Linux) Build Remote Server
209    if: github.repository_owner == 'zed-industries'
210    runs-on:
211      - buildjet-16vcpu-ubuntu-2204
212    needs: check_docs_only
213    steps:
214      - name: Add Rust to the PATH
215        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
216
217      - name: Checkout repo
218        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
219        with:
220          clean: false
221
222      - name: Cache dependencies
223        if: needs.check_docs_only.outputs.docs_only == 'false'
224        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
225        with:
226          save-if: ${{ github.ref == 'refs/heads/main' }}
227          cache-provider: "buildjet"
228
229      - name: Install Clang & Mold
230        if: needs.check_docs_only.outputs.docs_only == 'false'
231        run: ./script/remote-server && ./script/install-mold 2.34.0
232
233      - name: Build Remote Server
234        if: needs.check_docs_only.outputs.docs_only == 'false'
235        run: cargo build -p remote_server
236
237  # todo(windows): Actually run the tests
238  windows_tests:
239    timeout-minutes: 60
240    name: (Windows) Run Clippy and tests
241    if: github.repository_owner == 'zed-industries'
242    runs-on: hosted-windows-1
243    needs: check_docs_only
244    steps:
245      # more info here:- https://github.com/rust-lang/cargo/issues/13020
246      - name: Enable longer pathnames for git
247        run: git config --system core.longpaths true
248      - name: Checkout repo
249        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
250        with:
251          clean: false
252
253      - name: Cache dependencies
254        if: needs.check_docs_only.outputs.docs_only == 'false'
255        uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
256        with:
257          save-if: ${{ github.ref == 'refs/heads/main' }}
258          cache-provider: "github"
259
260      - name: cargo clippy
261        if: needs.check_docs_only.outputs.docs_only == 'false'
262        # Windows can't run shell scripts, so we need to use `cargo xtask`.
263        run: cargo xtask clippy
264
265      - name: Build Zed
266        if: needs.check_docs_only.outputs.docs_only == 'false'
267        run: cargo build
268
269  bundle-mac:
270    timeout-minutes: 60
271    name: Create a macOS bundle
272    runs-on:
273      - self-hosted
274      - bundle
275    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
276    needs: [macos_tests]
277    env:
278      MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
279      MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
280      APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
281      APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
282      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
283      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
284      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
285      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
286    steps:
287      - name: Install Node
288        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
289        with:
290          node-version: "18"
291
292      - name: Checkout repo
293        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
294        with:
295          # We need to fetch more than one commit so that `script/draft-release-notes`
296          # is able to diff between the current and previous tag.
297          #
298          # 25 was chosen arbitrarily.
299          fetch-depth: 25
300          clean: false
301          ref: ${{ github.ref }}
302
303      - name: Limit target directory size
304        run: script/clear-target-dir-if-larger-than 100
305
306      - name: Determine version and release channel
307        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
308        run: |
309          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
310          script/determine-release-channel
311
312      - name: Draft release notes
313        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
314        run: |
315          mkdir -p target/
316          # Ignore any errors that occur while drafting release notes to not fail the build.
317          script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md || true
318          script/create-draft-release target/release-notes.md
319        env:
320          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
321
322      - name: Generate license file
323        run: script/generate-licenses
324
325      - name: Create macOS app bundle
326        run: script/bundle-mac
327
328      - name: Rename binaries
329        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
330        run: |
331          mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
332          mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
333
334      - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
335        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
336        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
337        with:
338          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
339          path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
340
341      - name: Upload app bundle (x86_64) to workflow run if main branch or specific label
342        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
343        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
344        with:
345          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
346          path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
347
348      - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
349        name: Upload app bundle to release
350        if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
351        with:
352          draft: true
353          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
354          files: |
355            target/zed-remote-server-macos-x86_64.gz
356            target/zed-remote-server-macos-aarch64.gz
357            target/aarch64-apple-darwin/release/Zed-aarch64.dmg
358            target/x86_64-apple-darwin/release/Zed-x86_64.dmg
359        env:
360          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
361
362  bundle-linux:
363    timeout-minutes: 60
364    name: Create a Linux bundle
365    runs-on:
366      - buildjet-16vcpu-ubuntu-2004
367    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
368    needs: [linux_tests]
369    env:
370      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
371      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
372      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
373      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
374    steps:
375      - name: Checkout repo
376        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
377        with:
378          clean: false
379
380      - name: Install Linux dependencies
381        run: ./script/linux && ./script/install-mold 2.34.0
382
383      - name: Determine version and release channel
384        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
385        run: |
386          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
387          script/determine-release-channel
388
389      - name: Create Linux .tar.gz bundle
390        run: script/bundle-linux
391
392      - name: Upload Linux bundle to workflow run if main branch or specific label
393        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
394        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
395        with:
396          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
397          path: target/release/zed-*.tar.gz
398
399      - name: Upload app bundle to release
400        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
401        with:
402          draft: true
403          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
404          files: |
405            target/zed-remote-server-linux-x86_64.gz
406            target/release/zed-linux-x86_64.tar.gz
407        env:
408          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
409
410  bundle-linux-aarch64: # this runs on ubuntu22.04
411    timeout-minutes: 60
412    name: Create arm64 Linux bundle
413    runs-on:
414      - buildjet-16vcpu-ubuntu-2204-arm
415    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
416    needs: [linux_tests]
417    env:
418      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
419      ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
420      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
421      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
422    steps:
423      - name: Checkout repo
424        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
425        with:
426          clean: false
427
428      - name: Install Linux dependencies
429        run: ./script/linux
430
431      - name: Determine version and release channel
432        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
433        run: |
434          # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
435          script/determine-release-channel
436
437      - name: Create and upload Linux .tar.gz bundle
438        run: script/bundle-linux
439
440      - name: Upload Linux bundle to workflow run if main branch or specific label
441        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
442        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
443        with:
444          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
445          path: target/release/zed-*.tar.gz
446
447      - name: Upload app bundle to release
448        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
449        with:
450          draft: true
451          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
452          files: |
453            target/zed-remote-server-linux-aarch64.gz
454            target/release/zed-linux-aarch64.tar.gz
455        env:
456          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
457
458  auto-release-preview:
459    name: Auto release preview
460    if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') }}
461    needs: [bundle-mac, bundle-linux, bundle-linux-aarch64]
462    runs-on:
463      - self-hosted
464      - bundle
465    steps:
466      - name: gh release
467        run: gh release edit $GITHUB_REF_NAME --draft=false
468        env:
469          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}