fix(release): stop the workflow re-releasing its own version bump - #532
Merged
Conversation
This workflow ends by opening a pull request that brings the integration
branch up to the version it just tagged. Merging that pull request is a push
to the integration branch, which triggers this workflow again, which bumps
the version again, which opens another pull request.
The bump commit carries `[skip ci]`, but the MERGE COMMIT that actually lands
on the branch does not — so the marker never gets a chance to work.
Measured on opencatalogi, 2026-08-20, over its last 100 development commits:
45 chore(release): version bumps
46 merges of release/* branches
9 actual work
91% of the branch's history was the workflow reacting to itself, one cycle
about every ten minutes, and the base version never advanced: every one of
those releases was 1.0.9-unstable.<timestamp>.
It hides well. Each run is a legitimate release of a real commit, so the only
symptom is that the branch never settles — which reads as "someone is
committing a lot" rather than as a defect. The damage shows up elsewhere: a
development branch that moves every ten minutes cancels its own in-flight CI
by concurrency, and opencatalogi's dev→beta pull request had its E2E and
Hydra Gates jobs cancelled repeatedly for exactly that reason. A cancelled
job yields no verdict, so the promotion could not be judged at all.
The guard skips the job when the triggering push IS the bump landing, in
either merge style: a merge commit names the `release/v*` head branch, and a
squash produces `chore(release): <version> (#123)`. Nothing is lost — those
pushes contain only appinfo/info.xml (and openapi.json where present), so
re-releasing them would build a byte-identical artefact under a new number.
`workflow_dispatch` is never skipped, so a human can still force a release by
hand, including of a commit this guard would refuse.
Verified with a truth table over REAL commit messages from opencatalogi's
history, asserting both directions rather than only the skip: the two bump
shapes and the squash shape skip, while `feat/rotterdam-demo-rig`, a plain
`test(federation):` commit and a `chore/nc-vue-2.8.2` dependency bump all
still release. A guard that only proved it can skip would be indisttinguishable
from one that skips everything.
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.
The workflow releases its own release
This workflow ends by opening a pull request that brings the integration
branch up to the version it just tagged. Merging that pull request is a push
to the integration branch, which triggers this workflow again, which bumps
the version again, which opens another pull request.
The bump commit carries
[skip ci]— but the merge commit that actuallylands on the branch does not, so the marker never gets a chance to work.
Measured
opencatalogi, 2026-08-20, last 100
developmentcommits:chore(release):version bumpsrelease/*branches91% of the branch's history was the workflow reacting to itself, roughly
one cycle every ten minutes — and the base version never advanced. Every one
of those releases was
1.0.9-unstable.<timestamp>.Why it hides
Each individual run is a legitimate release of a real commit. The only
symptom is that the branch never settles, which reads as "someone is
committing a lot" rather than as a defect.
The damage lands somewhere else entirely: a development branch that moves
every ten minutes cancels its own in-flight CI by concurrency.
opencatalogi's dev→beta PR had its E2E and Hydra Gates jobs cancelled
repeatedly for exactly this reason — and a cancelled job yields no verdict,
so the promotion could not be judged at all.
The guard
Skip the job when the triggering push is the bump landing, in either merge
style — a merge commit names the
release/v*head branch, a squash produceschore(release): <version> (#123).Nothing is lost: those pushes contain only
appinfo/info.xml(andopenapi.jsonwhere present), so re-releasing them builds a byte-identicalartefact under a new number.
workflow_dispatchis never skipped, so a human can always force arelease by hand — including of a commit this guard would refuse.
Verification
Truth table over real commit messages from opencatalogi's history,
asserting both directions:
Merge pull request #955 from ConductionNL/release/v1.0.9-unstable…chore(release): 1.0.9-unstable.… [skip ci]chore(release): 1.0.9-unstable.… (#955)(squash)Merge pull request #928 from ConductionNL/feat/rotterdam-demo-rigtest(federation): prove the SSRF allowance…Merge pull request #194 from ConductionNL/chore/nc-vue-2.8.2workflow_dispatchAll 7 correct. A guard that only proved it can skip would be
indistinguishable from one that skips everything, so the must-still-release
rows are the ones that matter.