ci: add check-macos build gate for hot platform-guarded files#3223
Merged
ten9876 merged 1 commit intoMay 27, 2026
Merged
Conversation
Add a check-macos job to .github/workflows/ci.yml that mirrors
check-windows: same dorny/paths-filter trigger (build-changed),
same hot-file coverage (CMakeLists.txt, third_party/**,
.github/workflows/**, src/gui/MainWindow.{cpp,h},
src/core/AudioEngine.{cpp,h}), Apple Silicon runner only,
build-only (no codesign / no macdeployqt / no DMG / no
notarization — those stay in macos-dmg.yml on tag push).
Closes a real coverage gap: today macOS validation only runs on
tag push via macos-dmg.yml, so a Linux-passing change that breaks
macOS compile or link is discovered at release time. AudioEngine
and MainWindow both carry dense Q_OS_MAC / CoreAudio / Cocoa-bridge
code paths that Linux clang doesn't exercise.
Cost is bounded by the same path filter that gates check-windows:
the build group only trips when CMakeLists.txt, third_party/,
workflows, or the two hot files change. macos-15 Apple Silicon
runners are ~10× Linux per-minute, but at the recent build-filter
trip rate (2-3× per week) total additional spend is ~$20/month.
Comment update on the existing filter block: reworded "force the
Windows CI build" → "force the cross-platform CI build" since the
same triggers now protect both check-windows and check-macos.
Same paths, no new entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
ten9876
added a commit
that referenced
this pull request
May 28, 2026
…per (#3239) Completes the platform matrix promised in #3232. Linux (evdev) landed in #3238; this PR adds the Windows (hidapi) and macOS (IOKit) sides. The mapper dialog drops its Linux guard and now builds everywhere. Architecture ------------ All three backends expose the same Qt signal contract: tuneSteps(int) - rotary delta buttonEvent(sig, action) - canonical Linux-keycode-name strings connectionChanged(bool, name) A new typedef `UlanziDialBackend` (src/core/UlanziDialBackend.h) resolves to the right concrete class per platform. Mapper dialog and MainWindow dispatcher use only the alias and have no platform switches of their own. Windows (UlanziDialWindowsManager) ---------------------------------- - hidapi (already a project dep) enumerates HID devices, matches by product_string substring "Ulanzi Dial" - Opens every matching interface (the dial enumerates as multiple HID interfaces on Windows: Keyboard + Consumer Control, possibly Mouse) and polls each via QTimer at 5ms intervals - HID report parsing: standard 8-byte keyboard report (modifier mask + up-to-6-keys array, diffed across frames for transitions) and Consumer Control reports (2-byte usage code) - HID usage codes mapped to canonical Linux keycode integers so the signature strings (`KEY_PLAYPAUSE`, `Ctrl+V`, ...) match Linux exactly and `kPillSpecs` is unchanged - Chord assembly state machine identical to the Linux backend - Hot-plug via 3s rescan timer - LIMITATION: no exclusive-claim equivalent yet. The dial's keystrokes still reach the focused window because hidapi doesn't suppress OS input routing. RawInput + RIDEV_NOLEGACY is the proper fix; tracked for a follow-up macOS (UlanziDialMacOSManager) ------------------------------ - IOKit HID Manager with device-matching dictionary ({ kIOHIDProductKey: "Ulanzi Dial" }) - `IOHIDManagerOpen` with `kIOHIDOptionsTypeSeizeDevice` -- the documented macOS exclusive-claim mechanism. Equivalent to Linux EVIOCGRAB: when seized, the dial's events stop reaching the OS keyboard stack, so its media keys don't leak to the focused window - Event-driven via `IOHIDManagerRegisterInputValueCallback`; no polling - Same usage-page-to-Linux-keycode mapping and chord assembly as Windows backend - Scheduled on `CFRunLoopGetMain()` (IOKit requires a CFRunLoop, and only the main thread has one integrated with Qt's event loop on macOS). MainWindow conditionally skips `moveToThread` on macOS to match this constraint - Hot-plug native via IOHIDManager device-matching/removal callbacks Build wiring (CMakeLists.txt) ----------------------------- - UlanziDialBackend.h + UlanziDialMapperDialog.{cpp,h}: unconditional - EvdevEncoderManager.{cpp,h}: UNIX AND NOT APPLE (Linux) - UlanziDialWindowsManager.{cpp,h}: WIN32 - UlanziDialMacOSManager.{cpp,h}: APPLE - macOS links -framework IOKit and -framework CoreFoundation Tested ------ - Linux: compiles + runs as before (Linux behaviour unchanged; same EvdevEncoderManager underneath the alias) - Windows + macOS: compile validation gated by CI (check-windows from #3210 and check-macos from #3223). Live testing on hardware happens in the user's environment Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
G6PWY-Chris
pushed a commit
to G6PWY-Chris/AetherSDR
that referenced
this pull request
Jun 22, 2026
…sdr#3223) Add a check-macos job to .github/workflows/ci.yml that mirrors check-windows: same dorny/paths-filter trigger (build-changed), same hot-file coverage (CMakeLists.txt, third_party/**, .github/workflows/**, src/gui/MainWindow.{cpp,h}, src/core/AudioEngine.{cpp,h}), Apple Silicon runner only, build-only (no codesign / no macdeployqt / no DMG / no notarization — those stay in macos-dmg.yml on tag push). Closes a real coverage gap: today macOS validation only runs on tag push via macos-dmg.yml, so a Linux-passing change that breaks macOS compile or link is discovered at release time. AudioEngine and MainWindow both carry dense Q_OS_MAC / CoreAudio / Cocoa-bridge code paths that Linux clang doesn't exercise. Cost is bounded by the same path filter that gates check-windows: the build group only trips when CMakeLists.txt, third_party/, workflows, or the two hot files change. macos-15 Apple Silicon runners are ~10× Linux per-minute, but at the recent build-filter trip rate (2-3× per week) total additional spend is ~$20/month. Comment update on the existing filter block: reworded "force the Windows CI build" → "force the cross-platform CI build" since the same triggers now protect both check-windows and check-macos. Same paths, no new entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
G6PWY-Chris
pushed a commit
to G6PWY-Chris/AetherSDR
that referenced
this pull request
Jun 22, 2026
…per (aethersdr#3239) Completes the platform matrix promised in aethersdr#3232. Linux (evdev) landed in aethersdr#3238; this PR adds the Windows (hidapi) and macOS (IOKit) sides. The mapper dialog drops its Linux guard and now builds everywhere. Architecture ------------ All three backends expose the same Qt signal contract: tuneSteps(int) - rotary delta buttonEvent(sig, action) - canonical Linux-keycode-name strings connectionChanged(bool, name) A new typedef `UlanziDialBackend` (src/core/UlanziDialBackend.h) resolves to the right concrete class per platform. Mapper dialog and MainWindow dispatcher use only the alias and have no platform switches of their own. Windows (UlanziDialWindowsManager) ---------------------------------- - hidapi (already a project dep) enumerates HID devices, matches by product_string substring "Ulanzi Dial" - Opens every matching interface (the dial enumerates as multiple HID interfaces on Windows: Keyboard + Consumer Control, possibly Mouse) and polls each via QTimer at 5ms intervals - HID report parsing: standard 8-byte keyboard report (modifier mask + up-to-6-keys array, diffed across frames for transitions) and Consumer Control reports (2-byte usage code) - HID usage codes mapped to canonical Linux keycode integers so the signature strings (`KEY_PLAYPAUSE`, `Ctrl+V`, ...) match Linux exactly and `kPillSpecs` is unchanged - Chord assembly state machine identical to the Linux backend - Hot-plug via 3s rescan timer - LIMITATION: no exclusive-claim equivalent yet. The dial's keystrokes still reach the focused window because hidapi doesn't suppress OS input routing. RawInput + RIDEV_NOLEGACY is the proper fix; tracked for a follow-up macOS (UlanziDialMacOSManager) ------------------------------ - IOKit HID Manager with device-matching dictionary ({ kIOHIDProductKey: "Ulanzi Dial" }) - `IOHIDManagerOpen` with `kIOHIDOptionsTypeSeizeDevice` -- the documented macOS exclusive-claim mechanism. Equivalent to Linux EVIOCGRAB: when seized, the dial's events stop reaching the OS keyboard stack, so its media keys don't leak to the focused window - Event-driven via `IOHIDManagerRegisterInputValueCallback`; no polling - Same usage-page-to-Linux-keycode mapping and chord assembly as Windows backend - Scheduled on `CFRunLoopGetMain()` (IOKit requires a CFRunLoop, and only the main thread has one integrated with Qt's event loop on macOS). MainWindow conditionally skips `moveToThread` on macOS to match this constraint - Hot-plug native via IOHIDManager device-matching/removal callbacks Build wiring (CMakeLists.txt) ----------------------------- - UlanziDialBackend.h + UlanziDialMapperDialog.{cpp,h}: unconditional - EvdevEncoderManager.{cpp,h}: UNIX AND NOT APPLE (Linux) - UlanziDialWindowsManager.{cpp,h}: WIN32 - UlanziDialMacOSManager.{cpp,h}: APPLE - macOS links -framework IOKit and -framework CoreFoundation Tested ------ - Linux: compiles + runs as before (Linux behaviour unchanged; same EvdevEncoderManager underneath the alias) - Windows + macOS: compile validation gated by CI (check-windows from aethersdr#3210 and check-macos from aethersdr#3223). Live testing on hardware happens in the user's environment Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a check-macos job to .github/workflows/ci.yml that mirrors
check-windows: same dorny/paths-filter trigger (build-changed),
same hot-file coverage (CMakeLists.txt, third_party/,
.github/workflows/, src/gui/MainWindow.{cpp,h},
src/core/AudioEngine.{cpp,h}), Apple Silicon runner only,
build-only (no codesign / no macdeployqt / no DMG / no
notarization — those stay in macos-dmg.yml on tag push).
Closes a real coverage gap: today macOS validation only runs on
tag push via macos-dmg.yml, so a Linux-passing change that breaks
macOS compile or link is discovered at release time. AudioEngine
and MainWindow both carry dense Q_OS_MAC / CoreAudio / Cocoa-bridge
code paths that Linux clang doesn't exercise.
Cost is bounded by the same path filter that gates check-windows:
the build group only trips when CMakeLists.txt, third_party/,
workflows, or the two hot files change. macos-15 Apple Silicon
runners are ~10× Linux per-minute, but at the recent build-filter
trip rate (2-3× per week) total additional spend is ~$20/month.
Comment update on the existing filter block: reworded "force the
Windows CI build" → "force the cross-platform CI build" since the
same triggers now protect both check-windows and check-macos.
Same paths, no new entries.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com