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