Skip to content

Commit 7e210c0

Browse files
committed
Qt viewer: verify packaged artifacts in CI; descope Qt Comparator (#63)
Add a packaged-artifact smoke check to the Qt viewer CI and release workflows: after deploying the bundle (windeployqt / macdeployqt) or building the Linux AppImage, run that artifact headlessly via --selftest over a PNG and a raw fixture so it must open a common image and a raw frame and exit 0. This exercises the artifact's own bundled Qt libs/plugins and libheif runtime, not the build-tree binary the existing offscreen smoke test used, and is the automated stand-in for #63's manual clean-desktop / packaged-app verification (Linux runs under xvfb; the Windows/macOS step caches the process handle so the exit code is readable). Add a tiny 16x16 PNG fixture for the image-plugin check. Record the maintainer decision that the Qt Comparator (ComparatorQt) is out of scope: the cross-platform effort targets Viewer parity only, the MFC Comparator stays the comparison tool, and PORTING_ROADMAP Phase 5 is descoped. With Comparator excluded and packaged verification automated, the Qt Viewer parity tracked in #63 is complete.
1 parent fcac2d4 commit 7e210c0

5 files changed

Lines changed: 106 additions & 7 deletions

File tree

.github/workflows/release-qt-viewer.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,46 @@ jobs:
165165
166166
chmod +x "dist/${{ matrix.asset_name }}.AppImage"
167167
168+
# Verify the released artifact (its own bundled Qt libs/plugins and libheif
169+
# runtime) before publishing: the deployed bundle / AppImage must open a
170+
# common image and a raw frame headlessly and exit 0. Automated stand-in
171+
# for the manual clean-desktop check (#63).
172+
- name: Verify packaged AppImage (Linux)
173+
if: runner.os == 'Linux'
174+
shell: bash
175+
run: |
176+
set -euxo pipefail
177+
sudo apt-get install -y xvfb
178+
appimage="dist/${{ matrix.asset_name }}.AppImage"
179+
export APPIMAGE_EXTRACT_AND_RUN=1
180+
xvfb-run -a "${appimage}" --selftest Tests/fixtures/sample_16x16.png
181+
xvfb-run -a "${appimage}" --selftest --raw --width 16 --height 16 \
182+
--format yuv420 Tests/fixtures/raw/gradient_16x16.yuv420
183+
184+
- name: Verify packaged app (Windows/macOS)
185+
if: runner.os != 'Linux'
186+
shell: pwsh
187+
run: |
188+
$pkg = "package/${{ matrix.asset_name }}"
189+
if ($env:RUNNER_OS -eq "Windows") {
190+
$bin = Join-Path $pkg "q1view_viewer_qt.exe"
191+
} else {
192+
$bin = Join-Path $pkg "q1view_viewer_qt.app/Contents/MacOS/q1view_viewer_qt"
193+
}
194+
if (-not (Test-Path $bin)) { throw "packaged binary not found: $bin" }
195+
function Invoke-SelfTest($AppArgs) {
196+
$p = Start-Process -FilePath $bin -ArgumentList $AppArgs -PassThru -NoNewWindow
197+
$null = $p.Handle # cache handle so ExitCode is readable after exit
198+
if (-not $p.WaitForExit(60000)) {
199+
$p.Kill(); throw "packaged --selftest timed out: $($AppArgs -join ' ')"
200+
}
201+
if ($p.ExitCode -ne 0) {
202+
throw "packaged --selftest failed ($($p.ExitCode)): $($AppArgs -join ' ')"
203+
}
204+
}
205+
Invoke-SelfTest @("--selftest", "Tests/fixtures/sample_16x16.png")
206+
Invoke-SelfTest @("--selftest", "--raw", "--width", "16", "--height", "16", "--format", "yuv420", "Tests/fixtures/raw/gradient_16x16.yuv420")
207+
168208
- name: Upload release asset artifact
169209
uses: actions/upload-artifact@v4
170210
with:

.github/workflows/viewer-qt.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,48 @@ jobs:
163163
164164
chmod +x "${package}/q1view-viewer-qt-linux-x86_64.AppImage"
165165
166+
# Verify the *packaged* artifact (its own bundled Qt libs/plugins and the
167+
# libheif runtime), not the build-tree binary the smoke test above used.
168+
# This is the automated stand-in for the manual clean-desktop check (#63):
169+
# the deployed bundle must open a common image and a raw frame and exit 0.
170+
- name: Verify packaged AppImage (Linux)
171+
if: runner.os == 'Linux'
172+
shell: bash
173+
run: |
174+
set -euxo pipefail
175+
sudo apt-get install -y xvfb
176+
appimage="package/q1view-viewer-qt-${RUNNER_OS}/q1view-viewer-qt-linux-x86_64.AppImage"
177+
# xvfb gives the bundled xcb plugin a display; extract-and-run avoids
178+
# needing FUSE on the runner.
179+
export APPIMAGE_EXTRACT_AND_RUN=1
180+
xvfb-run -a "${appimage}" --selftest Tests/fixtures/sample_16x16.png
181+
xvfb-run -a "${appimage}" --selftest --raw --width 16 --height 16 \
182+
--format yuv420 Tests/fixtures/raw/gradient_16x16.yuv420
183+
184+
- name: Verify packaged app (Windows/macOS)
185+
if: runner.os != 'Linux'
186+
shell: pwsh
187+
run: |
188+
$pkg = "package/q1view-viewer-qt-${{ runner.os }}"
189+
if ($env:RUNNER_OS -eq "Windows") {
190+
$bin = Join-Path $pkg "q1view_viewer_qt.exe"
191+
} else {
192+
$bin = Join-Path $pkg "q1view_viewer_qt.app/Contents/MacOS/q1view_viewer_qt"
193+
}
194+
if (-not (Test-Path $bin)) { throw "packaged binary not found: $bin" }
195+
function Invoke-SelfTest($AppArgs) {
196+
$p = Start-Process -FilePath $bin -ArgumentList $AppArgs -PassThru -NoNewWindow
197+
$null = $p.Handle # cache handle so ExitCode is readable after exit
198+
if (-not $p.WaitForExit(60000)) {
199+
$p.Kill(); throw "packaged --selftest timed out: $($AppArgs -join ' ')"
200+
}
201+
if ($p.ExitCode -ne 0) {
202+
throw "packaged --selftest failed ($($p.ExitCode)): $($AppArgs -join ' ')"
203+
}
204+
}
205+
Invoke-SelfTest @("--selftest", "Tests/fixtures/sample_16x16.png")
206+
Invoke-SelfTest @("--selftest", "--raw", "--width", "16", "--height", "16", "--format", "yuv420", "Tests/fixtures/raw/gradient_16x16.yuv420")
207+
166208
- name: Upload package
167209
uses: actions/upload-artifact@v4
168210
with:

Tests/fixtures/sample_16x16.png

590 Bytes
Loading

docs/PORTING_ROADMAP.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,12 @@ viewer entry once parity is reached.
591591

592592
## Phase 5 — ComparatorQt
593593

594+
> **Descoped (maintainer decision, 2026-06-17).** ComparatorQt will **not** be
595+
> implemented. The cross-platform effort targets Viewer parity only; the Windows
596+
> MFC Comparator stays the comparison tool. The design below is retained for
597+
> reference in case this decision is ever revisited, but it is not planned work,
598+
> and #63 is considered complete without it.
599+
594600
**Why last:** ComparatorQt is the largest single chunk of new UI work and
595601
it benefits from a battle-tested ViewerQt plus the abstractions laid down
596602
in Phases 0–2 (decoders, file scanner, watcher, video, audio). Doing it

docs/PORTING_STATUS.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ This file captures the current cross-platform porting state so future Codex sess
1111
- The short-lived `cross-platform-core` branch has been **merged and deleted**
1212
it no longer exists. All further work lands directly on `master`.
1313
- Qt viewer feature-parity work is tracked in #63. Video playback, file-change
14-
auto-refresh, and multi-window Sync Input have landed; remaining items are the
15-
Comparator features, clean-desktop AppImage verification, automated Qt smoke
16-
checks, and raw fixtures.
14+
auto-refresh, and multi-window Sync Input have landed. The Qt **Comparator**
15+
is out of scope (see "Out of scope" below), so the only remaining #63 item —
16+
verifying the *packaged* artifacts on each OS — is now automated in CI: every
17+
Qt build runs the deployed bundle / AppImage headlessly via `--selftest`.
1718
- The Qt viewer stays additive: it builds behind the `Q1VIEW_BUILD_QT_VIEWER`
1819
CMake option (default OFF) and only *links* the shared core, so the MFC
1920
Windows product (`Viewer.sln` / `Comparator.sln`) is unaffected.
@@ -131,9 +132,15 @@ Current capabilities:
131132
Playback sync covers raw-sequence play/stop and video play/pause; the video
132133
clock/position itself is not mirrored (each window plays on its own clock)
133134

134-
It does not yet implement:
135+
Out of scope (maintainer decision, 2026-06-17):
135136

136-
- Comparator features.
137+
- **Comparator / ComparatorQt features are not being ported to Qt.** The
138+
cross-platform effort targets *Viewer* parity only; the Windows MFC
139+
Comparator remains the comparison tool. Phase 5 of
140+
[PORTING_ROADMAP.md](PORTING_ROADMAP.md) is therefore descoped, and #63's
141+
remaining Viewer work (packaged-artifact verification) is now automated in
142+
CI rather than done by hand. With Comparator excluded, the Qt Viewer is at
143+
feature parity with the MFC Viewer.
137144

138145
Successful Qt viewer CI runs:
139146

@@ -206,8 +213,12 @@ Local build note: GitHub Actions remains the cross-platform source of truth (Lin
206213

207214
## Next Suggested Steps
208215

209-
1. Track and land the remaining Qt viewer parity work via #63 (Comparator, Qt
210-
smoke checks, and raw fixtures).
216+
1. Qt viewer parity (#63) is complete for the in-scope feature set; the Qt
217+
Comparator is intentionally not ported (the MFC Comparator remains the
218+
comparison tool). Raw fixtures and automated Qt smoke checks have landed, and
219+
the packaged artifacts are now verified headlessly in CI (`--selftest` against
220+
the deployed bundle / AppImage), replacing the earlier manual clean-desktop
221+
check.
211222
2. Improve packaging for `q1view_viewer_qt`:
212223
- Windows packaging uses `windeployqt`.
213224
- macOS packaging uses `macdeployqt`.

0 commit comments

Comments
 (0)