From 6e9a4bbc681b74faf05862ea32b732ac2f9b30aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Alvergnat?= Date: Sun, 5 Jul 2026 14:43:25 +0200 Subject: [PATCH 1/2] =?UTF-8?q?ci:=20retry=20the=20gh-pages=20publish=20up?= =?UTF-8?q?=20to=203=C3=97=20on=20transient=20failures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub's auto "pages build and deployment" occasionally fails with "Deployment failed, try again later." when concurrent gh-pages pushes race, leaving the site stuck on the previous build. Add a composite action that, after each zensical deploy, waits for that deployment and reruns it up to three times until it succeeds. Wire it into the main, develop and preview workflows and grant them actions: write so they can rerun the run. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01DgcYQy7Mnh2afkmSg295uU --- .../actions/ensure-pages-published/action.yml | 73 +++++++++++++++++++ .github/workflows/zensical-develop.yml | 6 ++ .github/workflows/zensical-preview.yml | 4 + .github/workflows/zensical.yml | 6 ++ 4 files changed, 89 insertions(+) create mode 100644 .github/actions/ensure-pages-published/action.yml diff --git a/.github/actions/ensure-pages-published/action.yml b/.github/actions/ensure-pages-published/action.yml new file mode 100644 index 0000000..3049c7d --- /dev/null +++ b/.github/actions/ensure-pages-published/action.yml @@ -0,0 +1,73 @@ +name: Ensure Pages published +description: >- + Wait for GitHub's auto "pages build and deployment" of the current gh-pages + HEAD and rerun it (up to 3 attempts) if it fails with a transient error. + +runs: + using: composite + steps: + - shell: bash + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + run: | + set -euo pipefail + + target_sha="$(gh api "repos/$REPO/branches/gh-pages" --jq '.commit.sha')" + echo "Ensuring Pages is published for gh-pages@$target_sha" + + find_run() { + gh run list --repo "$REPO" --workflow "pages-build-deployment" \ + --commit "$target_sha" --limit 1 \ + --json databaseId,status,conclusion \ + --jq '.[0] // empty | "\(.databaseId) \(.status) \(.conclusion // "")"' 2>/dev/null || true + } + + # Block until a run for this SHA reaches "completed"; echo "id conclusion". + await_completed() { + for _ in $(seq 1 90); do + local info id status conclusion + info="$(find_run)" + id="$(printf '%s' "$info" | awk '{print $1}')" + status="$(printf '%s' "$info" | awk '{print $2}')" + conclusion="$(printf '%s' "$info" | awk '{print $3}')" + if [ -n "$id" ] && [ "$status" = "completed" ]; then + printf '%s %s\n' "$id" "$conclusion" + return 0 + fi + sleep 10 + done + return 1 + } + + for attempt in 1 2 3; do + echo "::group::Pages publish check (attempt $attempt/3)" + if ! result="$(await_completed)"; then + echo "Timed out waiting for the pages-build-deployment run." >&2 + echo "::endgroup::" + exit 1 + fi + run_id="${result%% *}" + conclusion="${result##* }" + echo "pages-build-deployment run $run_id -> $conclusion" + echo "::endgroup::" + + if [ "$conclusion" = "success" ]; then + echo "Pages published for gh-pages@$target_sha." + exit 0 + fi + + if [ "$attempt" -lt 3 ]; then + echo "Transient failure; rerunning run $run_id…" + gh run rerun "$run_id" --repo "$REPO" || true + # Let the rerun leave the "completed" state before we poll again. + for _ in $(seq 1 12); do + status="$(find_run | awk '{print $2}')" + [ "$status" != "completed" ] && break + sleep 5 + done + fi + done + + echo "Pages deployment still failing after 3 attempts for gh-pages@$target_sha." >&2 + exit 1 diff --git a/.github/workflows/zensical-develop.yml b/.github/workflows/zensical-develop.yml index 7fc6496..8c359db 100644 --- a/.github/workflows/zensical-develop.yml +++ b/.github/workflows/zensical-develop.yml @@ -9,6 +9,9 @@ on: concurrency: group: gh-pages-develop cancel-in-progress: true +permissions: + contents: write + actions: write jobs: deploy: runs-on: ubuntu-latest @@ -35,3 +38,6 @@ jobs: # Publish the develop build under /dev/ without touching the stable site at the root. target-folder: dev clean: true + + - name: Ensure Pages published (retry ×3) + uses: ./.github/actions/ensure-pages-published diff --git a/.github/workflows/zensical-preview.yml b/.github/workflows/zensical-preview.yml index 9fe8735..0d067fb 100644 --- a/.github/workflows/zensical-preview.yml +++ b/.github/workflows/zensical-preview.yml @@ -11,6 +11,7 @@ concurrency: cancel-in-progress: true permissions: contents: write + actions: write jobs: deploy: # Same-repo docs/* PRs only: fork PRs get a read-only token and cannot push to gh-pages. @@ -49,6 +50,9 @@ jobs: target-folder: preview/${{ steps.slug.outputs.name }} clean: true + - name: Ensure Pages published (retry ×3) + uses: ./.github/actions/ensure-pages-published + cleanup: # When a docs/* PR is merged or closed, remove its preview folder. if: >- diff --git a/.github/workflows/zensical.yml b/.github/workflows/zensical.yml index 06eae8a..2d0eef1 100644 --- a/.github/workflows/zensical.yml +++ b/.github/workflows/zensical.yml @@ -9,6 +9,9 @@ on: concurrency: group: gh-pages-main cancel-in-progress: false +permissions: + contents: write + actions: write jobs: deploy: runs-on: ubuntu-latest @@ -38,3 +41,6 @@ jobs: clean-exclude: | dev preview + + - name: Ensure Pages published (retry ×3) + uses: ./.github/actions/ensure-pages-published From 3d3d584f93f66452eb1112d6b48cb5f5849a6dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Alvergnat?= Date: Sun, 5 Jul 2026 14:53:13 +0200 Subject: [PATCH 2/2] ci: add progressive backoff and raise pages publish retries to 5 Under concurrent multi-repo Pages deploys, GitHub throttles at the account level and reruns fired seconds apart still fail. Wait a growing delay (30/60/90/120s) before each rerun and allow up to 5 attempts, so the retry absorbs the throttling window instead of exhausting itself immediately. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01DgcYQy7Mnh2afkmSg295uU --- .../actions/ensure-pages-published/action.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/actions/ensure-pages-published/action.yml b/.github/actions/ensure-pages-published/action.yml index 3049c7d..fac9659 100644 --- a/.github/actions/ensure-pages-published/action.yml +++ b/.github/actions/ensure-pages-published/action.yml @@ -1,7 +1,7 @@ name: Ensure Pages published description: >- Wait for GitHub's auto "pages build and deployment" of the current gh-pages - HEAD and rerun it (up to 3 attempts) if it fails with a transient error. + HEAD and rerun it (with backoff) if it fails with a transient error. runs: using: composite @@ -10,6 +10,7 @@ runs: env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} + ATTEMPTS: "5" run: | set -euo pipefail @@ -25,7 +26,7 @@ runs: # Block until a run for this SHA reaches "completed"; echo "id conclusion". await_completed() { - for _ in $(seq 1 90); do + for _ in $(seq 1 60); do local info id status conclusion info="$(find_run)" id="$(printf '%s' "$info" | awk '{print $1}')" @@ -40,8 +41,8 @@ runs: return 1 } - for attempt in 1 2 3; do - echo "::group::Pages publish check (attempt $attempt/3)" + for attempt in $(seq 1 "$ATTEMPTS"); do + echo "::group::Pages publish check (attempt $attempt/$ATTEMPTS)" if ! result="$(await_completed)"; then echo "Timed out waiting for the pages-build-deployment run." >&2 echo "::endgroup::" @@ -57,8 +58,12 @@ runs: exit 0 fi - if [ "$attempt" -lt 3 ]; then - echo "Transient failure; rerunning run $run_id…" + if [ "$attempt" -lt "$ATTEMPTS" ]; then + # Progressive backoff: transient failures are usually account-level + # Pages throttling under concurrent deploys — give it room to clear. + backoff=$((attempt * 30)) + echo "Transient failure; waiting ${backoff}s before rerunning run $run_id…" + sleep "$backoff" gh run rerun "$run_id" --repo "$REPO" || true # Let the rerun leave the "completed" state before we poll again. for _ in $(seq 1 12); do @@ -69,5 +74,5 @@ runs: fi done - echo "Pages deployment still failing after 3 attempts for gh-pages@$target_sha." >&2 + echo "Pages deployment still failing after $ATTEMPTS attempts for gh-pages@$target_sha." >&2 exit 1