Skip to content

Cutting a release publishes every local tag on the maintainer's machine — v0.10.0 pushed a private salvage tag alongside it #457

Description

@50rayn

Cutting v0.10.0 pushed two tags, not one:

To github.com:poveste-dev/poveste.git
 * [new tag]           salvage/amazing-cerf-61cd4c -> salvage/amazing-cerf-61cd4c
 * [new tag]           v0.10.0 -> v0.10.0

salvage/amazing-cerf-61cd4c is a local tag on a maintainer's machine, pointing at 66550fae"fix(poveste): let the watcher ignore globs cross dot segments", authored 23 August and not reachable from any branch. It had nothing to do with this release and is now public.

What is actually wrong

package.json:38:

"release": "pnpm run release:check && bumpp --yes --release"

bumpp pushes tags without restricting itself to the one it just created, so every local tag on the machine cutting the release is published. Whatever a maintainer tagged while bisecting, salvaging a worktree or parking an experiment leaks to a public repository on the next release, under their name.

Nothing was harmed this time. The general case is worse than a stray name: a tag pointing at an unmerged branch publishes that code, and a tag whose name reveals something about unreleased work publishes that too.

This is invisible from CI

release.yml never sees it — the push happens on the maintainer's machine before the tag reaches GitHub and starts the workflow. No gate can catch it, and the only reason it was noticed is that the push output happened to be read.

Two ways to fix

Push the release tag explicitly. Configure bumpp so the push is the commit plus v<version> rather than --tags, or drive the push directly after --no-push. Precise, and it makes the release say what it pushed.

Or make the check a preflight. release:check already gates on lint, build, tests and the smoke test; it could also fail when the local tag list contains anything that is not v*, naming what it found. That catches the class rather than this instance, and it runs before anything is pushed.

The first is the actual fix. The second is worth having anyway, because a machine that cuts releases accumulating stray tags is the condition that made this possible.

Do not delete the stray tag

66550fae is not an ancestor of main. Deleting salvage/amazing-cerf-61cd4c removes the only reference to that commit and it becomes unreachable. Decide whether the watcher fix is wanted — it looks related to the createWatchIgnore work — and land or discard it deliberately, rather than dropping the tag as cleanup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:ciWorkflows, runners, test harnessa:repoRepo-wide: docs site, policy, tracking, anything without a single packagesprint:5-releaseRelease-path gaps from the 0.5 incident; no user impact

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions