From b92b1dfc98bba751bdc7d18f92b911f74dd9922f Mon Sep 17 00:00:00 2001 From: Su Yang Date: Mon, 9 Nov 2026 18:21:42 +0800 Subject: [PATCH 1/2] Retry transient Windows CMake download failures --- validation/setup_windows.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/validation/setup_windows.ps1 b/validation/setup_windows.ps1 index 49adace1..6044155e 100644 --- a/validation/setup_windows.ps1 +++ b/validation/setup_windows.ps1 @@ -6,8 +6,11 @@ $ErrorActionPreference = 'Stop' $Name = "cmake-$Version-windows-$Architecture.zip" $Base = "https://github.com/Kitware/CMake/releases/download/v$Version" $Destination = Join-Path $env:RUNNER_TEMP 'linkerbot-cmake' -Invoke-WebRequest "$Base/$Name" -OutFile "$env:RUNNER_TEMP/$Name" -Invoke-WebRequest "$Base/cmake-$Version-SHA-256.txt" -OutFile "$env:RUNNER_TEMP/cmake-checksums.txt" +# GitHub release downloads can return transient 5xx responses on hosted runners. +# Retry both assets before failing; checksum verification below remains mandatory. +$DownloadOptions = @{ MaximumRetryCount = 5; RetryIntervalSec = 5; TimeoutSec = 120 } +Invoke-WebRequest "$Base/$Name" -OutFile "$env:RUNNER_TEMP/$Name" @DownloadOptions +Invoke-WebRequest "$Base/cmake-$Version-SHA-256.txt" -OutFile "$env:RUNNER_TEMP/cmake-checksums.txt" @DownloadOptions $Line = @(Get-Content "$env:RUNNER_TEMP/cmake-checksums.txt" | Where-Object { $_ -match " $([regex]::Escape($Name))$" }) if ($Line.Count -ne 1) { throw 'CMake checksum entry missing or ambiguous' } $Expected = ($Line[0] -split '\s+')[0] From b362e5439b0854e78673c67f1b07188e2b9f731a Mon Sep 17 00:00:00 2001 From: Su Yang Date: Mon, 9 Nov 2026 18:57:33 +0800 Subject: [PATCH 2/2] Allow worker scheduling time in configured-speed cache regression --- tests/hand/device/test_device.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/hand/device/test_device.cpp b/tests/hand/device/test_device.cpp index af69e96a..279387df 100644 --- a/tests/hand/device/test_device.cpp +++ b/tests/hand/device/test_device.cpp @@ -3923,6 +3923,9 @@ TEST_CASE("L20Lite verified firmware rejects unavailable scalar force without IO TEST_CASE("L20Lite measured speed never populates or overwrites configured speed", "[comm][device][l20lite][configured-speed]") { + // This checks cache semantics, not the default request deadline. Even cache + // reads run through the device worker, which can be delayed on loaded CI hosts. + const auto timeout = std::chrono::seconds{2}; FakeTransport *transport = nullptr; HandDevice device(config_for(Model::kL20Lite), [&] { auto next = std::make_unique(); @@ -3944,16 +3947,16 @@ TEST_CASE("L20Lite measured speed never populates or overwrites configured speed } return classic_angle_reply(Model::kL20Lite, request); }); - REQUIRE(device.get_speeds().raw == std::vector(10, 0)); - REQUIRE_THROWS_AS(device.get_configured_speeds(), DeviceNotReadyError); + REQUIRE(device.get_speeds(timeout).raw == std::vector(10, 0)); + REQUIRE_THROWS_AS(device.get_configured_speeds(timeout), DeviceNotReadyError); REQUIRE_FALSE(device.get_snapshot().configured_speeds.has_value()); REQUIRE(completed(device.set_speeds(std::vector(10, 20))).stage() == CommandStage::kAcknowledged); - const auto configured = device.get_configured_speeds(); + const auto configured = device.get_configured_speeds(timeout); REQUIRE(configured.raw == std::vector(10, 20)); REQUIRE(configured.meta.delivery == TelemetryDelivery::kCommandResponse); - REQUIRE(device.get_speeds().raw == std::vector(10, 0)); + REQUIRE(device.get_speeds(timeout).raw == std::vector(10, 0)); const auto sent = transport->sent().size(); - REQUIRE(device.get_configured_speeds().raw == configured.raw); + REQUIRE(device.get_configured_speeds(timeout).raw == configured.raw); REQUIRE(transport->sent().size() == sent); const auto snapshot = device.get_snapshot(); REQUIRE(test_support::require_value(snapshot.measured_speeds).raw == std::vector(10, 0)); @@ -3961,7 +3964,7 @@ TEST_CASE("L20Lite measured speed never populates or overwrites configured speed REQUIRE(snapshot.joints[0].measured_speed_raw == 0); REQUIRE(snapshot.joints[0].configured_speed_raw == 20); device.recover(); - REQUIRE_THROWS_AS(device.get_configured_speeds(), DeviceNotReadyError); + REQUIRE_THROWS_AS(device.get_configured_speeds(timeout), DeviceNotReadyError); device.close(); }