Skip to content

Retry publishMainSite on concurrent asf-site-production pushes - #541

Merged
jamesfredley merged 3 commits into
apache:masterfrom
jamesfredley:ci/deploy-github-pages-action
Sep 3, 2026
Merged

Retry publishMainSite on concurrent asf-site-production pushes#541
jamesfredley merged 3 commits into
apache:masterfrom
jamesfredley:ci/deploy-github-pages-action

Conversation

@jamesfredley

@jamesfredley jamesfredley commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Why not switch this workflow to deploy-github-pages

apache/grails-github-actions deploy-github-pages (asf after #110) can publish to apache/grails-website asf-site-production. Grails Core already does that with GH_TOKEN: ${{ secrets.GRAILS_GHTOKEN }}, TARGET_REPOSITORY: apache/grails-website, and DOCUMENTATION_BRANCH: asf-site-production. The only formal action input is token; destination layout is env vars, not a hard-coded docs/ path. TARGET_FOLDER defaults to .. Grails Core sets TARGET_FOLDER: docs because its output belongs under docs/.

That is the wrong shape for this site:

  • This job must additively overlay build/dist/ onto the branch root and leave grails-core's docs/ tree (and ASF files such as .asf.yaml) in place.
  • PURGE_EXISTING defaults to true. Pointing TARGET_FOLDER at . with purge would git rm the destination checkout, including docs/.
  • Staging is still git add --verbose "${PUBLISH_PATH}"/*. Source copy includes dotfiles, but that glob does not stage new root .htaccess or .well-known.
  • GRADLE_PUBLISH_RELEASE / LAST_SNAPSHOT_FOLDER / latest is a versioned-docs layout. This site is not a snapshot-or-version docs tree.

#110 added a five-attempt porcelain non-fast-forward / fetch first rebase retry (no force-push). Sequential site-then-docs action runs are not inherently racy after that change. This PR copies that retry into :publishMainSite instead of adopting the action.

GITHUB_TOKEN still cannot write apache/grails-website. A PAT (GRAILS_GHTOKEN) is required either way.

What this PR does

  • Port the Updates doc #110 retry into publishMainSite: fetch, require the new tip to descend from the cloned tip, rebase the unpublished commit, retry up to 5 times. Rewritten history and rebase conflicts fail closed.
  • Redact authenticated URLs from logged git output.
  • Set workflow permissions.contents to read (this job does not push this repo).
  • Keep secrets.GRAILS_GHTOKEN, GITHUB_SLUG: apache/grails-website, GH_BRANCH: asf-site-production, and intra-repo concurrency with cancel-in-progress: false.

Tests

PublishMainSiteTaskSpec: first push, disjoint rebase keeps both trees, conflict aborts, unrelated failures are not retried, rewritten history fails closed, credential URLs are redacted.

Keep Gradle publish instead of deploy-github-pages: that action writes docs/<snapshot|version>, skips root dotfiles, and would wipe grails-core docs. Copy the PR apache#110 non-fast-forward rebase retry into publishMainSite and drop contents:write since this workflow only pushes with GRAILS_GHTOKEN.
Copilot AI lite review requested due to automatic review settings September 3, 2026 01:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new retry implementation introduces avoidable secret-leak risk in logs and has a few determinism/test-isolation issues that should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a retry/rebase loop to publishMainSite so concurrent pushes to apache/grails-website’s asf-site-production (e.g., from Grails Core docs publishing) are handled safely without force-pushing, and documents/validates the behavior with tests.

Changes:

  • Implement pushWithRetry for non-fast-forward / fetch-first push rejections (fetch + descendant check + rebase + retry).
  • Add Spock coverage for success, disjoint rebase, conflict abort, non-retryable failures, and rewritten-history fail-closed behavior.
  • Update workflow/README to reflect the approach and tighten job contents permission to read.
File summaries
File Description
README.md Documents the cross-repo non-fast-forward retry behavior and links to upstream precedent.
buildSrc/src/main/groovy/website/gradle/tasks/PublishMainSiteTask.groovy Adds push retry logic with fetch/descendant check/rebase and standardizes git invocations.
buildSrc/src/test/groovy/website/gradle/tasks/PublishMainSiteTaskSpec.groovy Introduces fixture-based tests covering retry/rebase and failure modes.
.github/workflows/publish.yml Updates comments and reduces permissions.contents to read-only.
Review details

Suppressed comments (2)

buildSrc/src/main/groovy/website/gradle/tasks/PublishMainSiteTask.groovy:309

  • git rebase can run hooks (e.g., pre-rebase). This command currently omits -c core.hooksPath= even though other git invocations explicitly disable hooks. Add the flag here to keep CI behavior deterministic.
                spec.commandLine = ['git', 'rebase', '--onto', newRemoteTip, observedTip]

buildSrc/src/main/groovy/website/gradle/tasks/PublishMainSiteTask.groovy:315

  • git rebase --abort should also disable hooks for the same reason as the main rebase command, to avoid surprises from any global core.hooksPath configuration.
                    spec.commandLine = ['git', 'rebase', '--abort']
  • Files reviewed: 4/4 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread buildSrc/src/main/groovy/website/gradle/tasks/PublishMainSiteTask.groovy Outdated
Comment thread buildSrc/src/main/groovy/website/gradle/tasks/PublishMainSiteTask.groovy Outdated
Redact authenticated URLs before logging push output, restore the skip-backoff test property after the spec, disable hooks on merge-base, and include both tips in the ancestor-failure message.
The action is not hard-wired to docs/; grails-core sets TARGET_FOLDER to docs. Keep Gradle because a purged root overlay would wipe that tree and git add globs skip new root dotfiles.
@jamesfredley
jamesfredley merged commit e646c3a into apache:master Sep 3, 2026
1 check passed
@jamesfredley
jamesfredley deleted the ci/deploy-github-pages-action branch September 3, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants