Skip to content

Commit 7c77d10

Browse files
authored
fix: use semver-compliant dev version numbering (#479)
* fix: use semver-compliant dev version numbering Change dev release scheme from MAJOR.MINOR.(PATCH+COMMITS)-dev.SHA to MAJOR.MINOR.(PATCH+1)-dev.COMMITS. The old scheme inflated the patch number (e.g. 3.1.49 for 45 commits after 3.1.4), colliding with the real semver space. The new scheme keeps dev versions in the correct prerelease range (e.g. 3.1.5-dev.45) — npm never picks them up on plain install, they sort correctly, and the target release is obvious. Updated in publish.yml, scripts/bench-version.js, and dogfood skill. Impact: 1 functions changed, 0 affected * fix: align version computation between publish.yml and bench-version.js - Add COMMITS=0 guard in publish.yml to return clean version when HEAD is exactly at a tag (mirrors bench-version.js early return) - Change bench-version.js to use PATCH+1-dev.COMMITS format instead of PATCH+COMMITS-dev.SHA (mirrors publish.yml's new scheme) - Fix fallback in bench-version.js to use dev.1 matching publish.yml's no-tags COMMITS=1 default Impact: 1 functions changed, 0 affected
1 parent fe08b9b commit 7c77d10

3 files changed

Lines changed: 21 additions & 21 deletions

File tree

.claude/skills/dogfood/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Your goal is to install the published package, exercise every feature, compare e
2424
npm init -y && npm install @optave/codegraph@$ARGUMENTS
2525
```
2626

27-
**Dev build** (version contains `-dev.`, e.g. `2.5.33-dev.3c36ef7`):
27+
**Dev build** (version contains `-dev.`, e.g. `3.1.6-dev.12`):
2828
Dev builds are **not published to npm**. They are attached as tarballs to GitHub pre-releases. Install from the GitHub release:
2929
```bash
3030
npm init -y

.github/workflows/publish.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,11 @@ jobs:
6767
NPM_TAG="latest"
6868
echo "Stable release (manual retry): $VERSION"
6969
else
70-
# Use git describe to find the nearest release tag — same strategy
71-
# as scripts/bench-version.js so versions are always consistent.
70+
# Dev versions use the NEXT patch with a prerelease suffix:
71+
# v3.1.5 tag + 12 commits → 3.1.6-dev.12
72+
# This keeps dev versions in the correct semver range (between
73+
# the current release and the next) and avoids inflating the
74+
# patch number (old scheme produced 3.1.17 for 12 commits after 3.1.5).
7275
RELEASE_TAG=$(git describe --tags --match "v*" --abbrev=0 2>/dev/null || echo "")
7376
if [ -n "$RELEASE_TAG" ]; then
7477
COMMITS=$(git rev-list "${RELEASE_TAG}..HEAD" --count)
@@ -77,9 +80,11 @@ jobs:
7780
COMMITS=1
7881
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
7982
fi
80-
DEV_PATCH=$((PATCH + COMMITS))
81-
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
82-
VERSION="${MAJOR}.${MINOR}.${DEV_PATCH}-dev.${SHORT_SHA}"
83+
if [ "$COMMITS" -eq 0 ]; then
84+
VERSION="${MAJOR}.${MINOR}.${PATCH}"
85+
else
86+
VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))-dev.${COMMITS}"
87+
fi
8388
NPM_TAG="dev"
8489
echo "Dev release: $VERSION (${COMMITS} commits since ${RELEASE_TAG:-none})"
8590
fi

scripts/bench-version.js

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/**
22
* Compute the benchmark version string from git state.
33
*
4-
* Uses the same two-step strategy as publish.yml's compute-version job:
4+
* Uses the same strategy as publish.yml's compute-version job:
55
* 1. `git describe --tags --match "v*" --abbrev=0` → find nearest release tag
66
* 2. `git rev-list <tag>..HEAD --count` → count commits since that tag
77
*
8-
* - If HEAD is exactly tagged (0 commits): returns "2.5.0"
9-
* - Otherwise: returns "2.5.N-dev.hash" (e.g. "2.5.3-dev.c50f7f5")
10-
* where N = PATCH + commits since tag, hash = short commit SHA
8+
* - If HEAD is exactly tagged (0 commits): returns "3.1.5"
9+
* - Otherwise: returns "3.1.6-dev.12" (NEXT_PATCH-dev.COMMIT_COUNT)
10+
* This keeps dev versions in the correct semver range between the
11+
* current release and the next, avoiding inflated patch numbers.
1112
*
1213
* This prevents dev/dogfood benchmark runs from overwriting release data
1314
* in the historical benchmark reports (which deduplicate by version).
@@ -38,24 +39,18 @@ export function getBenchmarkVersion(pkgVersion, cwd) {
3839
// Exact tag (0 commits since tag): return clean release version
3940
if (commits === 0) return `${major}.${minor}.${patch}`;
4041

41-
// Dev build: MAJOR.MINOR.(PATCH+COMMITS)-dev.SHORT_SHA
42-
const hash = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd, ...GIT_OPTS }).trim();
43-
const devPatch = Number(patch) + commits;
44-
return `${major}.${minor}.${devPatch}-dev.${hash}`;
42+
// Dev build: MAJOR.MINOR.(PATCH+1)-dev.COMMITS
43+
const nextPatch = Number(patch) + 1;
44+
return `${major}.${minor}.${nextPatch}-dev.${commits}`;
4545
} catch {
4646
/* git not available or no tags */
4747
}
4848

49-
// Fallback: no git or no tags — match publish.yml's no-tags behavior (PATCH+1-dev.SHA)
49+
// Fallback: no git or no tags — match publish.yml's no-tags behavior (COMMITS=1)
5050
const parts = pkgVersion.split('.');
5151
if (parts.length === 3) {
5252
const [major, minor, patch] = parts;
53-
try {
54-
const hash = execFileSync('git', ['rev-parse', '--short', 'HEAD'], { cwd, ...GIT_OPTS }).trim();
55-
return `${major}.${minor}.${Number(patch) + 1}-dev.${hash}`;
56-
} catch {
57-
return `${major}.${minor}.${Number(patch) + 1}-dev`;
58-
}
53+
return `${major}.${minor}.${Number(patch) + 1}-dev.1`;
5954
}
6055
return `${pkgVersion}-dev`;
6156
}

0 commit comments

Comments
 (0)