Skip to content

Commit 34c22ff

Browse files
MajorTalclaude
andauthored
ci(publish): make the lockstep version-bump commit-back rebase-safe (#424)
Same fragility as run402-private's publish-functions (fixed there): the 'Commit version bump' step did a bare 'git push origin main', which loses a push race with any concurrent merge — leaving run402-mcp/run402/@run402/sdk published on npm but main un-bumped with no tag/release. Now it rebuilds the (already-published) lockstep bump on the LATEST main each attempt — fetch + reset --hard origin/main + re-set the exact published version across all three package.json (root via npm version, cli/sdk via node -e, mirroring the bump step) + npm install --package-lock-only — which is conflict-free, then retries the push up to 5x with backoff. Idempotent. dry_run path unchanged. YAML validated. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 75873e1 commit 34c22ff

1 file changed

Lines changed: 40 additions & 4 deletions

File tree

.github/workflows/publish.yml

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,49 @@ jobs:
267267
}
268268
publish_idempotent "@run402/sdk"
269269
270-
- name: Commit version bump
270+
- name: Commit version bump (rebase-safe — retries against a moving main)
271271
if: ${{ !inputs.dry_run }}
272272
run: |
273273
set -euo pipefail
274-
git add package.json cli/package.json sdk/package.json package-lock.json
275-
git commit -m "chore: bump version to v${{ steps.bump.outputs.new }}"
276-
git push origin main
274+
NEW="${{ steps.bump.outputs.new }}"
275+
# All three packages are already published at v$NEW (irreversible).
276+
# This step only records the lockstep bump on main. A bare
277+
# `git push origin main` loses a push race with ANY concurrent merge,
278+
# leaving npm ahead of main with no version-bump commit and no
279+
# tag/release. So rebuild the bump on top of the LATEST main each
280+
# attempt — reset, re-set the exact published version across all three
281+
# package.json, re-sync the lockfile — which is conflict-free, and
282+
# retry the push.
283+
for attempt in 1 2 3 4 5; do
284+
git fetch origin main
285+
git reset --hard origin/main
286+
npm version "$NEW" --no-git-tag-version --allow-same-version >/dev/null
287+
node -e "
288+
const fs = require('fs');
289+
for (const path of ['cli/package.json', 'sdk/package.json']) {
290+
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));
291+
pkg.version = '$NEW';
292+
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
293+
}
294+
"
295+
npm install --package-lock-only >/dev/null
296+
git add package.json cli/package.json sdk/package.json package-lock.json
297+
if git diff --cached --quiet; then
298+
echo "main is already at v$NEW — nothing to commit."
299+
break
300+
fi
301+
git commit -m "chore: bump version to v$NEW"
302+
if git push origin HEAD:main; then
303+
echo "Pushed v$NEW lockstep bump on attempt $attempt."
304+
break
305+
fi
306+
if [ "$attempt" -eq 5 ]; then
307+
echo "::error::Could not push the v$NEW bump to main after 5 attempts. All three packages ARE published; main needs a manual commit-back (set package.json + cli/package.json + sdk/package.json to $NEW + npm install --package-lock-only)."
308+
exit 1
309+
fi
310+
echo "Push rejected (main advanced); rebuilding on fresh main and retrying ($attempt/5)…"
311+
sleep "$((attempt * 2))"
312+
done
277313
278314
- name: Tag and push
279315
if: ${{ !inputs.dry_run }}

0 commit comments

Comments
 (0)