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  style:
 26    timeout-minutes: 60
 27    name: Check formatting and spelling
 28    runs-on:
 29      - self-hosted
 30      - test
 31    steps:
 32      - name: Checkout repo
 33        uses: actions/checkout@v4
 34        with:
 35          clean: false
 36          fetch-depth: 0
 37
 38      - name: Remove untracked files
 39        run: git clean -df
 40
 41      - name: Set up default .cargo/config.toml
 42        run: cp ./.cargo/ci-config.toml ~/.cargo/config.toml
 43
 44      - name: Check spelling
 45        run: |
 46          if ! which typos > /dev/null; then
 47            cargo install typos-cli
 48          fi
 49          typos
 50
 51      - name: Run style checks
 52        uses: ./.github/actions/check_style
 53
 54      - name: Check unused dependencies
 55        uses: bnjbvr/cargo-machete@main
 56
 57      - name: Check license generation
 58        run: script/generate-licenses /tmp/zed_licenses_output
 59
 60      - name: Ensure fresh merge
 61        shell: bash -euxo pipefail {0}
 62        run: |
 63          if [ -z "$GITHUB_BASE_REF" ];
 64          then
 65            echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV
 66          else
 67            git checkout -B temp
 68            git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp"
 69            echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
 70          fi
 71
 72      - uses: bufbuild/buf-setup-action@v1
 73        with:
 74          version: v1.29.0
 75      - uses: bufbuild/buf-breaking-action@v1
 76        with:
 77          input: "crates/proto/proto/"
 78          against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=${BUF_BASE_BRANCH},subdir=crates/proto/proto/"
 79
 80  macos_tests:
 81    timeout-minutes: 60
 82    name: (macOS) Run Clippy and tests
 83    runs-on:
 84      - self-hosted
 85      - test
 86    steps:
 87      - name: Checkout repo
 88        uses: actions/checkout@v4
 89        with:
 90          clean: false
 91
 92      - name: cargo clippy
 93        run: cargo xtask clippy
 94
 95      - name: Run tests
 96        uses: ./.github/actions/run_tests
 97
 98      - name: Build collab
 99        run: cargo build -p collab
