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