Skip to content

ci: stabilize and scope pull request checks - #20

Merged
2dubu merged 2 commits into
mainfrom
fix/async-loader-test-stability
Aug 20, 2026
Merged

2dubu merged 2 commits into
mainfrom
fix/async-loader-test-stability

Conversation

@2dubu

@2dubu 2dubu commented Aug 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Replace polling-based asynchronous UI tests with callback-backed event waits.
  • Skip the macOS and iOS test jobs for documentation-only or repository-metadata-only changes while still reporting required checks.
  • Bound CI jobs with explicit timeouts, update actions/checkout to v6, and make Xcode discovery actionlint-clean.

Background

The loader tests polled phase every 50 milliseconds until a wall-clock deadline. If the loader completed during the final sleep, the loop could cross the deadline and record a timeout without observing the completed state. The failing CI log demonstrated this mismatch: the timeout was recorded while the final phase was already the expected .success or .failure value. Repeated polling from @MainActor tests also introduced unnecessary executor wake-ups.

Separately, the workflow ran both macOS and iOS jobs for documentation-only pull requests and had no explicit job timeouts. One iOS Simulator run remained in xcodebuild test for more than 20 minutes. GitHub's default job timeout would otherwise allow a stuck runner to remain active for up to six hours.

Solution

  • Add a reusable test helper that races a callback-backed AsyncStream event against an explicit timeout, suspending instead of polling the main actor.
  • Update loader and UIKit view tests to wait for the actual success or failure callback, then verify the resulting state and callback metadata.
  • Cover both event delivery and timeout cancellation in dedicated helper tests.
  • Add a lightweight Detect code changes job. The macOS and iOS jobs run only when Sources, Tests, Examples, package configuration, or CI workflows change.
  • Use job-level conditions instead of workflow-level path filters so documentation-only pull requests still report successful skipped checks and remain compatible with required branch-protection checks.
  • Limit the macOS job to 10 minutes and the iOS job to 15 minutes.
  • Update actions/checkout from v4 to v6 and replace the warning-prone ls | grep Xcode discovery with find.

Related Issue

None. This is CI reliability and maintenance work discovered while validating pull request #19.

Verification

  • Tests added or updated:
    • Added event-delivery and timeout-cancellation coverage for the asynchronous test helper.
    • Updated loader success and failure tests to verify callback type, callback metadata, final phase, and cache behavior without polling.
    • Updated UIKit view success and forced-reload tests to wait for callback events without polling.
    • Verified documentation-only changes are classified to skip expensive jobs and code changes are classified to run them.
  • Commands run:
    • actionlint .github/workflows/ci.yml
    • swift package resolve
    • swift build -c debug
    • swift test --filter PaletteKitTests --filter PaletteKitInsightsTests — 55 tests, 0 failures.
    • Focused iOS asynchronous suites with -test-iterations 20 — 320 test runs, 0 failures.
    • Full iOS core suite with -test-iterations 10 — 1,410 test runs, 0 failures.
    • git diff --check
  • Environment and platforms:
    • macOS 26.5.1, Xcode 26.4, Swift 6.3.
    • iPhone 17 Pro Simulator running iOS 26.4.
    • The workflow continues to target GitHub-hosted macos-15 runners.

Compatibility and Impact

  • Public API: None.
  • Behavioral impact: Package runtime behavior is unchanged. Only test synchronization and CI scheduling behavior change. Documentation-only changes now skip the expensive build and simulator jobs.
  • Performance impact: No production performance impact. Asynchronous tests no longer wake the main actor every 50 milliseconds, and documentation-only pull requests no longer consume macOS runners.
  • Affected platforms: GitHub Actions and iOS/UIKit test targets. Shipping library behavior on supported Apple platforms is unaffected.

Checklist

  • This pull request is focused and contains no unrelated changes.
  • Tests were added or updated where behavior changed, or I explained why they are not needed.
  • Regression tests cover the intended behavior or root cause rather than only a reported sample.
  • Public API changes are documented and reflected in the changelog, or this pull request has none.
  • I considered source compatibility, behavioral changes, and performance impact.

@2dubu
2dubu marked this pull request as ready for review August 20, 2026 16:38
Select and boot the newest compatible iOS 26 runtime, split async and remaining core suites with step-level timeouts, and preserve xcresult and simulator diagnostics on failure.
@2dubu
2dubu merged commit 85f98c2 into main Aug 20, 2026
3 checks passed
@2dubu
2dubu deleted the fix/async-loader-test-stability branch August 20, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant