We have an ongoing issue with concurrent publishing to the grails-website repository. This has affected multiple releases over the past several months in addition to grails-website publishing. Any time two publishing actions are running at the same time.

I previously opened https://github.com/apache/grails-github-actions/pull/98 to make concurrent documentation pushes safe. It was closed in favor of a job-level concurrency group (`grails-docs-publish`) added in grails-core#15988 and then closed again, after re-opening, when it became clear that did not work. That approach serializes independent documentation jobs within Grails Core. Because GitHub Actions concurrency groups are scoped to a single repository, it cannot coordinate publishers from other repositories (grails-static-website, and eventually Grails Forge) that also target the same destination branch.

In practice making this serial has introduced measurable delays during release sequences (for example, an 18-minute wait observed on the each release documentation job, plus manual synchronization, plus manual re-run on grail-website action which failed, plus waiting on github runner availability). This burned 3 hours this morning.

The current pair of pull requests restores the ability to publish in parallel while remaining conservative:


- https://github.com/apache/grails-github-actions/pull/110 – Safely retry concurrent documentation pushes When another publisher advances the destination branch first, the action recognizes a genuine non-fast-forward rejection, fetches the new tip into the existing shallow checkout, confirms the fetched tip descends from the originally observed tip, rebases the unpublished local deployment commit, and retries a normal push (maximum five attempts). There is no force-push. Conflicts, non-descendant history, and unrelated failures fail closed without modifying the remote.

- https://github.com/apache/grails-core/pull/16110 – Allow concurrent documentation publishing Removes the repository-local `grails-docs-publish` queue so independent documentation jobs can proceed once the action-level retry is available. Git’s normal fast-forward rules then coordinate updates to the shared branch.

This is a deliberately narrow solution. It covers the cross-repository case, avoids serializing unrelated release work, and fails safely. I am open to any alternative that fully addresses the same constraints (multiple independent publishers, no force-push, safe handling of true content conflicts, and no artificial serialization of independent jobs). Until a better complete solution is available and verified, these changes allow the project to move forward without further release delays.

An alternate solution has also been proposed of uploading artifacts and then having a separate workflow process them: That approach would introduce additional moving parts (artifact storage, a new coordinating workflow, hand-off between producers and a consumer, extra latency, and new failure modes) for what is fundamentally a concurrent commit problem on a shared branch. Multiple independent publishers are simply generating documentation and pushing it to the same destination. When another push lands first, the required response is the standard Git sequence: fetch the new tip, rebase the unpublished local commit, and push again. That is exactly what the retry logic in apache/grails-github-actions#110 does, using ordinary fast-forward rules and failing closed on true conflicts.

Let's debate this and get it fixed before the next release cycle, so we can get back to faster releases.

James

Reply via email to