about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2025-02-11 16:34:16 +0100
committerJakub Beránek <berykubik@gmail.com>2025-02-17 12:30:02 +0100
commit8083fd4b495236535ac235c890e1b439b6b1f888 (patch)
tree95c3e1acfc928ac297be2483bafcc18bcf820f00
parent77bd646023118c10d901cb1d521cf00df6358afd (diff)
downloadrust-8083fd4b495236535ac235c890e1b439b6b1f888.tar.gz
rust-8083fd4b495236535ac235c890e1b439b6b1f888.zip
Add tests
-rw-r--r--src/ci/citool/Cargo.lock70
-rw-r--r--src/ci/citool/Cargo.toml3
-rw-r--r--src/ci/citool/src/main.rs81
-rw-r--r--src/ci/citool/tests/jobs.rs64
-rw-r--r--src/ci/citool/tests/test-jobs.yml145
5 files changed, 324 insertions, 39 deletions
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
index d7931af464e..39b6b44da64 100644
--- a/src/ci/citool/Cargo.lock
+++ b/src/ci/citool/Cargo.lock
@@ -64,6 +64,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "clap",
+ "insta",
  "serde",
  "serde_json",
  "serde_yaml",
@@ -116,6 +117,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
 
 [[package]]
+name = "console"
+version = "0.15.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "windows-sys",
+]
+
+[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
 name = "equivalent"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -144,6 +163,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "insta"
+version = "1.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71c1b125e30d93896b365e156c33dadfffab45ee8400afcbba4752f59de08a86"
+dependencies = [
+ "console",
+ "linked-hash-map",
+ "once_cell",
+ "pin-project",
+ "similar",
+]
+
+[[package]]
 name = "is_terminal_polyfill"
 version = "1.70.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -156,6 +188,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
 
 [[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
 name = "memchr"
 version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -168,6 +212,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
 
 [[package]]
+name = "pin-project"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -237,6 +301,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "similar"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
+
+[[package]]
 name = "strsim"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml
index d6423d7ae4b..e77c67c7147 100644
--- a/src/ci/citool/Cargo.toml
+++ b/src/ci/citool/Cargo.toml
@@ -10,6 +10,9 @@ serde = { version = "1", features = ["derive"] }
 serde_yaml = "0.9"
 serde_json = "1"
 
+[dev-dependencies]
+insta = "1"
+
 # Tell cargo that citool is its own workspace.
 # If this is omitted, cargo will look for a workspace elsewhere.
 # We want to avoid this, since citool is independent of the other crates.
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 9a22d1264fa..b8d74100423 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -1,5 +1,5 @@
-use std::collections::HashMap;
-use std::path::Path;
+use std::collections::BTreeMap;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 
 use anyhow::Context;
@@ -17,13 +17,13 @@ struct Job {
     name: String,
     /// GitHub runner on which the job should be executed
     os: String,
-    env: HashMap<String, Value>,
+    env: BTreeMap<String, Value>,
     /// Should the job be only executed on a specific channel?
     #[serde(default)]
     only_on_channel: Option<String>,
     /// Rest of attributes that will be passed through to GitHub actions
     #[serde(flatten)]
-    extra_keys: HashMap<String, Value>,
+    extra_keys: BTreeMap<String, Value>,
 }
 
 impl Job {
@@ -44,11 +44,11 @@ impl Job {
 #[derive(serde::Deserialize, Debug)]
 struct JobEnvironments {
     #[serde(rename = "pr")]
-    pr_env: HashMap<String, Value>,
+    pr_env: BTreeMap<String, Value>,
     #[serde(rename = "try")]
-    try_env: HashMap<String, Value>,
+    try_env: BTreeMap<String, Value>,
     #[serde(rename = "auto")]
-    auto_env: HashMap<String, Value>,
+    auto_env: BTreeMap<String, Value>,
 }
 
 #[derive(serde::Deserialize, Debug)]
@@ -71,7 +71,7 @@ impl JobDatabase {
 }
 
 fn load_job_db(path: &Path) -> anyhow::Result<JobDatabase> {
-    let db = std::fs::read_to_string(path)?;
+    let db = read_to_string(path)?;
     let mut db: Value = serde_yaml::from_str(&db)?;
 
     // We need to expand merge keys (<<), because serde_yaml can't deal with them
@@ -92,9 +92,9 @@ struct GithubActionsJob {
     /// prefix (PR/try/auto).
     full_name: String,
     os: String,
-    env: HashMap<String, String>,
+    env: BTreeMap<String, String>,
     #[serde(flatten)]
-    extra_keys: HashMap<String, serde_json::Value>,
+    extra_keys: BTreeMap<String, serde_json::Value>,
 }
 
 /// Type of workflow that is being executed on CI
@@ -116,27 +116,17 @@ struct GitHubContext {
 
 impl GitHubContext {
     fn get_run_type(&self) -> Option<RunType> {
-        if self.event_name == "pull_request" {
-            return Some(RunType::PullRequest);
-        } else if self.event_name == "push" {
-            let is_try_build =
-                ["refs/heads/try", "refs/heads/try-perf", "refs/heads/automation/bors/try"]
-                    .iter()
-                    .any(|r| **r == self.branch_ref);
-            // Unrolled branch from a rollup for testing perf
-            // This should **not** allow custom try jobs
-            let is_unrolled_perf_build = self.branch_ref == "refs/heads/try-perf";
-            if is_try_build {
-                let custom_jobs =
-                    if !is_unrolled_perf_build { Some(self.get_custom_jobs()) } else { None };
-                return Some(RunType::TryJob { custom_jobs });
-            }
-
-            if self.branch_ref == "refs/heads/auto" {
-                return Some(RunType::AutoJob);
+        match (self.event_name.as_str(), self.branch_ref.as_str()) {
+            ("pull_request", _) => Some(RunType::PullRequest),
+            ("push", "refs/heads/try-perf") => Some(RunType::TryJob { custom_jobs: None }),
+            ("push", "refs/heads/try" | "refs/heads/automation/bors/try") => {
+                let custom_jobs = self.get_custom_jobs();
+                let custom_jobs = if !custom_jobs.is_empty() { Some(custom_jobs) } else { None };
+                Some(RunType::TryJob { custom_jobs })
             }
+            ("push", "refs/heads/auto") => Some(RunType::AutoJob),
+            _ => None,
         }
-        None
     }
 
     /// Tries to parse names of specific CI jobs that should be executed in the form of
@@ -175,7 +165,7 @@ fn skip_jobs(jobs: Vec<Job>, channel: &str) -> Vec<Job> {
         .collect()
 }
 
-fn to_string_map(map: &HashMap<String, Value>) -> HashMap<String, String> {
+fn to_string_map(map: &BTreeMap<String, Value>) -> BTreeMap<String, String> {
     map.iter()
         .map(|(key, value)| {
             (
@@ -232,7 +222,7 @@ fn calculate_jobs(
     let jobs = jobs
         .into_iter()
         .map(|job| {
-            let mut env: HashMap<String, String> = to_string_map(base_env);
+            let mut env: BTreeMap<String, String> = to_string_map(base_env);
             env.extend(to_string_map(&job.env));
             let full_name = format!("{prefix} - {}", job.name);
 
@@ -312,9 +302,9 @@ fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> any
         JobType::Auto => &db.auto_jobs,
         JobType::PR => &db.pr_jobs,
     };
-    let job = find_linux_job(&jobs, &name).with_context(|| format!("Cannot find job {name}"))?;
+    let job = find_linux_job(jobs, &name).with_context(|| format!("Cannot find job {name}"))?;
 
-    let mut custom_env: HashMap<String, String> = HashMap::new();
+    let mut custom_env: BTreeMap<String, String> = BTreeMap::new();
     // Replicate src/ci/scripts/setup-environment.sh
     // Adds custom environment variables to the job
     if name.starts_with("dist-") {
@@ -340,7 +330,10 @@ fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> any
 enum Args {
     /// Calculate a list of jobs that should be executed on CI.
     /// Should only be used on CI inside GitHub actions.
-    CalculateJobMatrix,
+    CalculateJobMatrix {
+        #[clap(long)]
+        jobs_file: Option<PathBuf>,
+    },
     /// Execute a given CI job locally.
     #[clap(name = "run-local")]
     RunJobLocally {
@@ -362,19 +355,29 @@ enum JobType {
 
 fn main() -> anyhow::Result<()> {
     let args = Args::parse();
-    let db = load_job_db(Path::new(JOBS_YML_PATH)).context("Cannot load jobs.yml")?;
+    let default_jobs_file = Path::new(JOBS_YML_PATH);
+    let load_db = |jobs_path| load_job_db(jobs_path).context("Cannot load jobs.yml");
 
     match args {
-        Args::CalculateJobMatrix => {
+        Args::CalculateJobMatrix { jobs_file } => {
+            let jobs_path = jobs_file.as_deref().unwrap_or(default_jobs_file);
             let gh_ctx = load_github_ctx()
                 .context("Cannot load environment variables from GitHub Actions")?;
-            let channel = std::fs::read_to_string(Path::new(CI_DIRECTORY).join("channel"))
+            let channel = read_to_string(Path::new(CI_DIRECTORY).join("channel"))
                 .context("Cannot read channel file")?;
 
-            calculate_job_matrix(db, gh_ctx, &channel).context("Failed to calculate job matrix")?;
+            calculate_job_matrix(load_db(jobs_path)?, gh_ctx, &channel)
+                .context("Failed to calculate job matrix")?;
+        }
+        Args::RunJobLocally { job_type, name } => {
+            run_workflow_locally(load_db(default_jobs_file)?, job_type, name)?
         }
-        Args::RunJobLocally { job_type, name } => run_workflow_locally(db, job_type, name)?,
     }
 
     Ok(())
 }
+
+fn read_to_string<P: AsRef<Path>>(path: P) -> anyhow::Result<String> {
+    let error = format!("Cannot read file {:?}", path.as_ref());
+    std::fs::read_to_string(path).context(error)
+}
diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs
new file mode 100644
index 00000000000..1d81d58f893
--- /dev/null
+++ b/src/ci/citool/tests/jobs.rs
@@ -0,0 +1,64 @@
+use std::process::{Command, Stdio};
+
+const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test-jobs.yml");
+
+#[test]
+fn auto_jobs() {
+    let stdout = get_matrix("push", "commit", "refs/heads/auto");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","SELECT_XCODE":"/Applications/Xcode_15.4.app","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}]
+    run_type=auto
+    "#);
+}
+
+#[test]
+fn try_jobs() {
+    let stdout = get_matrix("push", "commit", "refs/heads/try");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}]
+    run_type=try
+    "#);
+}
+
+#[test]
+fn try_custom_jobs() {
+    let stdout = get_matrix(
+        "push",
+        r#"This is a test PR
+
+try-job: aarch64-gnu
+try-job: dist-i686-msvc"#,
+        "refs/heads/try",
+    );
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"DIST_TRY_BUILD":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}]
+    run_type=try
+    "#);
+}
+
+#[test]
+fn pr_jobs() {
+    let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true}]
+    run_type=pr
+    "#);
+}
+
+fn get_matrix(event_name: &str, commit_msg: &str, branch_ref: &str) -> String {
+    let output = Command::new("cargo")
+        .args(["run", "-q", "calculate-job-matrix", "--jobs-file", TEST_JOBS_YML_PATH])
+        .env("GITHUB_EVENT_NAME", event_name)
+        .env("COMMIT_MESSAGE", commit_msg)
+        .env("GITHUB_REF", branch_ref)
+        .stdout(Stdio::piped())
+        .output()
+        .expect("Failed to execute command");
+
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    let stderr = String::from_utf8(output.stderr).unwrap();
+    if !output.status.success() {
+        panic!("cargo run failed: {}\n{}", stdout, stderr);
+    }
+    stdout
+}
diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml
new file mode 100644
index 00000000000..56b9ced2071
--- /dev/null
+++ b/src/ci/citool/tests/test-jobs.yml
@@ -0,0 +1,145 @@
+runners:
+  - &base-job
+    env: { }
+
+  - &job-linux-4c
+    os: ubuntu-24.04
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
+    <<: *base-job
+
+  - &job-linux-16c
+    os: ubuntu-22.04-16core-64gb
+    <<: *base-job
+
+  - &job-macos-m1
+    os: macos-14
+    <<: *base-job
+
+  - &job-windows
+    os: windows-2022
+    <<: *base-job
+
+  - &job-aarch64-linux
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
+    os: ubuntu-22.04-arm
+    <<: *base-job
+envs:
+  env-x86_64-apple-tests: &env-x86_64-apple-tests
+    SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
+    RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
+    RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+    # Ensure that host tooling is tested on our minimum supported macOS version.
+    MACOSX_DEPLOYMENT_TARGET: 10.12
+    MACOSX_STD_DEPLOYMENT_TARGET: 10.12
+    SELECT_XCODE: /Applications/Xcode_15.2.app
+    NO_LLVM_ASSERTIONS: 1
+    NO_DEBUG_ASSERTIONS: 1
+    NO_OVERFLOW_CHECKS: 1
+
+  production:
+    &production
+    DEPLOY_BUCKET: rust-lang-ci2
+    # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named
+    # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to
+    # rotate them in a single branch while keeping the old key in another
+    # branch, which wouldn't be possible if the key was named with the kind
+    # (caches, artifacts...).
+    CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+    ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+    AWS_REGION: us-west-1
+    TOOLSTATE_PUBLISH: 1
+
+  try:
+    <<: *production
+    # The following env var activates faster `try` builds in `opt-dist` by, e.g.
+    # - building only the more commonly useful components (we rarely need e.g. rust-docs in try
+    #   builds)
+    # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain
+    #
+    # If you *want* these to happen however, temporarily comment it before triggering a try build.
+    DIST_TRY_BUILD: 1
+
+  auto:
+    <<: *production
+
+  pr:
+    PR_CI_JOB: 1
+
+# Jobs that run on each push to a pull request (PR)
+# These jobs automatically inherit envs.pr, to avoid repeating
+# it in each job definition.
+pr:
+  - name: mingw-check
+    <<: *job-linux-4c
+  - name: mingw-check-tidy
+    continue_on_error: true
+    <<: *job-linux-4c
+
+# Jobs that run when you perform a try build (@bors try)
+# These jobs automatically inherit envs.try, to avoid repeating
+# it in each job definition.
+try:
+  - name: dist-x86_64-linux
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-16c
+
+# Main CI jobs that have to be green to merge a commit into master
+# These jobs automatically inherit envs.auto, to avoid repeating
+# it in each job definition.
+auto:
+  - name: aarch64-gnu
+    <<: *job-aarch64-linux
+
+  # The x86_64-gnu-llvm-18 job is split into multiple jobs to run tests in parallel.
+  # x86_64-gnu-llvm-18-1 skips tests that run in x86_64-gnu-llvm-18-{2,3}.
+  - name: x86_64-gnu-llvm-18-1
+    env:
+      RUST_BACKTRACE: 1
+      READ_ONLY_SRC: "0"
+      IMAGE: x86_64-gnu-llvm-18
+      DOCKER_SCRIPT: stage_2_test_set1.sh
+    <<: *job-linux-4c
+
+
+  ####################
+  #  macOS Builders  #
+  ####################
+
+  - name: aarch64-apple
+    env:
+      SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+      RUST_CONFIGURE_ARGS: >-
+        --enable-sanitizers
+        --enable-profiler
+        --set rust.jemalloc
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      SELECT_XCODE: /Applications/Xcode_15.4.app
+      USE_XCODE_CLANG: 1
+      # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
+      # supports the hardware, so only need to test it there.
+      MACOSX_DEPLOYMENT_TARGET: 11.0
+      MACOSX_STD_DEPLOYMENT_TARGET: 11.0
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+    <<: *job-macos-m1
+
+  ######################
+  #  Windows Builders  #
+  ######################
+
+  - name: dist-i686-msvc
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=i686-pc-windows-msvc
+        --host=i686-pc-windows-msvc
+        --target=i686-pc-windows-msvc,i586-pc-windows-msvc
+        --enable-full-tools
+        --enable-profiler
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-windows