Let the Merge Make the Tag
I’ve tagged a release before merging it more than once. The pull request looked ready, so I created the tag, wrote the notes, and then merged. The tag pointed at the commit on the release branch instead of the merge commit. Each time, I had to delete the tag and the release and make them again.
The fix wasn’t to be more careful. It was to stop tagging by hand.
Make the merge the release step
My projects already use a release branch named after the version, such as release/1.1.6. That branch only bumps the version number and moves the changelog notes under the new heading. So the merge of that pull request is the moment the release is ready, and a workflow can do the rest.
In GitHub Actions, the trigger is a pull request that was closed and merged into the main development branch from a branch that starts with release/.
on:
pull_request:
types: [ closed ]
branches: [ develop ]
jobs:
release:
if: github.event.pull_request.merged && startsWith( github.head_ref, 'release/' )
runs-on: ubuntu-latest
permissions:
contents: write
The job reads the version from the branch name and creates the release on the merge commit, which is github.event.pull_request.merge_commit_sha. Using gh release create with --target set to that commit creates the tag in the same step.
Check before you publish
A release that runs on its own should refuse to run when something doesn’t match. Mine stops if:
- the branch name isn’t a valid version
- the version in the code doesn’t match the branch
- a release with that tag already exists
- the changelog has no section for that version
The release notes come from that changelog section, so the notes on GitHub match what’s in the repository.
One catch with built files
For a theme, the release also needs a ZIP. I had a separate workflow that built it whenever a release was published. A release created with the workflow’s own GITHUB_TOKEN doesn’t trigger other workflows, so that ZIP never appeared. Building and attaching the ZIP in the same workflow that creates the release fixed it.
Now a release is one action: merge the release pull request. The tag lands on the right commit every time, and I don’t have to remember the order.