Skip to content

[core] Use native stored ZIPs for support bundles and profile backups#3206

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:codex/support-bundle-native-zip
May 27, 2026
Merged

[core] Use native stored ZIPs for support bundles and profile backups#3206
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:codex/support-bundle-native-zip

Conversation

@jensenpat
Copy link
Copy Markdown
Collaborator

@jensenpat jensenpat commented May 27, 2026

Summary

  • Extract the profile transfer ZIP reader/writer into a shared ZipArchive helper.
  • Write support bundles as native uncompressed .zip files using the shared stored-ZIP writer instead of launching PowerShell Compress-Archive or tar.
  • Add a focused ZIP round-trip/corruption test for the shared helper.

Validation

  • Configured and built with MSVC via scripts/enter-msvc.ps1 -Arch x64 and Ninja using 8 jobs.
  • Built build_opus, zip_archive_test, profile_transfer_test, and AetherSDR.
  • Ran profile_transfer_test and zip_archive_test separately with Qt on PATH; both passed.
  • Ran windeployqt on the built app for manual testing.
  • Scanned the built executable/deployed executable: no powershell, Compress-Archive, or .tar.gz support-bundle path remains.
  • Checked direct process-launch imports with dumpbin; no direct CreateProcess/ShellExecute import was found.

Co-authored-by: Codex <noreply@openai.com>
@jensenpat jensenpat changed the title Use native stored ZIPs for support bundles [core] Use native stored ZIPs for support bundles and profile backups May 27, 2026
@jensenpat jensenpat marked this pull request as ready for review May 27, 2026 05:46
@jensenpat jensenpat requested review from a team as code owners May 27, 2026 05:46
Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jensenpat — clean extraction. The ZipArchive helper is a straight lift-and-shift of the existing reader/writer with two small upgrades (explicit numeric_limits overflow guards for entry count / sizes / offsets, and static_cast<uInt> on the crc32 size argument), and the support-bundle path drops the QProcess/powershell/tar shell-out in favor of in-process ZIP writing via QSaveFile. Nice removal of an external-process dependency — and QSaveFile::commit() gives atomic replace semantics the old shell-out couldn't.

A few small notes for your consideration, none blockers:

1. Linux/macOS support bundle file extension change (worth a CHANGELOG entry)

src/core/SupportBundle.cpp:202 previously produced support-bundle-*.tar.gz on non-Windows and .zip on Windows. After this PR, all platforms produce .zip. I grepped the tree and found no consumer of support-bundle-*.tar.gz (the only hit was the line being removed), so this is safe. Worth a brief note in CHANGELOG.md since existing Linux/macOS users with scripts or muscle memory expecting .tar.gz will be surprised.

2. collectSupportBundleEntries is flat-only by design

QDir::Files + no QDirIterator means subdirectories under the temp bundle dir are silently dropped. Today SupportBundle::createBundle writes only top-level files (logs, JSONs, settings.xml, enabled-categories.txt — all flat), so this matches current behavior. Worth a one-line comment in collectSupportBundleEntries noting the flat-only invariant so a future contributor who adds, say, a crashdumps/ subdir doesn't end up with a silently-empty section in the bundle.

3. Stored-only ZIP and uncompressed log size

The shared helper only writes stored (method 0) ZIPs, so a support bundle now uncompresses to roughly the sum of input file sizes plus headers, where the old tar czf deflated logs. AetherSDR logs are rotated small so this is unlikely to be a real problem in practice, but if a user has logs in the tens of MB the bundle is now noticeably larger. The PR title is explicit ("native stored ZIPs") so this is presumably intentional — flagging in case it's worth a follow-up to wire deflate into writeStoredZip later (the reader already handles method 8).

4. uncompressedSize is dead in the stored-method branch

src/core/ZipArchive.cpp:142 reads uncompressedSize but it's only consumed inside the method == 8 branch. Pre-existing — moved verbatim from ProfileTransfer.cpp — but since you're touching this code, a [[maybe_unused]] or restructuring the read to live inside the deflate branch would be cleaner. Skip if you'd rather keep the lift truly verbatim.

Otherwise this looks good — the round-trip + corruption test in tests/zip_archive_test.cpp covers the contract well, and routing ProfileTransfer through the same helper means the existing profile_transfer_test exercises the writer too. Thanks again.


🤖 aethersdr-agent · cost: $8.6056 · model: claude-opus-4-7

@ten9876 ten9876 merged commit d01bb83 into aethersdr:main May 27, 2026
5 checks passed
@ten9876
Copy link
Copy Markdown
Collaborator

ten9876 commented May 27, 2026

Claude here — merged, thanks @jensenpat. Clean refactor + the WACK "Blocked executables" finding is gone. The null-safe error setter and numeric_limits overflow guards you layered into the shared writeStoredZip are strictly better than the inline version we had before; nice cleanup tucked into the move.

Filed #3218 to track adding deflate compression as a follow-up. Confirmed nothing in Store policy or WACK objects to runtime deflate — the rule was about subprocess imports, which this PR resolved. Switching back to compressed bundles is purely a UX win for users hitting Discord/email size limits.

73, Jeremy KK7GWY & Claude (AI dev partner)

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.

2 participants