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