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        run: ./script/clippy
151
152      - name: Build Zed
153        run: cargo build -p zed
154
155  bundle-mac:
156    timeout-minutes: 60
157    name: Create a macOS bundle
158    runs-on:
159      - self-hosted
160      - bundle
161    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
162    needs: [macos_tests]
163    env:
164      MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
165      MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
166      APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
167      APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
168      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
169      DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
170      DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
171    steps:
172      - name: Install Node
173        uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
174        with:
175          node-version: "18"
176
177      - name: Checkout repo
178        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
179        with:
180          # We need to fetch more than one commit so that `script/draft-release-notes`
181          # is able to diff between the current and previous tag.
182          #
183          # 25 was chosen arbitrarily.
184          fetch-depth: 25
185          clean: false
186
187      - name: Limit target directory size
188        run: script/clear-target-dir-if-larger-than 100
189
190      - name: Determine version and release channel
191        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
192        run: |
193          set -eu
194
195          version=$(script/get-crate-version zed)
196          channel=$(cat crates/zed/RELEASE_CHANNEL)
197          echo "Publishing version: ${version} on release channel ${channel}"
198          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
199
200          expected_tag_name=""
201          case ${channel} in
202            stable)
203              expected_tag_name="v${version}";;
204            preview)
205              expected_tag_name="v${version}-pre";;
206            nightly)
207              expected_tag_name="v${version}-nightly";;
208            *)
209              echo "can't publish a release on channel ${channel}"
210              exit 1;;
211          esac
212          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
213            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
214            exit 1
215          fi
216          mkdir -p target/
217          # Ignore any errors that occur while drafting release notes to not fail the build.
218          script/draft-release-notes "$version" "$channel" > target/release-notes.md || true
219
220      - name: Generate license file
221        run: script/generate-licenses
222
223      - name: Create macOS app bundle
224        run: script/bundle-mac
225
226      - name: Rename single-architecture binaries
227        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
228        run: |
229          mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
230          mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
231
232      - name: Upload app bundle (universal) to workflow run if main branch or specific label
233        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
234        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
235        with:
236          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
237          path: target/release/Zed.dmg
238      - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
239        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # 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 }}-aarch64.dmg
243          path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
244
245      - name: Upload app bundle (x86_64) to workflow run if main branch or specific label
246        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
247        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
248        with:
249          name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
250          path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
251
252      - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
253        name: Upload app bundle to release
254        if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
255        with:
256          draft: true
257          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
258          files: |
259            target/zed-remote-server-macos-x86_64.gz
260            target/zed-remote-server-macos-aarch64.gz
261            target/aarch64-apple-darwin/release/Zed-aarch64.dmg
262            target/x86_64-apple-darwin/release/Zed-x86_64.dmg
263            target/release/Zed.dmg
264          body_path: target/release-notes.md
265        env:
266          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
267
268  bundle-linux:
269    timeout-minutes: 60
270    name: Create a Linux bundle
271    runs-on:
272      - self-hosted
273      - deploy
274    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
275    needs: [linux_tests]
276    env:
277      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
278    steps:
279      - name: Add Rust to the PATH
280        run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
281
282      - name: Checkout repo
283        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
284        with:
285          clean: false
286
287      - name: Limit target directory size
288        run: script/clear-target-dir-if-larger-than 100
289
290      - name: Determine version and release channel
291        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
292        run: |
293          set -eu
294
295          version=$(script/get-crate-version zed)
296          channel=$(cat crates/zed/RELEASE_CHANNEL)
297          echo "Publishing version: ${version} on release channel ${channel}"
298          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
299
300          expected_tag_name=""
301          case ${channel} in
302            stable)
303              expected_tag_name="v${version}";;
304            preview)
305              expected_tag_name="v${version}-pre";;
306            nightly)
307              expected_tag_name="v${version}-nightly";;
308            *)
309              echo "can't publish a release on channel ${channel}"
310              exit 1;;
311          esac
312          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
313            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
314            exit 1
315          fi
316
317      - name: Create Linux .tar.gz bundle
318        run: script/bundle-linux
319
320      - name: Upload Linux bundle to workflow run if main branch or specific label
321        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
322        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
323        with:
324          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
325          path: target/release/zed-*.tar.gz
326
327      - name: Upload app bundle to release
328        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
329        with:
330          draft: true
331          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
332          files: |
333            target/zed-remote-server-linux-x86_64.gz
334            target/release/zed-linux-x86_64.tar.gz
335          body: ""
336        env:
337          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
338
339  bundle-linux-aarch64:
340    timeout-minutes: 60
341    name: Create arm64 Linux bundle
342    runs-on:
343      - hosted-linux-arm-1
344    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
345    needs: [linux_tests]
346    env:
347      ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
348    steps:
349      - name: Checkout repo
350        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
351        with:
352          clean: false
353      - name: "Setup jq"
354        uses: dcarbone/install-jq-action@8867ddb4788346d7c22b72ea2e2ffe4d514c7bcb # v2
355
356      - name: Set up Clang
357        run: |
358          sudo apt-get update
359          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
360          echo "/usr/lib/llvm-10/bin" >> $GITHUB_PATH
361
362      - uses: rui314/setup-mold@2e332a0b602c2fc65d2d3995941b1b29a5f554a0 # v1
363        with:
364          mold-version: 2.32.0
365
366      - name: rustup
367        run: |
368          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
369          echo "$HOME/.cargo/bin" >> $GITHUB_PATH
370
371      - name: Limit target directory size
372        run: script/clear-target-dir-if-larger-than 100
373
374      - name: Determine version and release channel
375        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
376        run: |
377          set -eu
378
379          version=$(script/get-crate-version zed)
380          channel=$(cat crates/zed/RELEASE_CHANNEL)
381          echo "Publishing version: ${version} on release channel ${channel}"
382          echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
383
384          expected_tag_name=""
385          case ${channel} in
386            stable)
387              expected_tag_name="v${version}";;
388            preview)
389              expected_tag_name="v${version}-pre";;
390            nightly)
391              expected_tag_name="v${version}-nightly";;
392            *)
393              echo "can't publish a release on channel ${channel}"
394              exit 1;;
395          esac
396          if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
397            echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
398            exit 1
399          fi
400
401      - name: Create and upload Linux .tar.gz bundle
402        run: script/bundle-linux
403
404      - name: Upload Linux bundle to workflow run if main branch or specific label
405        uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
406        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
407        with:
408          name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
409          path: target/release/zed-*.tar.gz
410
411      - name: Upload app bundle to release
412        uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
413        if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
414        with:
415          draft: true
416          prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
417          files: |
418            target/zed-remote-server-linux-aarch64.gz
419            target/release/zed-linux-aarch64.tar.gz
420          body: ""
421        env:
422          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}