Skip to content

fix(release): keep finalize versions on main#437

Merged
christso merged 1 commit into
mainfrom
fix/finalize-on-main
Jul 13, 2026
Merged

fix(release): keep finalize versions on main#437
christso merged 1 commit into
mainfrom
fix/finalize-on-main

Conversation

@christso

Copy link
Copy Markdown
Contributor

Summary

Finalizing a prerelease now leaves the stable package version on main instead of publishing it only from a detached tag commit. A fresh finalize requires main to point exactly at the selected prerelease, commits the stable version there, and pushes both main and the annotated stable tag.

Finalize now rejects an advanced or divergent main with guidance to create a new prerelease. For releases already created by the old detached flow, it can idempotently fast-forward main to the existing stable tag only when the selected prerelease is its ancestor; it never forces or overwrites history. The trusted workflow still validates the selected tag and continues publishing from the resolved release tag.

Related: EntityProcess/agentv#1437

Validation

The regression tests run the real release script against disposable repositories and bare remotes. Before implementation, all five focused checks failed for the expected reasons; after the fix:

  • bun run build
  • bun run typecheck
  • bun run lint
  • bun test tests/unit/scripts/release.test.ts — 5 passed
  • bun test — 1,326 passed, 5 skipped
  • bun run test:e2e — 116 passed, 4 skipped
  • bun -e "import { readFileSync } from 'node:fs'; import yaml from 'js-yaml'; yaml.load(readFileSync('.github/workflows/publish.yml', 'utf8'));"
  • git diff --check

The focused tests cover fresh success, advanced-main rejection, safe detached-tag recovery with an idempotent retry, unsafe divergent-tag rejection, and workflow tag validation without detaching.

Manual bare-remote E2E:

RELEASE_SCRIPT="$PWD/scripts/release.ts"
TMP=$(mktemp -d /tmp/allagents-finalize-e2e.XXXXXX)
REMOTE="$TMP/origin.git"
REPO="$TMP/repo"

git init --bare --initial-branch=main "$REMOTE"
git init --initial-branch=main "$REPO"
git -C "$REPO" config --local user.name "Release E2E"
git -C "$REPO" config --local user.email "release-e2e@example.com"
printf '{\n  "name": "allagents-release-e2e",\n  "version": "3.0.0"\n}\n' > "$REPO/package.json"
git -C "$REPO" add package.json
git -C "$REPO" commit -m "base release"
printf '{\n  "name": "allagents-release-e2e",\n  "version": "3.1.0-next.1"\n}\n' > "$REPO/package.json"
git -C "$REPO" add package.json
git -C "$REPO" commit -m "chore(release): bump version to 3.1.0-next.1"
git -C "$REPO" tag -a v3.1.0-next.1 -m "Release 3.1.0-next.1"
git -C "$REPO" remote add origin "$REMOTE"
git -C "$REPO" push -u origin main
git -C "$REPO" push origin v3.1.0-next.1

(cd "$REPO" && bun "$RELEASE_SCRIPT" finalize v3.1.0-next.1)
test "$(git --git-dir="$REMOTE" rev-parse refs/heads/main)" = "$(git --git-dir="$REMOTE" rev-parse 'refs/tags/v3.1.0^{}')"
test "$(git --git-dir="$REMOTE" cat-file -t refs/tags/v3.1.0)" = tag
git --git-dir="$REMOTE" show refs/heads/main:package.json
git -C "$REPO" branch --show-current

This produced the same commit for remote main and peeled v3.1.0, an annotated tag object, stable package version 3.1.0, and current branch main.

Operational note

The already-published v1.13.1 cannot use automatic recovery now. Its stable commit 6814b807 and current origin/main commit 174a5997 are sibling descendants of v1.13.1-next.1 (b520d060), so neither can fast-forward to the other. Finalize will correctly reject that state; do not force-update main or move the published tag. Repair requires an explicit maintainer-reviewed version normalization on current main, or a new prerelease/stable version from current main (for example 1.13.2-next.1).

Post-Deploy Monitoring & Validation

  • Window/owner: the release operator should validate the first finalize run after merge.
  • Healthy signals: the prepare job logs a release commit on main, pushes both main and the stable tag, and the remote main SHA equals the stable tag's peeled SHA before npm publication.
  • Failure signals: a detached-HEAD commit, mismatched remote SHAs, any non-fast-forward attempt, or finalize accepting an advanced main.
  • Mitigation: stop the release, preserve both refs, and create a new prerelease from current main; never force-push or retag an already-published version.

Compound Engineering
GPT-5

@christso christso merged commit 7f8860c into main Jul 13, 2026
5 checks passed
@christso christso deleted the fix/finalize-on-main branch July 13, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant