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