100
101      - name: Build other binaries and features
102        run: cargo build --workspace --bins --all-features; cargo check -p gpui --features "macos-blade"
103
104  # todo(linux): Actually run the tests
105  linux_tests:
106    timeout-minutes: 60
107    name: (Linux) Run Clippy and tests
108    runs-on:
109      - self-hosted
110      - deploy
111    steps:
112      - name: Add Rust to the PATH
113        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
114
115      - name: Checkout repo
116        uses: actions/checkout@v4
117        with:
118          clean: false
119
120      - name: cargo clippy
121        run: cargo xtask clippy
122
123      - name: Build Zed
124        run: cargo build -p zed
125
126  # todo(windows): Actually run the tests
127  windows_tests:
128    timeout-minutes: 60
129    name: (Windows) Run Clippy and tests
130    runs-on: hosted-windows-1
131    steps:
132      - name: Checkout repo
133        uses: actions/checkout@v4
134        with:
135          clean: false
136
137      - name: Cache dependencies
138        uses: swatinem/rust-cache@v2
139        with:
140          save-if: ${{ github.ref == 'refs/heads/main' }}
141
142      - name: cargo clippy
143        run: cargo xtask clippy
144
145      - name: Build Zed
146        run: cargo build -p zed
147
148  bundle-mac:
149    timeout-minutes: 60
150    name: Create a macOS bundle
151    runs-on:
152      - self-hosted
153      - bundle
154    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
155    needs: [macos_tests]
156    env:
157      MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
158      MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
159      APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
160      APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
161      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
162      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
163      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
164    steps:
165      - name: Install Node
166        uses: actions/setup-node@v4
167        with:
168          node-version: "18"
169
170      - name: Checkout repo
171        uses: actions/checkout@v4
172        with:
173          # We need to fetch more than one commit so that `script/draft-release-notes`
174          # is able to diff between the current and previous tag.
175          #
176          # 25 was chosen arbitrarily.
177          fetch-depth: 25
178          clean: false
179
180      - name: Limit target directory size
181        run: script/clear-target-dir-if-larger-than 100
182
183      - name: Determine version and release channel
184        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
185        run: |
186          set -eu
187
188          version=$(script/get-crate-version zed)
189          channel=$(cat crates/zed/RELEASE_CHANNEL)
190          echo "Publishing version: ${version} on release channel ${channel}"
191          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
192
193          expected_tag_name=""
194          case ${channel} in
195            stable)
196              expected_tag_name="v${version}";;
197            preview)
198              expected_tag_name="v${version}-pre";;
199            nightly)
200              expected_tag_name="v${version}-nightly";;
201            *)
202              echo "can't publish a release on channel ${channel}"
203              exit 1;;
204          esac
205          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
206            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
207            exit 1
208          fi
209          mkdir -p target/
210          # Ignore any errors that occur while drafting release notes to not fail the build.
211          script/draft-release-notes "$version" "$channel" > target/release-notes.md || true
212
213      - name: Generate license file
214        run: script/generate-licenses
215
216      - name: Create macOS app bundle
217        run: script/bundle-mac
218
219      - name: Rename single-architecture binaries
220        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
221        run: |
222          mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
223          mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
224
225      - name: Upload app bundle (universal) to workflow run if main branch or specific label
226        uses: actions/upload-artifact@v4
227        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
228        with:
229          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
230          path: target/release/Zed.dmg
231      - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
232        uses: actions/upload-artifact@v4
233        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
234        with:
235          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
236          path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
237
238      - name: Upload app bundle (x86_64) to workflow run if main branch or specific label
239        uses: actions/upload-artifact@v4
240        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
241        with:
242          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
243          path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
244
245      - uses: softprops/action-gh-release@v1
246        name: Upload app bundle to release
247        if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
248        with:
249          draft: true
250          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
251          files: |
252            target/aarch64-apple-darwin/release/Zed-aarch64.dmg
253            target/x86_64-apple-darwin/release/Zed-x86_64.dmg
254            target/release/Zed.dmg
255          body_file: target/release-notes.md
256        env:
257          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
258
259  bundle-linux:
260    timeout-minutes: 60
261    name: Create a Linux bundle
262    runs-on:
263      - self-hosted
264      - deploy
265    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
266    needs: [linux_tests]
267    env:
268      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
269    steps:
270      - name: Add Rust to the PATH
271        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
272
273      - name: Checkout repo
274        uses: actions/checkout@v4
275        with:
276          clean: false
277
278      - name: Limit target directory size
279        run: script/clear-target-dir-if-larger-than 100
280
281      - name: Determine version and release channel
282        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
283        run: |
284          set -eu
285
286          version=$(script/get-crate-version zed)
287          channel=$(cat crates/zed/RELEASE_CHANNEL)
288          echo "Publishing version: ${version} on release channel ${channel}"
289          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
290
291          expected_tag_name=""
292          case ${channel} in
293            stable)
294              expected_tag_name="v${version}";;
295            preview)
296              expected_tag_name="v${version}-pre";;
297            nightly)
298              expected_tag_name="v${version}-nightly";;
299            *)
300              echo "can't publish a release on channel ${channel}"
301              exit 1;;
302          esac
303          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
304            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
305            exit 1
306          fi
307
308      - name: Create and upload Linux .tar.gz bundle
309        run: script/bundle-linux
310
311      - name: Upload Linux bundle to workflow run if main branch or specific label
312        uses: actions/upload-artifact@v4
313        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
314        with:
315          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
316          path: zed-*.tar.gz
317
318      - name: Upload app bundle to release
319        uses: softprops/action-gh-release@v1
320        if: ${{ env.RELEASE_CHANNEL == 'preview' }}
321        with:
322          draft: true
323          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
324          files: target/release/zed-linux-x86_64.tar.gz
325          body: ""
326        env:
327          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
328
329  bundle-linux-aarch64:
330    timeout-minutes: 60
331    name: Create arm64 Linux bundle
332    runs-on:
333      - hosted-linux-arm-1
334    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
335    needs: [linux_tests]
336    env:
337      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
338    steps:
339      - name: Checkout repo
340        uses: actions/checkout@v4
341        with:
342          clean: false
343      - name: "Setup jq"
344        uses: dcarbone/install-jq-action@v2
345
346      - name: Set up Clang
347        run: |
348          sudo apt-get update
349          sudo apt-get install -y llvm-10 clang-10 build-essential cmake pkg-config libasound2-dev libfontconfig-dev libwayland-dev libxkbcommon-x11-dev libssl-dev libzstd-dev libvulkan1 libgit2-dev
350          echo "/usr/lib/llvm-10/bin" >> $GITHUB_PATH
351
352      - uses: rui314/setup-mold@v1
353        with:
354          mold_version: 2.32.0
355
356      - name: rustup
357        run: |
358          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
359          echo "$HOME/.cargo/bin" >> $GITHUB_PATH
360
361      - name: Limit target directory size
362        run: script/clear-target-dir-if-larger-than 100
363
364      - name: Determine version and release channel
365        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
366        run: |
367          set -eu
368
369          version=$(script/get-crate-version zed)
370          channel=$(cat crates/zed/RELEASE_CHANNEL)
371          echo "Publishing version: ${version} on release channel ${channel}"
372          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
373
374          expected_tag_name=""
375          case ${channel} in
376            stable)
377              expected_tag_name="v${version}";;
378            preview)
379              expected_tag_name="v${version}-pre";;
380            nightly)
381              expected_tag_name="v${version}-nightly";;
382            *)
383              echo "can't publish a release on channel ${channel}"
384              exit 1;;
385          esac
386          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
387            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
388            exit 1
389          fi
390
391      - name: Create and upload Linux .tar.gz bundle
392        run: script/bundle-linux
393
394      - name: Upload Linux bundle to workflow run if main branch or specific label
395        uses: actions/upload-artifact@v4
396        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
397        with:
398          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
399          path: target/release/zed-*.tar.gz
400
401      - name: Upload app bundle to release
402        uses: softprops/action-gh-release@v1
403        if: ${{ env.RELEASE_CHANNEL == 'preview' }}
404        with:
405          draft: true
406          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
407          files: target/release/zed-linux-aarch64.tar.gz
408          body: ""
409        env:
410          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}