ci: GitHub actions refactor (#26551)

Peter Tripp created

Refactor GitHub actions CI workflow.
- Single combined 'tests_pass' action so we only need one mandatory
check for merge queue
- Add new `job_spec` job which determines what needs to be run (+5secs)
  - Do not run full CI for docs only changes (~30secs vs 10+mins)
- Only run `script/generate-licenses` if Cargo.lock changed (saves
~23secs on mac_test)
- Move prettier /docs check to ci.yml and remove docs.yml 
- Run Windows tests on every PR commit
- Added new Windows runners named to reflect their OS/capacity
(windows-2025-64, windows-2025-32, windows-2025-16)

Release Notes:

- N/A

Change summary

.github/workflows/ci.yml   | 176 +++++++++++++++++++++++++++++----------
.github/workflows/docs.yml |  39 --------
2 files changed, 132 insertions(+), 83 deletions(-)

Detailed changes

.github/workflows/ci.yml 🔗

@@ -23,9 +23,43 @@ env:
   RUST_BACKTRACE: 1
 
 jobs:
+  job_spec:
+    name: Decide which jobs to run
+    if: github.repository_owner == 'zed-industries'
+    outputs:
+      run_tests: ${{ steps.filter.outputs.run_tests }}
+    runs-on:
+      - ubuntu-latest
+    steps:
+      - name: Checkout repo
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
+        with:
+          fetch-depth: 350
+      # 350 is arbitrary. Full fetch is ~18secs; 350 is ~5s
+      # This will fail if your branch is >350 commits behind main
+      - name: Fetch main branch (or PR target) branch
+        run: git fetch origin ${{ github.event.pull_request.base.ref }} --depth=350
+      - name:
+        id: filter
+        run: |
+          MERGE_BASE=$(git merge-base origin/main HEAD)
+          if [[ $(git diff --name-only $MERGE_BASE ${{ github.sha }} | grep -v "^docs/") ]]; then
+            echo "run_tests=true" >> $GITHUB_OUTPUT
+          else
+            echo "run_tests=false" >> $GITHUB_OUTPUT
+          fi
+          if [[ $(git diff --name-only $MERGE_BASE ${{ github.sha }} | grep '^Cargo.lock') ]]; then
+            echo "run_license=true" >> $GITHUB_OUTPUT
+          else
+            echo "run_license=false" >> $GITHUB_OUTPUT
+          fi
+
   migration_checks:
     name: Check Postgres and Protobuf migrations, mergability
-    if: github.repository_owner == 'zed-industries'
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
     timeout-minutes: 60
     runs-on:
       - self-hosted
@@ -69,6 +103,7 @@ jobs:
   style:
     timeout-minutes: 60
     name: Check formatting and spelling
+    needs: [job_spec]
     if: github.repository_owner == 'zed-industries'
     runs-on:
       - buildjet-8vcpu-ubuntu-2204
@@ -76,6 +111,21 @@ jobs:
       - name: Checkout repo
         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
 
+      - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
+        with:
+          version: 9
+
+      - name: Prettier Check on /docs
+        working-directory: ./docs
+        run: |
+          pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
+            echo "To fix, run from the root of the zed repo:"
+            echo "  cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
+            false
+          }
+        env:
+          PRETTIER_VERSION: 3.5.0
+
       # To support writing comments that they will certainly be revisited.
       - name: Check for todo! and FIXME comments
         run: script/check-todos
@@ -91,7 +141,10 @@ jobs:
   macos_tests:
     timeout-minutes: 60
     name: (macOS) Run Clippy and tests
-    if: github.repository_owner == 'zed-industries'
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
     runs-on:
       - self-hosted
       - test
@@ -123,7 +176,9 @@ jobs:
       - name: Check licenses
         run: |
           script/check-licenses
-          script/generate-licenses /tmp/zed_licenses_output
+          if [[ "${{ needs.job_spec.outputs.run_license }}" == "true" ]]; then
+            script/generate-licenses /tmp/zed_licenses_output
+          fi
 
       - name: Check for new vulnerable dependencies
         if: github.event_name == 'pull_request'
@@ -154,7 +209,10 @@ jobs:
   linux_tests:
     timeout-minutes: 60
     name: (Linux) Run Clippy and tests
-    if: github.repository_owner == 'zed-industries'
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
     runs-on:
       - buildjet-16vcpu-ubuntu-2204
     steps:
@@ -203,9 +261,12 @@ jobs:
   build_remote_server:
     timeout-minutes: 60
     name: (Linux) Build Remote Server
-    if: github.repository_owner == 'zed-industries'
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
     runs-on:
-      - buildjet-16vcpu-ubuntu-2204
+      - buildjet-8vcpu-ubuntu-2204
     steps:
       - name: Add Rust to the PATH
         run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
@@ -239,21 +300,12 @@ jobs:
   windows_clippy:
     timeout-minutes: 60
     name: (Windows) Run Clippy
-    if: github.repository_owner == 'zed-industries'
-    runs-on: hosted-windows-2
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
+    runs-on: windows-2025-16
     steps:
-      # Temporarily Collect some metadata about the hardware behind our runners.
-      - name: GHA Runner Info
-        run: |
-          Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute?api-version=2023-07-01" |
-            ConvertTo-Json -Depth 10 |
-            jq "{ vm_size: .vmSize, location: .location, os_disk_gb: (.storageProfile.osDisk.diskSizeGB | tonumber), rs_disk_gb: (.storageProfile.resourceDisk.size | tonumber / 1024) }"
-          @{
-              Cores = (Get-CimInstance Win32_Processor).NumberOfCores
-              vCPUs = (Get-CimInstance Win32_Processor).NumberOfLogicalProcessors
-              RamGb = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
-              cpuid = (Get-CimInstance Win32_Processor).Name.Trim()
-          } | ConvertTo-Json
       # more info here:- https://github.com/rust-lang/cargo/issues/13020
       - name: Enable longer pathnames for git
         run: git config --system core.longpaths true
@@ -306,21 +358,12 @@ jobs:
   windows_tests:
     timeout-minutes: 60
     name: (Windows) Run Tests
-    if: ${{ github.repository_owner == 'zed-industries' && (github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'windows')) }}
-    runs-on: hosted-windows-2
+    needs: [job_spec]
+    if: |
+      github.repository_owner == 'zed-industries' &&
+      needs.job_spec.outputs.run_tests == 'true'
+    runs-on: windows-2025-64
     steps:
-      # Temporarily Collect some metadata about the hardware behind our runners.
-      - name: GHA Runner Info
-        run: |
-          Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute?api-version=2023-07-01" |
-            ConvertTo-Json -Depth 10 |
-            jq "{ vm_size: .vmSize, location: .location, os_disk_gb: (.storageProfile.osDisk.diskSizeGB | tonumber), rs_disk_gb: (.storageProfile.resourceDisk.size | tonumber / 1024) }"
-          @{
-              Cores = (Get-CimInstance Win32_Processor).NumberOfCores
-              vCPUs = (Get-CimInstance Win32_Processor).NumberOfLogicalProcessors
-              RamGb = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
-              cpuid = (Get-CimInstance Win32_Processor).Name.Trim()
-          } | ConvertTo-Json
       # more info here:- https://github.com/rust-lang/cargo/issues/13020
       - name: Enable longer pathnames for git
         run: git config --system core.longpaths true
@@ -372,13 +415,44 @@ jobs:
             Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml"  -Force
           }
 
+  tests_pass:
+    name: Tests Pass
+    runs-on: ubuntu-latest
+    needs:
+      - job_spec
+      - style
+      - migration_checks
+      - linux_tests
+      - build_remote_server
+      - macos_tests
+      - windows_clippy
+      - windows_tests
+    if: |
+      always() && (
+        needs.style.result == 'success'
+        && (
+          needs.job_spec.outputs.run_tests == 'false'
+          || (needs.macos_tests.result == 'success'
+              && needs.linux_tests.result == 'success'
+              && needs.windows_tests.result == 'success'
+              && needs.windows_clippy.result == 'success'
+              && needs.build_remote_server.result == 'success'
+              && needs.migration_checks.result == 'success')
+        )
+      )
+    steps:
+      - name: All tests passed
+        run: echo "All tests passed successfully!"
+
   bundle-mac:
     timeout-minutes: 120
     name: Create a macOS bundle
     runs-on:
       - self-hosted
       - bundle
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+    if: |
+      startsWith(github.ref, 'refs/tags/v')
+      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
     needs: [macos_tests]
     env:
       MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
@@ -468,7 +542,9 @@ jobs:
     name: Linux x86_x64 release bundle
     runs-on:
       - buildjet-16vcpu-ubuntu-2004
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+    if: |
+      startsWith(github.ref, 'refs/tags/v')
+      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
     needs: [linux_tests]
     env:
       ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
@@ -485,7 +561,7 @@ jobs:
         run: ./script/linux && ./script/install-mold 2.34.0
 
       - name: Determine version and release channel
-        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
+        if: startsWith(github.ref, 'refs/tags/v')
         run: |
           # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
           script/determine-release-channel
@@ -495,14 +571,18 @@ jobs:
 
       - name: Upload Linux bundle to workflow run if main branch or specific label
         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
-        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+        if: |
+          github.ref == 'refs/heads/main'
+          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
         with:
           name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
           path: target/release/zed-*.tar.gz
 
       - name: Upload Linux remote server to workflow run if main branch or specific label
         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
-        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+        if: |
+          github.ref == 'refs/heads/main'
+          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
         with:
           name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.gz
           path: target/zed-remote-server-linux-x86_64.gz
@@ -523,7 +603,9 @@ jobs:
     name: Linux arm64 release bundle
     runs-on:
       - buildjet-16vcpu-ubuntu-2204-arm
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+    if: |
+      startsWith(github.ref, 'refs/tags/v')
+      || contains(github.event.pull_request.labels.*.name, 'run-bundling')
     needs: [linux_tests]
     env:
       ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
@@ -540,7 +622,7 @@ jobs:
         run: ./script/linux
 
       - name: Determine version and release channel
-        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
+        if: startsWith(github.ref, 'refs/tags/v')
         run: |
           # This exports RELEASE_CHANNEL into env (GITHUB_ENV)
           script/determine-release-channel
@@ -550,14 +632,18 @@ jobs:
 
       - name: Upload Linux bundle to workflow run if main branch or specific label
         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
-        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+        if: |
+          github.ref == 'refs/heads/main'
+          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
         with:
           name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz
           path: target/release/zed-*.tar.gz
 
       - name: Upload Linux remote server to workflow run if main branch or specific label
         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
-        if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
+        if: |
+          github.ref == 'refs/heads/main'
+          || contains(github.event.pull_request.labels.*.name, 'run-bundling')
         with:
           name: zed-remote-server-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.gz
           path: target/zed-remote-server-linux-aarch64.gz
@@ -575,7 +661,9 @@ jobs:
 
   auto-release-preview:
     name: Auto release preview
-    if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') }}
+    if: |
+      startsWith(github.ref, 'refs/tags/v')
+      && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre')
     needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64]
     runs-on:
       - self-hosted

.github/workflows/docs.yml 🔗

@@ -1,39 +0,0 @@
-name: Docs
-
-on:
-  pull_request:
-    paths:
-      - "docs/**"
-  push:
-    branches:
-      - main
-
-jobs:
-  check_formatting:
-    name: "Check formatting"
-    if: github.repository_owner == 'zed-industries'
-    runs-on: ubuntu-latest
-
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
-
-      - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
-        with:
-          version: 9
-
-      - name: Prettier Check on /docs
-        working-directory: ./docs
-        run: |
-          pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
-            echo "To fix, run from the root of the zed repo:"
-            echo "  cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
-            false
-          }
-        env:
-          PRETTIER_VERSION: 3.5.0
-
-      - name: Check for Typos with Typos-CLI
-        uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
-        with:
-          config: ./typos.toml
-          files: ./docs/