## Why
A release can be replaced under the same tag during asset upload. Cleanup by tag could then delete the replacement release.
## What changed
Move GitHub release publication into `.github/scripts/publish-github-release.sh`. Create releases through the API and capture their IDs so an exit trap deletes only the newly created prerelease if asset upload fails. Clear the trap after upload so a metadata update failure preserves the uploaded assets.
Keep existing releases and tags intact, verify tags before creating releases, and continue creating stable releases as drafts until upload completes.
## Testing
Extend the publication test to cover upload failures, retries, metadata update failures, stable drafts, replacement releases, and missing tags. The focused test passes.
GitOrigin-RevId: a310d5b77a66dc6a9cf2d136c280d968f0e7a28f