diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc1fb8c13..ab6e7b516 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1473,7 +1473,7 @@ jobs: startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && inputs.release_artifacts == 'full') - needs: [rust-check-shared, rust-check-macos, rust-test, rust-test-servo, rust-deny, sdk, ui, e2e, web-assets, python, python-generated] + needs: [rust-check-shared, rust-check-macos, rust-test, rust-test-servo, rust-windows, rust-deny, sdk, ui, e2e, web-assets, python, python-generated] strategy: fail-fast: false matrix: @@ -1822,7 +1822,7 @@ jobs: startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && inputs.release_artifacts == 'full') - needs: [rust-check-shared, rust-check-macos, rust-test, rust-test-servo, rust-deny, sdk, ui, e2e, web-assets, python, python-generated] + needs: [rust-check-shared, rust-check-macos, rust-test, rust-test-servo, rust-windows, rust-deny, sdk, ui, e2e, web-assets, python, python-generated] strategy: fail-fast: false matrix: diff --git a/crates/hypercolor-macos-owner/tests/coordinator_tests.rs b/crates/hypercolor-macos-owner/tests/coordinator_tests.rs index 132685900..388b8a953 100644 --- a/crates/hypercolor-macos-owner/tests/coordinator_tests.rs +++ b/crates/hypercolor-macos-owner/tests/coordinator_tests.rs @@ -550,41 +550,44 @@ fn stop_request_keeps_new_owner_publication_outside_the_validated_window() { let prior = store .publish_owner(MacosDaemonOwner::DirectLaunchd, identity("direct-old", 101)) .expect("initial owner should publish"); - let publisher_store = store.clone(); - let (start_tx, start_rx) = mpsc::sync_channel(0); - let (attempt_tx, attempt_rx) = mpsc::sync_channel(0); - let (published_tx, published_rx) = mpsc::sync_channel(0); - let publisher = std::thread::spawn(move || { - start_rx.recv().expect("publisher should be released"); - attempt_tx.send(()).expect("attempt should be visible"); - let replacement = publisher_store - .publish_owner(MacosDaemonOwner::DirectLaunchd, identity("direct-new", 202)) - .expect("replacement should publish after the stop request"); - published_tx - .send(replacement) - .expect("replacement should be observable"); - }); + let replacement = std::thread::scope(|scope| { + let publisher_store = store.clone(); + let (start_tx, start_rx) = mpsc::sync_channel(0); + let (attempt_tx, attempt_rx) = mpsc::sync_channel(0); + let (published_tx, published_rx) = mpsc::sync_channel(1); + let publisher = scope.spawn(move || { + start_rx.recv().expect("publisher should be released"); + attempt_tx.send(()).expect("attempt should be visible"); + let replacement = publisher_store + .publish_owner(MacosDaemonOwner::DirectLaunchd, identity("direct-new", 202)) + .expect("replacement should publish after the stop request"); + published_tx + .send(()) + .expect("replacement should be observable"); + replacement + }); - store - .request_stop_if_current(&prior.incarnation(), || { - start_tx.send(()).expect("publisher should start"); - attempt_rx - .recv() - .expect("publisher should attempt publication"); - assert!( - published_rx - .recv_timeout(Duration::from_millis(50)) - .is_err(), - "publication must remain blocked while the stop request is active" - ); - Ok(()) - }) - .expect("exact stop request should run"); + store + .request_stop_if_current(&prior.incarnation(), || { + start_tx.send(()).expect("publisher should start"); + attempt_rx + .recv() + .expect("publisher should attempt publication"); + assert!( + matches!( + published_rx.recv_timeout(Duration::from_millis(50)), + Err(mpsc::RecvTimeoutError::Timeout) + ), + "publication must remain blocked while the stop request is active" + ); + Ok(()) + }) + .expect("exact stop request should run"); - let replacement = published_rx - .recv_timeout(Duration::from_secs(1)) - .expect("publication should complete after the stop request"); - publisher.join().expect("publisher should finish"); + // Completion follows lock release; filesystem latency has no deadline. + // The scope also keeps the temporary store alive when an assertion fails. + publisher.join().expect("publisher should finish") + }); assert!(replacement.owner_epoch > prior.owner_epoch); } diff --git a/scripts/tests/macos-ci-coverage.test.mjs b/scripts/tests/macos-ci-coverage.test.mjs index 8cc012204..2a28611a8 100644 --- a/scripts/tests/macos-ci-coverage.test.mjs +++ b/scripts/tests/macos-ci-coverage.test.mjs @@ -54,11 +54,12 @@ test('cache ownership and restored target directories agree across lanes', () => assert.equal(condition('Save Rust build caches'), 'always()'); }); -test('both release builders still require the entire macOS matrix', () => { +test('both release builders require the macOS matrix and Windows tests', () => { for (const id of ['build-release', 'build-native-app']) { const body = workflow.match(new RegExp(`^ ${id}:\\n([\\s\\S]*?)(?=^ [a-z][\\w-]*:)`, 'm'))?.[1]; assert.ok(body, `missing release builder: ${id}`); const needs = body.match(/^ needs: \[(.+)\]$/m)?.[1].split(', ').map((value) => value.trim()); assert.ok(needs?.includes('rust-check-macos'), `${id} must wait for both lanes on both architectures`); + assert.ok(needs?.includes('rust-windows'), `${id} must wait for Windows tests before producing release artifacts`); } });