From 612df796a576ed6651ea815052b7e3f2b0f79acb Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 2 Sep 2026 09:27:36 +0100 Subject: [PATCH 1/5] Expose each example as a unique test. Helps you see which example is failing to run. --- aarch32-tests/tests/tests.rs | 43 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/aarch32-tests/tests/tests.rs b/aarch32-tests/tests/tests.rs index fe33b3a..73a1154 100644 --- a/aarch32-tests/tests/tests.rs +++ b/aarch32-tests/tests/tests.rs @@ -137,25 +137,26 @@ fn main() { for group in MATRIX { for &target in group.targets { for variant in group.variants { - let mut name = format!("{}/{}", group.example, target); - if !variant.label.is_empty() { - name.push_str(&format!(" [{}]", variant.label)); - } - let example = group.example; - let target = target.to_string(); let rustflags = group.rustflags; - let flags: Vec<&'static str> = group - .flags - .iter() - .chain(variant.extra_flags) - .copied() - .collect(); - - tests.push(Trial::test(name, move || { - run_target(example, &target, &flags, rustflags); - Ok(()) - })); + let dir = test_utils::test_dir(&format!("examples/{example}")); + for bin in test_utils::discover_bins(&dir) { + let target = target.to_string(); + let flags: Vec<&'static str> = group + .flags + .iter() + .chain(variant.extra_flags) + .copied() + .collect(); + let mut name = format!("{}/{}/{}", group.example, target, bin); + if !variant.label.is_empty() { + name.push_str(&format!(" [{}]", variant.label)); + } + tests.push(Trial::test(name, move || { + run_target_bin(example, &bin, &target, &flags, rustflags); + Ok(()) + })); + } } } } @@ -163,7 +164,7 @@ fn main() { libtest_mimic::run(&args, tests).exit(); } -fn run_target(example: &str, target: &str, flags: &[&str], rustflags: Option<&str>) { +fn run_target_bin(example: &str, bin: &str, target: &str, flags: &[&str], rustflags: Option<&str>) { let dir = test_utils::test_dir(&format!("examples/{example}")); // Per-example folder: snapshots//-.snap @@ -174,8 +175,6 @@ fn run_target(example: &str, target: &str, flags: &[&str], rustflags: Option<&st settings.set_prepend_module_to_snapshot(false); let _guard = settings.bind_to_scope(); - for bin in test_utils::discover_bins(&dir) { - let stdout = test_utils::run_bin(&dir, &bin, target, flags, rustflags); - insta::assert_snapshot!(format!("{bin}-{target}"), stdout); - } + let stdout = test_utils::run_bin(&dir, &bin, target, flags, rustflags); + insta::assert_snapshot!(format!("{bin}-{target}"), stdout); } From e5bad59947113e4e0a302d41d920d3089dae43f0 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 2 Sep 2026 09:33:01 +0100 Subject: [PATCH 2/5] Add better default handlers for all the examples. Now if an unexpected exception occurs, it doesn't hang the CI. --- examples/mps3-an536-el2/memory.x | 16 ++++++++++++- examples/mps3-an536-el2/src/lib.rs | 36 ++++++++++++++++++++++++++++++ examples/mps3-an536/memory.x | 14 ++++++++++++ examples/mps3-an536/src/lib.rs | 36 ++++++++++++++++++++++++++++++ examples/versatileab/memory.x | 15 +++++++++++++ examples/versatileab/src/lib.rs | 36 ++++++++++++++++++++++++++++++ examples/xilinx-zynq-a9/memory.x | 14 ++++++++++++ examples/xilinx-zynq-a9/src/lib.rs | 36 ++++++++++++++++++++++++++++++ 8 files changed, 202 insertions(+), 1 deletion(-) diff --git a/examples/mps3-an536-el2/memory.x b/examples/mps3-an536-el2/memory.x index 89a0be6..91e7400 100644 --- a/examples/mps3-an536-el2/memory.x +++ b/examples/mps3-an536-el2/memory.x @@ -23,4 +23,18 @@ PROVIDE(_irq_stack_size = 8); PROVIDE(_fiq_stack_size = 8); PROVIDE(_sys_stack_size = 8); -PROVIDE(_num_cores = 2); \ No newline at end of file +PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/mps3-an536-el2/src/lib.rs b/examples/mps3-an536-el2/src/lib.rs index 604ca12..57ebc6a 100644 --- a/examples/mps3-an536-el2/src/lib.rs +++ b/examples/mps3-an536-el2/src/lib.rs @@ -254,3 +254,39 @@ unsafe fn make_gic() -> arm_gic::gicv3::GicV3<'static> { arm_gic::gicv3::GicCpuInterface::set_priority_mask(0x80); gic } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/mps3-an536/memory.x b/examples/mps3-an536/memory.x index aefc73c..8f52ae8 100644 --- a/examples/mps3-an536/memory.x +++ b/examples/mps3-an536/memory.x @@ -46,3 +46,17 @@ PROVIDE(_inter_stack_padding = 64); PROVIDE(_region_alignment = 64K); PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/mps3-an536/src/lib.rs b/examples/mps3-an536/src/lib.rs index 2d7bf4c..f441bb1 100644 --- a/examples/mps3-an536/src/lib.rs +++ b/examples/mps3-an536/src/lib.rs @@ -298,3 +298,39 @@ pub extern "C" fn _asm_secondary_core_park() { fpga_led = const FPGA_LED ); } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/versatileab/memory.x b/examples/versatileab/memory.x index 65a2a3d..eec1806 100644 --- a/examples/versatileab/memory.x +++ b/examples/versatileab/memory.x @@ -20,3 +20,18 @@ PROVIDE(_abt_stack_size = 16K); PROVIDE(_irq_stack_size = 64); PROVIDE(_fiq_stack_size = 64); PROVIDE(_sys_stack_size = 16K); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); + diff --git a/examples/versatileab/src/lib.rs b/examples/versatileab/src/lib.rs index 3d6ff6e..a233e7d 100644 --- a/examples/versatileab/src/lib.rs +++ b/examples/versatileab/src/lib.rs @@ -103,3 +103,39 @@ fn stack_dump() { } } } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} diff --git a/examples/xilinx-zynq-a9/memory.x b/examples/xilinx-zynq-a9/memory.x index 13de51c..8667b2c 100644 --- a/examples/xilinx-zynq-a9/memory.x +++ b/examples/xilinx-zynq-a9/memory.x @@ -27,3 +27,17 @@ PROVIDE(_sys_stack_size = 16K); /* This is a dual-core Cortex-A9, so reserve a set of stacks per core. */ PROVIDE(_num_cores = 2); + +EXTERN(_unexpected_undefined_exception_handler); +EXTERN(_unexpected_svc_exception_handler); +EXTERN(_unexpected_hvc_exception_handler); +EXTERN(_unexpected_prefetch_abort_exception_handler); +EXTERN(_unexpected_data_abort_exception_handler); +EXTERN(_unexpected_irq_exception_handler); + +PROVIDE(_undefined_handler = _unexpected_undefined_exception_handler); +PROVIDE(_svc_handler = _unexpected_svc_exception_handler); +PROVIDE(_hvc_handler = _unexpected_hvc_exception_handler); +PROVIDE(_prefetch_abort_handler = _unexpected_prefetch_abort_exception_handler); +PROVIDE(_data_abort_handler = _unexpected_data_abort_exception_handler); +PROVIDE(_irq_handler = _unexpected_irq_exception_handler); diff --git a/examples/xilinx-zynq-a9/src/lib.rs b/examples/xilinx-zynq-a9/src/lib.rs index ffde4ec..5e3fd2c 100644 --- a/examples/xilinx-zynq-a9/src/lib.rs +++ b/examples/xilinx-zynq-a9/src/lib.rs @@ -187,3 +187,39 @@ pub unsafe fn make_gic() -> arm_gic::gicv2::GicV2<'static> { gic.setup(); gic } + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_undefined_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_undefined_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_svc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_svc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_hvc_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_hvc_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_prefetch_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_prefetch_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_data_abort_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_data_abort_exception_handler!"); + semihosting::process::exit(1); +} + +#[unsafe(no_mangle)] +pub extern "C" fn _unexpected_irq_exception_handler() -> ! { + semihosting::eprintln!("In _unexpected_irq_exception_handler!"); + semihosting::process::exit(1); +} From 472e4397e45bf6a2ce5dda1ea546bcedf6ead0ca Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 2 Sep 2026 09:50:07 +0100 Subject: [PATCH 3/5] Trim the number of CI jobs Instead of using a matrix over (build, clippy, doc), have those just be three steps in the same job. This should reduce the number of jobs that CI spawns and hopefully reduce over-all runtime because I think currently we hit some limit on the number of parallel jobs. --- .github/workflows/build.yml | 70 +++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0982a1c..f82bc39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,10 +30,6 @@ jobs: strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.msrv-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 @@ -43,9 +39,15 @@ jobs: run: | rustup install 1.93 rustup target add ${{ matrix.target }} --toolchain=1.93 - - name: Run just + - name: Run build run: | - RUSTUP_TOOLCHAIN=1.93 just ${{ matrix.action }}-tier2 ${{ matrix.target }} + RUSTUP_TOOLCHAIN=1.93 just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + RUSTUP_TOOLCHAIN=1.93 just clippy-tier2 ${{ matrix.target }} + - name: Run doc + run: | + RUSTUP_TOOLCHAIN=1.93 just doc-tier2 ${{ matrix.target }} # Build the workspace for a target architecture using latest stable build-tier2-stable: @@ -54,10 +56,6 @@ jobs: strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.stable-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 @@ -67,9 +65,15 @@ jobs: run: | rustup install stable rustup target add ${{ matrix.target }} --toolchain=stable - - name: Run just + - name: Run build + run: | + RUSTUP_TOOLCHAIN=stable just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + RUSTUP_TOOLCHAIN=stable just clippy-tier2 ${{ matrix.target }} + - name: Run doc run: | - RUSTUP_TOOLCHAIN=stable just ${{ matrix.action }}-tier2 ${{ matrix.target }} + RUSTUP_TOOLCHAIN=stable just doc-tier2 ${{ matrix.target }} # Build the workspace for all tier2 target architectures using rust-toolchain.toml build-tier2-nightly: @@ -78,18 +82,20 @@ jobs: strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier2-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier2 ${{ matrix.target }} + - name: Run clippy + run: | + just clippy-tier2 ${{ matrix.target }} + - name: Run doc run: | - just ${{ matrix.action }}-tier2 ${{ matrix.target }} + just doc-tier2 ${{ matrix.target }} # Build the workspace for all tier3 target architectures using rust-toolchain.toml build-tier3-nightly: @@ -98,18 +104,20 @@ jobs: strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier3-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier3 ${{ matrix.target }} + - name: Run clippy run: | - just ${{ matrix.action }}-tier3 ${{ matrix.target }} + just clippy-tier3 ${{ matrix.target }} + - name: Run doc + run: | + just doc-tier3 ${{ matrix.target }} # Build the workspace for all tier3 non atomic target architectures using rust-toolchain.toml build-tier3-no-atomics: @@ -118,18 +126,20 @@ jobs: strategy: matrix: target: ${{ fromJSON(needs.setup.outputs.nightly-tier3-noatomic-targets) }} - action: - - build - - clippy - - doc steps: - name: Checkout uses: actions/checkout@v7 - name: Install Just uses: taiki-e/install-action@just - - name: Run just + - name: Run build + run: | + just build-tier3-no-atomics ${{ matrix.target }} + - name: Run clippy + run: | + just clippy-tier3-no-atomics ${{ matrix.target }} + - name: Run doc run: | - just ${{ matrix.action }}-tier3-no-atomics ${{ matrix.target }} + just doc-tier3-no-atomics ${{ matrix.target }} # Build the host-only stuff on stable and MSRV build-arm-targets: From 1dffdee513b8b9eb16b9cd90bda7e22e9728a8c2 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 2 Sep 2026 10:04:37 +0100 Subject: [PATCH 4/5] Justfile did a "cargo build" not a "cargo clippy" --- .github/workflows/build.yml | 2 ++ justfile | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f82bc39..617b33a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,6 +39,7 @@ jobs: run: | rustup install 1.93 rustup target add ${{ matrix.target }} --toolchain=1.93 + rustup component add clippy --toolchain=1.93 - name: Run build run: | RUSTUP_TOOLCHAIN=1.93 just build-tier2 ${{ matrix.target }} @@ -65,6 +66,7 @@ jobs: run: | rustup install stable rustup target add ${{ matrix.target }} --toolchain=stable + rustup component add clippy --toolchain=stable - name: Run build run: | RUSTUP_TOOLCHAIN=stable just build-tier2 ${{ matrix.target }} diff --git a/justfile b/justfile index 07c293e..7d851ce 100644 --- a/justfile +++ b/justfile @@ -238,9 +238,9 @@ clippy-tier3 target: # Checks all the cross-compiled workspace passes the clippy lints clippy-tier2 target: - cargo build --target {{target}} {{verbose}} - cargo build --target {{target}} --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} - cargo build --target {{target}} --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} + cargo clippy --target {{target}} {{verbose}} + cargo clippy --target {{target}} --features "serde, defmt, critical-section-multi-core, check-asm" {{verbose}} + cargo clippy --target {{target}} --features "serde, defmt, critical-section-single-core, check-asm" {{verbose}} # Run all the tests test: test-cargo test-qemu From 2020847937bbfeebca81571aefc82dca60501802 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 2 Sep 2026 10:29:21 +0100 Subject: [PATCH 5/5] Set a 10 minute timeout on every job. No job should take more than 5 minutes, but we're seeing Github CI regularly hang for over an hour (e.g. running apt-get). --- .github/workflows/build.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 617b33a..b5027fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,7 @@ jobs: # Build the workspace for a target architecture using the MSRV build-tier2-msrv: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -53,6 +54,7 @@ jobs: # Build the workspace for a target architecture using latest stable build-tier2-stable: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -80,6 +82,7 @@ jobs: # Build the workspace for all tier2 target architectures using rust-toolchain.toml build-tier2-nightly: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -102,6 +105,7 @@ jobs: # Build the workspace for all tier3 target architectures using rust-toolchain.toml build-tier3-nightly: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -124,6 +128,7 @@ jobs: # Build the workspace for all tier3 non atomic target architectures using rust-toolchain.toml build-tier3-no-atomics: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -146,6 +151,7 @@ jobs: # Build the host-only stuff on stable and MSRV build-arm-targets: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: @@ -177,6 +183,7 @@ jobs: # Gather all the above build jobs together for the purposes of getting an overall pass-fail build-all: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: - build-tier2-msrv - build-tier2-stable @@ -190,6 +197,7 @@ jobs: # Format the workspace fmt-check: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -203,6 +211,7 @@ jobs: # Run clippy on the examples clippy-examples: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -220,6 +229,7 @@ jobs: # Run the unit tests test-cargo: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup steps: - name: Checkout @@ -233,6 +243,7 @@ jobs: # Run some programs in QEMU 9 test-qemu: runs-on: ubuntu-24.04 + timeout-minutes: 10 needs: setup strategy: matrix: