Skip to content

Direct release: no working recovery when the branch push lands but a tag push fails #774

Open

Description

@goosewobbler

Problem

A direct release pushes the branch, then each tag, and sets git.pushed only after the last one (packages/publish/src/stages/git-push.ts:182-191). Per-package mode does the same for each package (#765). If a tag push fails after the branch push, the release commit is on main and the packages are published, but the tags and GitHub Releases are missing.

The failure report can't tell this case from a rejected branch push, because both leave git.pushed false. For a direct release it recommends GitHub's "Re-run failed jobs" (packages/release/src/failure-report/failure-report.ts:160), and docs/troubleshooting.md:254 says the same. #762 rewords the report's state line to say the branch "may" be on the remote, but keeps that recovery.

What a re-run does

The re-run checks out the original trigger commit, not the release commit, so the resume path from #709 doesn't apply. It:

  1. computes the same version, since the tag never reached the remote;
  2. creates a second release commit on the old base;
  3. skips the packages already on the registry;
  4. pushes the branch, which is rejected as non-fast-forward because main already has the first release commit.

So the re-run fails at the same stage every time. Nothing is corrupted, but the report offers no way out. (Traced, not run.)

What works today

  • Roll forward. The next release reads the bumped package.json version and bumps past the failed one, under the default mismatchStrategy: 'warn' and under 'prefer-package'. Under 'error' it throws a version mismatch instead. The failed version never gets a tag or a GitHub Release.
  • Recreate the tags by hand on the release commit and push them. That restores the tags, not the GitHub Releases.

Fix

This needs a decision on the recovery path:

  • Record that the branch push landed, e.g. an optional git.branchPushed on PublishOutput, so the report can tell this case from a rejected branch push.
  • Choose what the report recommends for this case:
    • recreate and push the missing tags on the release commit, then create the GitHub Releases, possibly with a command or action mode that works from the failure report's data;
    • or roll forward, noting the mismatchStrategy: 'error' caveat.
  • Cover per-package runs too (below).
  • Update docs/troubleshooting.md to match.

Standing-PR mode isn't affected: its publish pushes tags only, and release:retry recreates them on the merge commit.

Per-package runs (moved from #735, item 3)

In per-package mode each package pushes the branch, then its tag, as it publishes, and GitHub Releases wait until every package succeeds. If a later package fails, a re-run recreates the release commit at a new SHA, finds the earlier packages' tags on the remote at a different commit, and throws GIT_TAG_ERROR (packages/publish/src/stages/git-commit.ts:105-127; traced, not run).

#762 settles that case the documented way: once a per-package run has pushed, the report recommends rolling forward and leaves out the "Retrying is safe" note. Two gaps remain for this issue:

  • The first package's tag push fails after its branch push. git.pushed is still false, so the report recommends a re-run, which fails for the reasons above.
  • Packages that published never get a GitHub Release. Their tags are on the remote, but releases are only created after every package succeeds. If the decision here is to restore missing tags and releases rather than roll forward, it should create these too.

Related: #765 set the per-package push order, and #762 the report wording this builds on.

Found while reviewing #762.

Activity

  1. modified the milestones: 0.43.0, 0.46.0 on Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:bugSomething isn't working

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions