This is an automated email from the ASF dual-hosted git repository.
jamesfredley pushed a commit to branch fix/concurrent-docs-deploy
in repository https://gitbox.apache.org/repos/asf/grails-github-actions.git
The following commit(s) were added to refs/heads/fix/concurrent-docs-deploy by
this push:
new b170851 fix: fail the deploy instead of masking reconcile restore
errors
b170851 is described below
commit b1708513c90d9f481aa3171e3b04a1fc6a994c62
Author: a <[email protected]>
AuthorDate: Fri Jul 3 23:30:27 2026 -0400
fix: fail the deploy instead of masking reconcile restore errors
Addresses review feedback on the concurrent-deploy reconcile logic. The
authoritative restore commands in reconcile_owned_paths previously used
`|| true`, so if restoring an owned documentation path failed, the action
would silently stage and commit a deletion and publish broken/missing docs.
- Owned purge/keep paths always exist in the deploy commit, so their
`git checkout`/`git add` restores are now unmasked: a failure fails the
job under `set -e` instead of committing a silent deletion. Only the
best-effort pre-clean `git rm --ignore-unmatch` stays lenient.
- The "latest" yield path only restores from the remote when the remote
actually publishes it (guarded by `git ls-tree`); otherwise the staged
removal stands, avoiding an abort on a now-absent pathspec. The
`git ls-tree` check is unmasked so an invalid FETCH_HEAD fails closed.
Assisted-by: claude-code:claude-4.8-opus
---
deploy-github-pages/entrypoint.sh | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/deploy-github-pages/entrypoint.sh
b/deploy-github-pages/entrypoint.sh
index 7075198..fe24214 100755
--- a/deploy-github-pages/entrypoint.sh
+++ b/deploy-github-pages/entrypoint.sh
@@ -187,8 +187,19 @@ reconcile_owned_paths() {
# remote's higher version. FETCH_HEAD is the remote tip fetched by the
# preceding `git pull --rebase`, i.e. the concurrent deploy we rebased
onto.
git rm -rf --ignore-unmatch --quiet -- "${LATEST_OWNED_PATH}" >/dev/null
2>&1 || true
- git checkout FETCH_HEAD -- "${LATEST_OWNED_PATH}" >/dev/null 2>&1 || true
- git add -A -- "${LATEST_OWNED_PATH}" >/dev/null 2>&1 || true
+ # Restore the remote's (higher) version IF the remote actually publishes
this
+ # path. If it does not (e.g. the higher release skipped "latest"), the
+ # `git rm` above already staged its removal - there is nothing to
restore, and
+ # a `git add -A` on the now-absent pathspec would exit 128 and abort. A
+ # genuinely broken FETCH_HEAD makes `git ls-tree` exit nonzero, which -
left
+ # unmasked - fails the job under `set -e` rather than being mistaken for
+ # "path absent". A checkout failure on a path the remote DOES have also
aborts.
+ local remote_latest
+ remote_latest="$(git ls-tree -r FETCH_HEAD -- "${LATEST_OWNED_PATH}")"
+ if [ -n "${remote_latest}" ]; then
+ git checkout FETCH_HEAD -- "${LATEST_OWNED_PATH}"
+ git add -A -- "${LATEST_OWNED_PATH}"
+ fi
local kept=() x
for x in "${OWNED_PURGE_PATHS[@]}"; do
[ "$x" = "${LATEST_OWNED_PATH}" ] || kept+=("$x")
@@ -198,15 +209,20 @@ reconcile_owned_paths() {
fi
fi
+ # These owned paths are always present in DEPLOY_COMMIT (this deploy
published
+ # them), so a restore failure means a genuinely broken repo state. Do NOT
mask
+ # checkout/add failures with `|| true`: under `set -e` they must fail the job
+ # rather than silently commit a deletion and publish broken/missing docs.
Only
+ # the best-effort pre-clean `git rm` (guarded by --ignore-unmatch) stays
lenient.
for p in "${OWNED_PURGE_PATHS[@]}"; do
git rm -rf --ignore-unmatch --quiet -- "$p" >/dev/null 2>&1 || true
- git checkout "$DEPLOY_COMMIT" -- "$p" >/dev/null 2>&1 || true
- git add -A -- "$p" >/dev/null 2>&1 || true
+ git checkout "$DEPLOY_COMMIT" -- "$p"
+ git add -A -- "$p"
changed=true
done
for p in "${OWNED_KEEP_PATHS[@]}"; do
- git checkout "$DEPLOY_COMMIT" -- "$p" >/dev/null 2>&1 || true
- git add -A -- "$p" >/dev/null 2>&1 || true
+ git checkout "$DEPLOY_COMMIT" -- "$p"
+ git add -A -- "$p"
changed=true
done
if [ "$changed" = true ]; then