Fix configuration issue in CI runners (#23223)

张小白 created

While working on PR #23117, I noticed that the Windows runner in our CI
setup doesn't seem to respect the settings defined in
`.cargo/config.toml`. With @SomeoneToIgnore ’s help, Kirill and I
realized this issue isn’t limited to the Windows runner—all of our
runners disregard the configurations in `.cargo/config.toml`.

Later, @osiewicz suggested an excellent workaround. I conducted some
tests on PR #23117 and found that the solution works as intended.

Personally, I prefer using environment variables for global
configuration. However, according to the documentation
[here](https://doc.rust-lang.org/cargo/reference/config.html), it seems
that environment variables always override the settings in
`.cargo/config.toml`.

Release Notes:

- N/A

Change summary

.cargo/ci-config.toml    | 12 +++++++++++
.github/workflows/ci.yml | 43 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletion(-)

Detailed changes

.cargo/ci-config.toml 🔗

@@ -0,0 +1,12 @@
+# This config is different from config.toml in this directory, as the latter is recognized by Cargo.
+# This file is placed in ./../.cargo/config.toml on CI runs. Cargo then merges Zeds .cargo/config.toml with ./../.cargo/config.toml
+# with preference for settings from Zeds config.toml.
+# TL;DR: If a value is set in both ci-config.toml and config.toml, config.toml value takes precedence.
+# Arrays are merged together though. See: https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure
+# The intent for this file is to configure CI build process with a divergance from Zed developers experience; for example, in this config file
+# we use `-D warnings` for rustflags (which makes compilation fail in presence of warnings during build process). Placing that in developers `config.toml`
+# would be incovenient.
+# The reason for not using the RUSTFLAGS environment variable is that doing so would override all the settings in the config.toml file, even if the contents of the latter are completely nonsensical. See: https://github.com/rust-lang/cargo/issues/5376
+# Here, we opted to use `[target.'cfg(all())']` instead of `[build]` because `[target.'**']` is guaranteed to be cumulative.
+[target.'cfg(all())']
+rustflags = ["-D", "warnings"]

.github/workflows/ci.yml 🔗

@@ -20,7 +20,6 @@ env:
   CARGO_TERM_COLOR: always
   CARGO_INCREMENTAL: 0
   RUST_BACKTRACE: 1
-  RUSTFLAGS: "-D warnings"
 
 jobs:
   migration_checks:
@@ -101,6 +100,11 @@ jobs:
         with:
           clean: false
 
+      - name: Configure CI
+        run: |
+          mkdir -p ./../.cargo
+          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
+
       - name: cargo clippy
         run: ./script/clippy
 
@@ -132,6 +136,11 @@ jobs:
           cargo build -p remote_server
           script/check-rust-livekit-macos
 
+      # Since the macOS runners are stateful, so we need to remove the config file to prevent potential bug.
+      - name: Clean CI config file
+        if: always()
+        run: rm -rf ./../.cargo
+
   linux_tests:
     timeout-minutes: 60
     name: (Linux) Run Clippy and tests
@@ -156,6 +165,11 @@ jobs:
       - name: Install Linux dependencies
         run: ./script/linux
 
+      - name: Configure CI
+        run: |
+          mkdir -p ./../.cargo
+          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
+
       - name: cargo clippy
         run: ./script/clippy
 
@@ -167,6 +181,14 @@ jobs:
           cargo build -p zed
           cargo check -p workspace
 
+      # Even the Linux runner is not stateful, in theory there is no need to do this cleanup.
+      # But, to avoid potential issues in the future if we choose to use a stateful Linux runner and forget to add code
+      # to clean up the config file, I’ve included the cleanup code here as a precaution.
+      # While it’s not strictly necessary at this moment, I believe it’s better to err on the side of caution.
+      - name: Clean CI config file
+        if: always()
+        run: rm -rf ./../.cargo
+
   build_remote_server:
     timeout-minutes: 60
     name: (Linux) Build Remote Server
@@ -191,9 +213,18 @@ jobs:
       - name: Install Clang & Mold
         run: ./script/remote-server && ./script/install-mold 2.34.0
 
+      - name: Configure CI
+        run: |
+          mkdir -p ./../.cargo
+          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
+
       - name: Build Remote Server
         run: cargo build -p remote_server
 
+      - name: Clean CI config file
+        if: always()
+        run: rm -rf ./../.cargo
+
   # todo(windows): Actually run the tests
   windows_tests:
     timeout-minutes: 60
@@ -215,6 +246,11 @@ jobs:
           save-if: ${{ github.ref == 'refs/heads/main' }}
           cache-provider: "github"
 
+      - name: Configure CI
+        run: |
+          mkdir -p ./../.cargo
+          cp ./.cargo/ci-config.toml ./../.cargo/config.toml
+
       - name: cargo clippy
         # Windows can't run shell scripts, so we need to use `cargo xtask`.
         run: cargo xtask clippy
@@ -222,6 +258,11 @@ jobs:
       - name: Build Zed
         run: cargo build
 
+      # Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
+      - name: Clean CI config file
+        if: always()
+        run: Remove-Item -Path "./../.cargo" -Recurse -Force
+
   bundle-mac:
     timeout-minutes: 120
     name: Create a macOS bundle