fix/pre-push-ghost-versionsCloses #1457.
Two manual bump-version.sh minor calls in the last 72 hours created tag-less version numbers:
v7.65.0 ← tagged (just now) v7.63.1 ← tagged v7.63.0 ← tagged v7.61.0 ← tagged v7.62.0 ← GHOST — my bump, release-please picked 7.63.0 v7.64.0 ← GHOST — my bump, release-please picked 7.65.0 v7.60.0 ← tagged
Version enforcement lives in two places that must stay in lock-step:
bin/git-hooks/pre-push L23 — local fail-fast.github/workflows/version-check.yml L41 — server-side "Validate: Version" gateBoth enforced manual version bumps on feat/fix/perf/refactor/* branches. Release-please (release-type: simple) computes its own next version from conventional-commit types since last tag and overwrites whatever the manual bump produced. When they disagreed, the manually-typed version became a ghost.
version-check and Version Bump before scoping a gate fix.bin/git-hooks/pre-push- if [[ "$BRANCH" =~ ^(docs|chore|ci|style|test)/ ]]; then + if [[ "$BRANCH" =~ ^(docs|chore|ci|style|test|feat|fix|perf|refactor)/ ]]; then echo " ✓ Skipping version check for $BRANCH" exit 0 fi
.github/workflows/version-check.yml- if [[ "$BRANCH_NAME" =~ ^(docs|chore|ci|style|test)/ ]]; then + if [[ "$BRANCH_NAME" =~ ^(docs|chore|ci|style|test|feat|fix|perf|refactor)/ ]]; then echo "skip=true" >> $GITHUB_OUTPUT exit 0 fi
tests/unit/test-pre-push-hook.shNew test_skip_regex_parity extracts the alternation group from both files and fails if they differ. Prevents the same two-layer split from recurring.
Release-please now owns version decisions on all conventional-commit branches. Both layers agree. Bare-named branches (hotfix-auth-bug, quick-patch) still trigger the check for legitimate manual control.
CONTRIBUTING.md gains a "Versioning" section documenting:
bump-version.sh on conventional-commit branchesrelease-as commit footer if you need to override its computed nextgit config core.hooksPath = bin/git-hooks is already set. .git/hooks/pre-push is a symlink. Local change is live without a separate install step. CI workflow update takes effect on the next PR event.
Next feat/* or fix/* PR to main: pre-push runs, sees branch prefix in the new skip list, exits 0. Server-side gate does the same. Release-please opens a PR with its computed version, no ghost number.