Files
pbakaus_impeccable/.github/workflows/sync-generated-output.yml
T
Paul BakausandClaude Code bea601ac76 Skip the pointless final-attempt rebuild; stop misattributing push failures
Copilot's two review points: the fifth attempt performed a full
reset + install + rebuild + 25s backoff that nothing would ever consume
before the job failed, and the retry message blamed "main advanced"
when the combined condition also fails on push errors (network, auth).
The loop now breaks before recovery on the final attempt, and both the
retry and terminal messages name the two possible causes.

Prepared with AI assistance (Claude Code), directed by @pbakaus.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-07-25 19:43:03 -07:00

129 lines
4.0 KiB
YAML

name: Sync Generated Provider Output
on:
push:
branches: [main]
paths:
- ".claude-plugin/**"
- "cli/engine/**"
- "skill/**"
- "scripts/**"
- "package.json"
- "bun.lock"
workflow_dispatch:
permissions:
contents: write
concurrency:
group: sync-generated-output
cancel-in-progress: false
env:
GENERATED_PATHS: >-
.agents
.claude
.cursor
.gemini
.github/skills
.grok
.kiro
.opencode
.pi
.qoder
.rovodev
.trae
.trae-cn
.vibe
plugin
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
# Optional PAT or GitHub App token. With the default GITHUB_TOKEN,
# GitHub suppresses follow-up workflow runs from the generated commit.
token: ${{ secrets.SYNC_GENERATED_OUTPUT_TOKEN || github.token }}
- name: Setup Node
uses: actions/setup-node@v7
with:
node-version: 24
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build release output
run: bun run build:release
- name: Check generated output drift
id: drift
run: |
changes="$(git status --porcelain -- $GENERATED_PATHS)"
if [ -z "$changes" ]; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No generated provider output drift."
else
echo "changed=true" >> "$GITHUB_OUTPUT"
printf '%s\n' "$changes"
fi
- name: Commit generated output
if: steps.drift.outputs.changed == 'true'
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# A push can lose the race against a human commit landing on main
# during the ~30s build window (issue #388: ~10% of runs). Instead
# of aborting and waiting for an unrelated push to re-trigger the
# sync, re-sync to the latest main, rebuild against the current
# source, and push again, with backoff. Every attempt builds from
# a fresh origin/main, so pushed output always matches the source
# state it lands on.
for attempt in 1 2 3 4 5; do
git add $GENERATED_PATHS
if git diff --cached --quiet; then
# The race that beat us was another sync (or the rebuilt output
# matches the new main); nothing left to push.
echo "No generated output drift after rebuild (attempt $attempt); nothing to push."
exit 0
fi
git commit -m "Sync generated provider output"
git fetch origin main
if git merge-base --is-ancestor origin/main HEAD && git push origin HEAD:main; then
echo "Pushed generated output on attempt $attempt."
exit 0
fi
# The recovery work is pointless on the final attempt: nothing
# would consume the rebuild, and the backoff would only delay
# the failure.
if [ "$attempt" = 5 ]; then break; fi
echo "Push did not land on attempt $attempt (main advanced, or the push itself failed); re-syncing and rebuilding."
git reset --hard origin/main
bun install --frozen-lockfile
bun run build:release
sleep $((attempt * 5))
done
echo "::error::Could not push generated output after 5 attempts (main kept advancing, or pushes kept failing); rerun this workflow on the latest main."
exit 1
- name: Summarize generated output commit
if: steps.drift.outputs.changed == 'true'
run: |
echo "Committed generated provider output directly to main." >> "$GITHUB_STEP_SUMMARY"