Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,6 +77,11 @@ jobs:
id: changesets
uses: changesets/action@v1
with:
# publish (pnpm run release) ends in scripts/release-publish.sh,
# which pushes all new version tags in ONE atomic git push. This
# pre-empts changesets/action's own concurrent per-tag pushes, which
# otherwise race GitHub's ref backend (remote: fatal error in
# commit_refs) and reject ~half the tags on a large fixed-group bump (#2191).
publish: pnpm run release
version: pnpm run version
commit: 'chore: version packages'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,7 +15,7 @@
"clean": "turbo run clean && rm -rf dist",
"setup": "pnpm install && pnpm --filter @objectstack/spec build",
"version": "changeset version",
"release": "pnpm run build && bash scripts/build-console.sh && changeset publish",
"release": "pnpm run build && bash scripts/build-console.sh && bash scripts/release-publish.sh",
"docs:dev": "pnpm --filter @objectstack/docs dev",
"docs:build": "pnpm --filter @objectstack/docs build",
"docs:start": "pnpm --filter @objectstack/docs start",
Expand Down
36 changes: 36 additions & 0 deletions scripts/release-publish.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# release-publish.sh — npm publish + atomic git-tag push for the Release workflow.
#
# Why this exists (the bug it fixes):
# `changeset publish` publishes every package to npm and creates a local
# annotated git tag (`<pkg>@<version>`) for each one. changesets/action
# then pushes those tags — but it fires one `git push origin <tag>` per tag
# *concurrently* (Promise.all). With this monorepo's large Changesets "fixed"
# group (~70+ packages all bumping in lockstep), that burst of simultaneous
# ref-creation pushes races on GitHub's ref backend, which responds with
# `remote: fatal error in commit_refs` and rejects a chunk of the tags. npm
# publishing has already fully succeeded by then, yet the job fails and the
# rejected version tags never make it to the remote (#2191).
#
# The fix:
# Push ALL new tags ourselves in a SINGLE atomic `git push origin --tags`
# immediately after `changeset publish`. One push = one ref transaction, so
# there is no concurrency to race. By the time changesets/action runs its own
# per-tag pushes, every tag already exists on the remote at the same SHA, so
# each of those pushes is a harmless no-op ("Everything up-to-date").
#
# git push auth comes from the persisted actions/checkout credentials. The
# tags themselves are already created by `changeset publish` (which configures
# the CI git identity); this script only pushes them. Run as the `publish:`
# command of changesets/action (see
# .github/workflows/release.yml) so the atomic push happens before the action
# pushes tags itself.
set -euo pipefail

# Publish to npm and create the local version tags.
changeset publish

# Push every new tag in one atomic transaction (see header). --tags pushes ALL
# local tags regardless of reachability; --follow-tags would push nothing here
# since this is a bare push with no branch ref attached.
git push origin --tags