ci(deploy): publish stable release on every main push#37
Merged
Conversation
Drops the dev-suffix prerelease path. Every push to main now produces a stable v$next-patch release with make_latest=legacy, so the wraithsec-site auto-update probe (which calls /releases/latest) tracks main within minutes of a merge instead of stalling on the last manually-tagged release. - Removes the v$NEXT-dev.$RUN_NUMBER prerelease build path. - Removes the unused RUN_NUMBER env var from the derive-version step. - Tag-triggered runs unchanged — explicit backports / hotfixes still work. - Stale-VERSION guard still aborts when VERSION lags behind the highest tag. - Header comment block rewritten to reflect new model.
There was a problem hiding this comment.
Pull request overview
This PR changes the deployment workflow so that every push to main publishes a stable GitHub Release (auto-incrementing the patch version within the major.minor line from VERSION) and marks it as “Latest” via GitHub’s SemVer comparison (make_latest: legacy). This aligns the repository’s /releases/latest behavior with the wraithsec-site probe so the site tracks main quickly without manual tagging.
Changes:
- Switch
mainpushes from prerelease-dev.Ntags to stablevX.Y.Ztags (prerelease=false,make_latest=legacy). - Remove the now-unused
RUN_NUMBERfrom the version derivation logic. - Update the workflow header documentation and messaging to reflect the new stable-on-main release model.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # probe (which calls /releases/latest) always sees the freshest stable within | ||
| # minutes of a merge — no manual tag step required. | ||
| # | ||
| # Tag pushes still work for explicit backports / hotfixes off a non-main branch. |
Two overlapping main pushes could both compute the same $nextStable
(neither tag exists yet at version-derivation time), then race at the
softprops/action-gh-release step — the loser fails with "tag already
exists". Concurrency group=deploy-${ref}, cancel-in-progress=false
queues the second run so it sees the first run's published tag and
picks the next patch.
Tag-push runs are scoped by their unique tag ref so they never collide
with each other or with main pushes.
Comment on lines
23
to
25
| push: | ||
| branches: [ main ] | ||
| tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] |
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
Two fixes plus a concurrency guard, so the next merge to main publishes a stable release that actually works and the site picks it up automatically.
1. Main pushes publish stable releases
Drops the
v$NEXT-dev.$RUN_NUMBERprerelease path. Main pushes now emitv$nextStablewithprerelease=false,make_latest=legacy. The wraithsec-site probe (which calls/releases/latestand ignores prereleases) starts tracking main within minutes of a merge, no manual tag step required. Tag-push runs unchanged — explicit backports / hotfixes still work.2. Workflow concurrency to prevent tag races
Two overlapping main pushes could both compute the same
$nextStable(neither tag exists at version-derivation time) and the second would fail atsoftprops/action-gh-releasewith "tag already exists".concurrency: { group: deploy-${{ github.ref }}, cancel-in-progress: false }queues the second run behind the first so it sees the just-published tag and picks the next patch.3. Re-ship
scanner/+automation/in the portable ZIP (regression from PR #36)PR #36 trimmed the ZIP to just
WRAITH.exe+README.mdon the assumption that the csproj Content includes embedded the Python scanner and PowerShell automation scripts inside the single-file binary. They don't —CopyToOutputDirectorydrops those trees ALONGSIDE the EXE in./publish; the single-file bundler only ingests managed assemblies and native libs.Result for portable-ZIP users: extract, double-click
WRAITH.exe, hit Scan → every Python-backed scan fails with"Python scanner not found at <extract-dir>\scanner\scanner.py"becauseBootstrapService.ResolveBaseDir()joins"scanner"to the EXE dir and the ZIP had none.The stage step now copies
./publish/scannerand./publish/automationinto./releasebeforeCompress-Archive. Sourcing from./publishmeans the csproj's existing Exclude pattern (test_*.py,__pycache__,*.pyc) automatically carries through — no duplicate filter to drift.Still kept OUT of the ZIP (PR #36's "no raw repo junk" intent preserved): START.bat, quick-scan.ps1, wraith.env.json template, LICENSE, CI / test files. The portable ZIP is now exactly the runtime payload — nothing more.
Velopack installer path was never broken by PR #36 (it consumes
./publish-velopackwhich still includes the dirs via the same csproj rule), so the third fix is portable-ZIP-only.Test plan
v$(next-patch), notv$(next-patch)-dev.N.WRAITH.exe, hit Scan → real scan output instead of "Python scanner not found"./releases/latestAPI endpoint returns the new tag, and wraithsec-site picks it up (sessionStorage 5 min, localStorage LKG 7 days — hard refresh to bypass).