Safely retry concurrent documentation pushes - #110
Open
jamesfredley wants to merge 2 commits into
Open
Conversation
Retry only genuine non-fast-forward races by fetching and rebasing the unpublished deployment commit in the existing shallow checkout. Fail safely on conflicts, rewritten history, and unrelated push errors. Assisted-by: opencode:gpt-5.6-sol
Clarify the five-attempt limit and the fail-closed conditions for concurrent documentation publishing. Assisted-by: opencode:gpt-5.6-sol
This was referenced Aug 6, 2026
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.
Summary
Make concurrent documentation publishers converge through normal Git fast-forward semantics instead of requiring a global workflow queue.
When another publisher advances the destination branch first, this action now:
There is no force-push. A rejected push has not changed the remote branch, and the retry only rebases the unpublished local commit before attempting another normal fast-forward push. Rebase conflicts, non-descendant history, and unrelated push failures fail without changing the remote.
This supersedes #98 with a substantially narrower implementation. It removes path ownership, version arbitration, and automatic conflict resolution from the design.
Why the Queue Is Insufficient
The destination branch is shared by publishers in multiple repositories, including Grails Core and
grails-static-website, with Grails Forge expected to publish there in the future. GitHub Actions concurrency groups are scoped to one repository, so a mutex in Grails Core cannot coordinate those other publishers. It also cannot coordinate older workflow revisions that do not contain the same group.Queueing all Grails Core documentation jobs also turns otherwise independent release work into a serial process. In the August 6 release sequence:
The supplied
grails-static-websiterun is not counted as queue-delay evidence because it was manually cancelled before publishing. It does demonstrate the cross-repository boundary: that publisher targets the same destination but cannot participate in a Grails Core concurrency group.The action already pays the cost of cloning the large destination repository. Retrying in that existing checkout avoids another clone while allowing disjoint publishers to proceed in parallel. Git's normal non-fast-forward rejection remains the serialization point for the branch tip.
Failure Policy
Verification
DeployGithubPagesSpec: 16/16 tests passed against Testcontainers and a real Gitea remote.bash -n deploy-github-pages/entrypoint.shgit diff --check origin/asf...HEADFollow-up
Companion PR apache/grails-core#16110 removes the repository-local
grails-docs-publishqueue. It is explicitly blocked from merging until this PR reachesasfand is verified.