Skip to content

feat(mqtt): per-topic control, CW keyer, radio state, AX.25, debug logging #3307

feat(mqtt): per-topic control, CW keyer, radio state, AX.25, debug logging

feat(mqtt): per-topic control, CW keyer, radio state, AX.25, debug logging #3307

Workflow file for this run

name: CI
on:
pull_request:
branches: [main]
# Post-merge guard. We dropped the "Require branches up to date before
# merging" branch-protection bit because it forced a CI rerun on every
# PR whenever main moved (~15–25 min × N stale PRs per batch day).
# The trade-off is: CI now runs on the merged commit itself, so any
# semantic conflict that slipped past three-way merge surfaces on main
# within ~10 min and triggers normal failure notifications.
push:
branches: [main]
# Least-privilege GITHUB_TOKEN. CI only needs to read repo contents to
# build and test — no writes, no token-bearing API calls. Any future job
# that needs more (e.g. publishing a comment) must opt in at the job level.
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/ten9876/aethersdr-ci:latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Setup DeepFilterNet3 (DFNR)
run: bash scripts/setup/setup-deepfilter.sh
- name: Configure
run: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build
run: cmake --build build -j$(nproc)
# Cross-platform build check — runs on every PR (no path gating).
#
# History: previously gated by a `check-paths` job on a hand-maintained
# allow-list of files known to carry `#ifdef Q_OS_WIN` / `Q_OS_MAC`
# branches (CMakeLists, third_party/, workflows, MainWindow,
# AudioEngine). The allow-list was a chronic leaker — every time a
# new platform-guarded path got added to a different file, the gap
# surfaced as a release-time regression: #796 (origin), #2671
# (MainWindow added after a miss), #3052 (AudioEngine added after a
# miss), #3210 (re-added after relapse), the v26.5.3
# ClientPhaseRotator.cpp M_PI MSVC break, and the CwSidetonePortAudioSink
# WASAPI fix in #3241 (Windows-only logic never compiled by CI). An
# always-on rule trades ~15-20 min of runner time per PR for a category
# of regression we kept paying for.
#
# Caching strategy:
# * Qt install — handled by jurplel/install-qt-action's cache: true
# * FFTW3 third_party — actions/cache, keyed on the setup script + version
# * MSVC object files — sccache via GitHub Actions cache backend
# Net effect: cold cache ~5 min, warm cache ~2-3 min (was ~14 min).
check-windows:
runs-on: windows-latest
env:
SCCACHE_GHA_ENABLED: 'true'
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Install Qt
uses: jurplel/install-qt-action@48d3ad6db93f3627c8ee7a0454bc6f3744f7e730 # v4.3.1
with:
# 6.8.3 matches what community Windows builders are running and
# exposes Qt 6.8.x MOC volume so we catch issues like #1910 (MSVC
# COFF section limit, fixed by /bigobj) before they reach users.
version: '6.8.3'
modules: 'qtmultimedia qtwebsockets qtserialport qtshadertools'
cache: true
- name: Cache FFTW3
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: third_party/fftw3
key: ${{ runner.os }}-fftw3-3.3.5-${{ hashFiles('scripts/setup/setup-fftw.ps1') }}
- name: Install FFTW3
shell: pwsh
run: .\scripts\setup\setup-fftw.ps1
- name: Setup DeepFilterNet3 (DFNR)
shell: pwsh
run: .\scripts\setup\setup-deepfilter.ps1
- name: Setup sccache
uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
# CMAKE_CXX_COMPILER_LAUNCHER is honoured by Ninja and Make
# generators, NOT by the Visual Studio / MSBuild generator that
# CMake selects by default on windows-latest. Switch to Ninja so
# cl.exe invocations actually route through sccache. msvc-dev-cmd
# puts the MSVC toolchain on PATH (cl.exe, link.exe, etc.) so
# Ninja can find them.
- name: Setup MSVC environment
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1
with:
arch: x64
- name: Setup hidapi (HID encoder support)
# Needed for the Ulanzi Dial Windows backend (#3239) and the
# existing USB HID encoders (#3171). Without this, HAVE_HIDAPI
# is undefined and the dial code falls back to a stub — CI
# would miss real compile errors in that path. Runs after
# msvc-dev-cmd so the script has cl.exe + link.exe on PATH.
shell: pwsh
run: .\scripts\setup\setup-hidapi.ps1
# zlib is bundled under third_party/zlib (1.3.1) — no vcpkg install
# needed; CMake builds zlibstatic from source. (#2651)
# Verify sccache can actually compile through the backend. GitHub
# Actions Cache occasionally has outages; when that happens, sccache's
# GHA backend can't read/write and every compile through sccache
# fails. Pre-flight a tiny test compile so we can fall through to a
# plain build instead of failing the whole job.
- name: Test sccache health
id: sccache_health
shell: pwsh
continue-on-error: true
run: |
'int main(){return 0;}' | Out-File -Encoding ASCII test.cpp
sccache cl /c test.cpp /Fo:test.obj 2>&1 | Tee-Object -Variable scOut
$exit = $LASTEXITCODE
Remove-Item test.cpp,test.obj -ErrorAction SilentlyContinue
if ($exit -eq 0) {
"healthy=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
Write-Host "sccache OK"
} else {
"healthy=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
Write-Host "::warning::sccache unhealthy (exit $exit) — building without compiler cache"
}
- name: Configure
shell: pwsh
run: |
$launcher = "${{ steps.sccache_health.outputs.healthy }}" -eq "true"
$cargs = @(
"-B","build","-G","Ninja",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded",
"-DCMAKE_TOOLCHAIN_FILE=$env:CMAKE_TOOLCHAIN_FILE",
"-DVCPKG_TARGET_TRIPLET=$env:VCPKG_TARGET_TRIPLET"
)
if ($launcher) {
$cargs += "-DCMAKE_C_COMPILER_LAUNCHER=sccache"
$cargs += "-DCMAKE_CXX_COMPILER_LAUNCHER=sccache"
}
& cmake @cargs
- name: Build Opus (RADE dependency)
# ExternalProject dependency ordering via BUILD_BYPRODUCTS is correct,
# but a separate step gives clearer CI failure attribution and avoids
# any Ninja parallel-build ordering edge cases with IMPORTED targets.
run: cmake --build build --target build_opus -j $env:NUMBER_OF_PROCESSORS
- name: Build
run: cmake --build build -j $env:NUMBER_OF_PROCESSORS
- name: sccache stats
if: always()
run: sccache --show-stats
# macOS build check — runs on every PR (no path gating), same rationale
# as check-windows above. Catches Q_OS_MAC / CoreAudio / Cocoa-bridge
# breakage that Linux clang misses, which is otherwise only discovered
# at release tag time by macos-dmg.yml. Build-only (no code signing,
# no DMG, no notarization — those stay in macos-dmg.yml on tag push).
# Apple Silicon runner only; Intel coverage remains release-time-only.
check-macos:
runs-on: macos-15
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Install dependencies via Homebrew
# Mirrors macos-dmg.yml's apple-silicon path. Homebrew Qt targets
# the current OS, which is fine for the arm64 CI check; deployment-
# target pinning is a release-time concern handled in macos-dmg.yml.
run: |
brew install ninja qt@6 qtkeychain fftw portaudio hidapi \
autoconf automake libtool
- name: Setup DeepFilterNet3 (DFNR)
run: bash scripts/setup/setup-deepfilter.sh
- name: Set up ccache
uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 # v1.2.23
with:
key: ccache-macos-ci
max-size: 500M
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_PREFIX_PATH="$(brew --prefix qt@6);$(brew --prefix)" \
-DMQTT_TLS=OFF
- name: Build Opus (RADE dependency)
run: cmake --build build --target build_opus -j$(sysctl -n hw.ncpu)
- name: Build
run: cmake --build build -j$(sysctl -n hw.ncpu)