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 merge_group:
14
15concurrency:
16 # Allow only one workflow per any non-`main` branch.
17 group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.ref_name == 'main' && github.sha || 'anysha' }}
18 cancel-in-progress: true
19
20env:
21 CARGO_TERM_COLOR: always
22 CARGO_INCREMENTAL: 0
23 RUST_BACKTRACE: 1
24 RUSTFLAGS: "-D warnings"
25
26jobs:
27 check_docs_only:
28 runs-on: ubuntu-latest
29 outputs:
30 docs_only: ${{ steps.check_changes.outputs.docs_only }}
31 steps:
32 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
33 with:
34 fetch-depth: 0
35 - name: Check for non-docs changes
36 id: check_changes
37 run: |
38 if [ "${{ github.event_name }}" == "merge_group" ]; then
39 # When we're running in a merge queue, never assume that the changes
40 # are docs-only, as there could be other PRs in the group that
41 # contain non-docs changes.
42 echo "docs_only=false" >> $GITHUB_OUTPUT
43 elif git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -qvE '^docs/'; then
44 echo "docs_only=false" >> $GITHUB_OUTPUT
45 else
46 echo "docs_only=true" >> $GITHUB_OUTPUT
47 fi
48
49 migration_checks:
50 name: Check Postgres and Protobuf migrations, mergability
51 if: github.repository_owner == 'zed-industries'
52 timeout-minutes: 60
53 runs-on:
54 - self-hosted
55 - test
56 steps:
57 - name: Checkout repo
58 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
59 with:
60 clean: false
61 fetch-depth: 0 # fetch full history
62
63 - name: Remove untracked files
64 run: git clean -df
65
66 - name: Find modified migrations
67 shell: bash -euxo pipefail {0}
68 run: |
69 export SQUAWK_GITHUB_TOKEN=${{ github.token }}
70 . ./script/squawk
71
72 - name: Ensure fresh merge
73 shell: bash -euxo pipefail {0}
74 run: |
75 if [ -z "$GITHUB_BASE_REF" ];
76 then
77 echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV
78 else
79 git checkout -B temp
80 git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp"
81 echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
82 fi
83
84 - uses: bufbuild/buf-setup-action@v1
85 with:
86 version: v1.29.0
87 - uses: bufbuild/buf-breaking-action@v1
88 with:
89 input: "crates/proto/proto/"
90 against: "https://github.com/${GITHUB_REPOSITORY}.git#branch=${BUF_BASE_BRANCH},subdir=crates/proto/proto/"
91
92 style:
93 timeout-minutes: 60
94 name: Check formatting and spelling
95 if: github.repository_owner == 'zed-industries'
96 runs-on:
97 - buildjet-8vcpu-ubuntu-2204
98 steps:
99 - name: Checkout repo
100 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
101
102 # To support writing comments that they will certainly be revisited.
103 - name: Check for todo! and FIXME comments
104 run: script/check-todos
105
106 - name: Run style checks
107 uses: ./.github/actions/check_style
108
109 - name: Check for typos
110 uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
111 with:
112 config: ./typos.toml
113
114 macos_tests:
115 timeout-minutes: 60
116 name: (macOS) Run Clippy and tests
117 if: github.repository_owner == 'zed-industries'
118 runs-on:
119 - self-hosted
120 - test
121 needs: check_docs_only
122 steps:
123 - name: Checkout repo
124 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
125 with:
126 clean: false
127
128 - name: cargo clippy
129 if: needs.check_docs_only.outputs.docs_only == 'false'
130 run: ./script/clippy
131
132 - name: Check unused dependencies
133 if: needs.check_docs_only.outputs.docs_only == 'false'
134 uses: bnjbvr/cargo-machete@main
135
136 - name: Check licenses
137 if: needs.check_docs_only.outputs.docs_only == 'false'
138 run: |
139 script/check-licenses
140 script/generate-licenses /tmp/zed_licenses_output
141
142 - name: Check for new vulnerable dependencies
143 if: github.event_name == 'pull_request' && needs.check_docs_only.outputs.docs_only == 'false'
144 uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4
145 with:
146 license-check: false
147
148 - name: Run tests
149 if: needs.check_docs_only.outputs.docs_only == 'false'
150 uses: ./.github/actions/run_tests
151
152 - name: Build collab
153 if: needs.check_docs_only.outputs.docs_only == 'false'
154 run: cargo build -p collab
155
156 - name: Build other binaries and features
157 if: needs.check_docs_only.outputs.docs_only == 'false'
158 run: |
159 cargo build --workspace --bins --all-features
160 cargo check -p gpui --features "macos-blade"
161 cargo check -p workspace
162 cargo build -p remote_server
163 script/check-rust-livekit-macos
164
165 linux_tests:
166 timeout-minutes: 60
167 name: (Linux) Run Clippy and tests
168 if: github.repository_owner == 'zed-industries'
169 runs-on:
170 - buildjet-16vcpu-ubuntu-2204
171 needs: check_docs_only
172 steps:
173 - name: Add Rust to the PATH
174 run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
175
176 - name: Checkout repo
177 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
178 with:
179 clean: false
180
181 - name: Cache dependencies
182 if: needs.check_docs_only.outputs.docs_only == 'false'
183 uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
184 with:
185 save-if: ${{ github.ref == 'refs/heads/main' }}
186 cache-provider: "buildjet"
187
188 - name: Install Linux dependencies
189 if: needs.check_docs_only.outputs.docs_only == 'false'
190 run: ./script/linux
191
192 - name: cargo clippy
193 if: needs.check_docs_only.outputs.docs_only == 'false'
194 run: ./script/clippy
195
196 - name: Run tests
197 if: needs.check_docs_only.outputs.docs_only == 'false'
198 uses: ./.github/actions/run_tests
199
200 - name: Build other binaries and features
201 if: needs.check_docs_only.outputs.docs_only == 'false'
202 run: |
203 cargo build -p zed
204 cargo check -p workspace
205
206 build_remote_server:
207 timeout-minutes: 60
208 name: (Linux) Build Remote Server
209 if: github.repository_owner == 'zed-industries'
210 runs-on:
211 - buildjet-16vcpu-ubuntu-2204
212 needs: check_docs_only
213 steps:
214 - name: Add Rust to the PATH
215 run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
216
217 - name: Checkout repo
218 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
219 with:
220 clean: false
221
222 - name: Cache dependencies
223 if: needs.check_docs_only.outputs.docs_only == 'false'
224 uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
225 with:
226 save-if: ${{ github.ref == 'refs/heads/main' }}
227 cache-provider: "buildjet"
228
229 - name: Install Clang & Mold
230 if: needs.check_docs_only.outputs.docs_only == 'false'
231 run: ./script/remote-server && ./script/install-mold 2.34.0
232
233 - name: Build Remote Server
234 if: needs.check_docs_only.outputs.docs_only == 'false'
235 run: cargo build -p remote_server
236
237 # todo(windows): Actually run the tests
238 windows_tests:
239 timeout-minutes: 60
240 name: (Windows) Run Clippy and tests
241 if: github.repository_owner == 'zed-industries'
242 runs-on: hosted-windows-1
243 needs: check_docs_only
244 steps:
245 # more info here:- https://github.com/rust-lang/cargo/issues/13020
246 - name: Enable longer pathnames for git
247 run: git config --system core.longpaths true
248 - name: Checkout repo
249 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
250 with:
251 clean: false
252
253 - name: Cache dependencies
254 if: needs.check_docs_only.outputs.docs_only == 'false'
255 uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
256 with:
257 save-if: ${{ github.ref == 'refs/heads/main' }}
258 cache-provider: "github"
259
260 - name: cargo clippy
261 if: needs.check_docs_only.outputs.docs_only == 'false'
262 # Windows can't run shell scripts, so we need to use `cargo xtask`.
263 run: cargo xtask clippy
264
265 - name: Build Zed
266 if: needs.check_docs_only.outputs.docs_only == 'false'
267 run: cargo build
268
269 bundle-mac:
270 timeout-minutes: 60
271 name: Create a macOS bundle
272 runs-on:
273 - self-hosted
274 - bundle
275 if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
276 needs: [macos_tests]
277 env:
278 MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
279 MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
280 APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
281 APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
282 ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
283 ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
284 DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
285 DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
286 steps:
287 - name: Install Node
288 uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
289 with:
290 node-version: "18"
291
292 - name: Checkout repo
293 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
294 with:
295 # We need to fetch more than one commit so that `script/draft-release-notes`
296 # is able to diff between the current and previous tag.
297 #
298 # 25 was chosen arbitrarily.
299 fetch-depth: 25
300 clean: false
301 ref: ${{ github.ref }}
302
303 - name: Limit target directory size
304 run: script/clear-target-dir-if-larger-than 100
305
306 - name: Determine version and release channel
307 if: ${{ startsWith(github.ref, 'refs/tags/v') }}
308 run: |
309 # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
310 script/determine-release-channel
311
312 - name: Draft release notes
313 if: ${{ startsWith(github.ref, 'refs/tags/v') }}
314 run: |
315 mkdir -p target/
316 # Ignore any errors that occur while drafting release notes to not fail the build.
317 script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md || true
318 script/create-draft-release target/release-notes.md
319 env:
320 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
321
322 - name: Generate license file
323 run: script/generate-licenses
324
325 - name: Create macOS app bundle
326 run: script/bundle-mac
327
328 - name: Rename binaries
329 if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
330 run: |
331 mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
332 mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
333
334 - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
335 uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
336 if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
337 with:
338 name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
339 path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
340
341 - name: Upload app bundle (x86_64) to workflow run if main branch or specific label
342 uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
343 if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
344 with:
345 name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
346 path: target/x86_64-apple-darwin/release/Zed-x86_64.dmg
347
348 - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
349 name: Upload app bundle to release
350 if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
351 with:
352 draft: true
353 prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
354 files: |
355 target/zed-remote-server-macos-x86_64.gz
356 target/zed-remote-server-macos-aarch64.gz
357 target/aarch64-apple-darwin/release/Zed-aarch64.dmg
358 target/x86_64-apple-darwin/release/Zed-x86_64.dmg
359 env:
360 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
361
362 bundle-linux:
363 timeout-minutes: 60
364 name: Create a Linux bundle
365 runs-on:
366 - buildjet-16vcpu-ubuntu-2004
367 if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
368 needs: [linux_tests]
369 env:
370 ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
371 ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
372 DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
373 DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
374 steps:
375 - name: Checkout repo
376 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
377 with:
378 clean: false
379
380 - name: Install Linux dependencies
381 run: ./script/linux && ./script/install-mold 2.34.0
382
383 - name: Determine version and release channel
384 if: ${{ startsWith(github.ref, 'refs/tags/v') }}
385 run: |
386 # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
387 script/determine-release-channel
388
389 - name: Create Linux .tar.gz bundle
390 run: script/bundle-linux
391
392 - name: Upload Linux bundle to workflow run if main branch or specific label
393 uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
394 if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
395 with:
396 name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
397 path: target/release/zed-*.tar.gz
398
399 - name: Upload app bundle to release
400 uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
401 with:
402 draft: true
403 prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
404 files: |
405 target/zed-remote-server-linux-x86_64.gz
406 target/release/zed-linux-x86_64.tar.gz
407 env:
408 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
409
410 bundle-linux-aarch64: # this runs on ubuntu22.04
411 timeout-minutes: 60
412 name: Create arm64 Linux bundle
413 runs-on:
414 - buildjet-16vcpu-ubuntu-2204-arm
415 if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
416 needs: [linux_tests]
417 env:
418 ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
419 ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
420 DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
421 DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
422 steps:
423 - name: Checkout repo
424 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
425 with:
426 clean: false
427
428 - name: Install Linux dependencies
429 run: ./script/linux
430
431 - name: Determine version and release channel
432 if: ${{ startsWith(github.ref, 'refs/tags/v') }}
433 run: |
434 # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
435 script/determine-release-channel
436
437 - name: Create and upload Linux .tar.gz bundle
438 run: script/bundle-linux
439
440 - name: Upload Linux bundle to workflow run if main branch or specific label
441 uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
442 if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
443 with:
444 name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
445 path: target/release/zed-*.tar.gz
446
447 - name: Upload app bundle to release
448 uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
449 with:
450 draft: true
451 prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
452 files: |
453 target/zed-remote-server-linux-aarch64.gz
454 target/release/zed-linux-aarch64.tar.gz
455 env:
456 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
457
458 auto-release-preview:
459 name: Auto release preview
460 if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') }}
461 needs: [bundle-mac, bundle-linux, bundle-linux-aarch64]
462 runs-on:
463 - self-hosted
464 - bundle
465 steps:
466 - name: gh release
467 run: gh release edit $GITHUB_REF_NAME --draft=false
468 env:
469 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}