ci(deploy): add portable-ZIP smoke test before release upload#39
Merged
Conversation
Adds a new step between "Create ZIP" and "Create GitHub Release" that
unpacks the produced ZIP into a temp dir and asserts:
Required (job fails if missing):
- WRAITH.exe
- README.md
- scanner/scanner.py
- automation/Register-WraithTimedScan.ps1
- automation/Register-WraithPersistenceListener.ps1
Forbidden (job fails if present):
- START.bat, quick-scan.ps1, wraith.env.json, LICENSE
- scanner/test_heuristics.py, scanner/__pycache__
The check unpacks the ACTUAL produced ZIP (not ./release) so it also
catches anything Compress-Archive does differently from a raw filesystem
copy. The pytest + dotnet test gates test source-code behaviour; this
step is the only thing that catches workflow-level staging regressions
like the one that shipped v1.0.65-dev.87 without scanner/.
Forbidden-list catches drift in the other direction too: if a future PR
re-introduces START.bat or stops excluding test files, the release is
blocked instead of silently bloating the ZIP.
There was a problem hiding this comment.
Pull request overview
Adds a release gate in the deployment workflow to validate the actual produced portable ZIP contents before publishing a GitHub Release, preventing broken or bloated archives from being uploaded.
Changes:
- Unpacks the generated portable ZIP in CI and asserts required runtime payload files are present.
- Fails the workflow if forbidden “repo junk” / test artefacts appear in the ZIP.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+445
to
+463
| $forbidden = @( | ||
| "START.bat", # PR #36 removed — must not come back | ||
| "quick-scan.ps1", # PR #36 removed | ||
| "wraith.env.json", # bootstrap creates fresh per install | ||
| "LICENSE", # repo metadata, not runtime | ||
| "scanner/test_heuristics.py", | ||
| "scanner/__pycache__" | ||
| ) | ||
|
|
||
| $missing = @() | ||
| foreach ($f in $required) { | ||
| $p = Join-Path $unpack $f | ||
| if (-not (Test-Path $p)) { $missing += $f } | ||
| } | ||
| $leaked = @() | ||
| foreach ($f in $forbidden) { | ||
| $p = Join-Path $unpack $f | ||
| if (Test-Path $p) { $leaked += $f } | ||
| } |
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.
Summary
Adds a pre-release smoke test that unpacks the produced portable ZIP and asserts the runtime payload is intact before
softprops/action-gh-releaseuploads anything. Catches the class of regression that shippedv1.0.65-dev.87withoutscanner/— the pytest + dotnet test gates only exercise source code, so a broken staging step had nothing stopping it from reaching users.What it checks
Required (job fails if missing):
WRAITH.exeREADME.mdscanner/scanner.py—BootstrapService.ResolveBaseDir()entry pointautomation/Register-WraithTimedScan.ps1— tray "Auto scan"automation/Register-WraithPersistenceListener.ps1— tray "Persistence"Forbidden (job fails if present):
START.bat,quick-scan.ps1,wraith.env.json,LICENSE— PR Trim release ZIP to WRAITH.exe + README only #36's "no raw repo junk" exclusionsscanner/test_heuristics.py,scanner/__pycache__— pytest artefacts that should never shipUnpacks the actual produced ZIP (not
./release) so the check also catches anythingCompress-Archivedoes differently from a raw filesystem copy.Why both lists
Forbidden-list catches drift in the other direction: if a future PR re-introduces
START.bator stops excludingtest_*.py, the release is blocked instead of silently bloating the archive. Symmetric guard.Test plan
Copy-Item scannerline locally → workflow fails at the new step, no release published.