You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GitHub Action also documents this intent in run.ts:
@changesets/ghcommit has to reset the branch to the same commit as the base, which GitHub will then react to by closing the PRs
We could not find any comment, README note, or issue explaining why changesets-gitlab intentionally diverges from this behavior.
Impact
In environments where multiple pipelines on the default branch can run concurrently (e.g. auto_cancel.on_new_commit: none), an older pipeline whose changeset job runs late may:
Decide to create/update a version MR based on changesets found at CI_COMMIT_SHA (decision in main() is correct).
Then execute runVersion, which fetch + reset to latest origin/main — potentially a different commit than the one that triggered the pipeline.
Run changeset version against that newer state and force-push an updated changeset-release/* branch / version MR.
This can interfere with the normal release flow:
Feature MR merges → version MR created
Version MR merges → next pipeline should publish (no changesets on that commit)
Meanwhile, a delayed job from an earlier pipeline may still run runVersion against the latest main and create/update another version MR
We observed this in a monorepo with high merge frequency on the default branch. As a mitigation we added resource_group to serialize changeset jobs, but the underlying reset behavior still seems incorrect compared to the GitHub Action.
Expected behavior
runVersion should reset the version branch to the pipeline trigger commit, equivalent to GitLab's CI_COMMIT_SHA:
Note: the publish vs. version MR decision in main() reads .changeset/ from the CI workspace at job start (before fetch/reset), so that part is fine. The problem is specifically in runVersion execution, after the decision has already been made.
Steps to reproduce
Configure CI on the default branch with multiple concurrent pipelines allowed (do not auto-cancel older pipelines on new commits).
Push commit A to main with a changeset → pipeline P1 starts.
Let P1 run through early stages slowly (or delay the changeset job via queue/resource_group without serialization).
Merge a version MR (commit B, no changesets) → pipeline P2 should publish.
Push commit C with a new changeset → pipeline P3 starts.
When P1's delayed changeset job finally runs:
readChangesetState() on checkout A → has changesets → enters runVersion
git fetch + reset origin/main → workspace moves to C
Creates/updates version MR based on C, not A
Environment
changesets-gitlab: 0.12.2 (also present on main at time of writing)
GitLab CI, default branch push pipelines
INPUT_PUBLISH configured (publish after version MR merge)
INPUT_REMOVE_SOURCE_BRANCH: true
Suggested fix
Change runVersion to reset to CI_COMMIT_SHA instead of origin/${currentBranch}.
We added resource_group: changeset on our GitLab CI job to serialize changeset executions per project. This reduces the race but does not fix the root cause, and does not help with merge races where the version MR merge commit itself still contains new changesets from concurrent merges.
Summary
When
runVersionprepares the version branch, it runs:This resets the working tree to the latest tip of the remote branch, not the commit that triggered the pipeline (
CI_COMMIT_SHA).The official
changesets/actionbehaves differently: it resets togithub.context.sha(the workflow trigger commit) inprepareBranch():GitHub Action also documents this intent in
run.ts:We could not find any comment, README note, or issue explaining why
changesets-gitlabintentionally diverges from this behavior.Impact
In environments where multiple pipelines on the default branch can run concurrently (e.g.
auto_cancel.on_new_commit: none), an older pipeline whosechangesetjob runs late may:CI_COMMIT_SHA(decision inmain()is correct).runVersion, which fetch + reset to latestorigin/main— potentially a different commit than the one that triggered the pipeline.changeset versionagainst that newer state and force-push an updatedchangeset-release/*branch / version MR.This can interfere with the normal release flow:
runVersionagainst the latestmainand create/update another version MRWe observed this in a monorepo with high merge frequency on the default branch. As a mitigation we added
resource_groupto serializechangesetjobs, but the underlying reset behavior still seems incorrect compared to the GitHub Action.Expected behavior
runVersionshould reset the version branch to the pipeline trigger commit, equivalent to GitLab'sCI_COMMIT_SHA:Or, if a fetch is still needed for shallow clones:
This would align with
changesets/actionand ensure each pipeline only versions changesets present on its own trigger commit.Actual behavior
runVersionalways resets toorigin/${currentBranch}after fetch, i.e. the current remote branch tip, which may be ahead ofCI_COMMIT_SHA.Relevant code (
src/run.ts):Note: the publish vs. version MR decision in
main()reads.changeset/from the CI workspace at job start (before fetch/reset), so that part is fine. The problem is specifically inrunVersionexecution, after the decision has already been made.Steps to reproduce
mainwith a changeset → pipeline P1 starts.changesetjob via queue/resource_groupwithout serialization).changesetjob finally runs:readChangesetState()on checkout A → has changesets → entersrunVersiongit fetch+reset origin/main→ workspace moves to CEnvironment
changesets-gitlab:0.12.2(also present onmainat time of writing)INPUT_PUBLISHconfigured (publish after version MR merge)INPUT_REMOVE_SOURCE_BRANCH: trueSuggested fix
runVersionto reset toCI_COMMIT_SHAinstead oforigin/${currentBranch}.INPUT_TARGET_BRANCH/mrTargetBranchdiffers fromcurrentBranch, reset to the appropriate base commit for the target branch (currently fetch/reset usescurrentBrancheven though MR target may be different — see Create MR with a custom target branch #69 / feat: create MR with custom target branch #70).Workaround
We added
resource_group: changeseton our GitLab CI job to serializechangesetexecutions per project. This reduces the race but does not fix the root cause, and does not help with merge races where the version MR merge commit itself still contains new changesets from concurrent merges.References
prepareBranch: https://github.com/changesets/action/blob/main/src/git.tsrunVersioncomment about resetting to base commit: https://github.com/changesets/action/blob/main/src/run.tsorigin/${currentBranch}, not target branch or pipeline SHAHappy to provide a PR if this analysis looks correct.