fix: tag the version-bump commit so released tags carry their own version#97
Conversation
…sion The release workflow created the git tag at main HEAD *before* generate-changelog.ts bumped shard.yaml / vault-manifest.json and committed the result, so the tagged tree always lagged one version behind its tag: v6.2 tag -> tree says version 6.1.0 v6.1 tag -> tree says version 6.0.0 ShardMind reads the manifest `version:` as the shard's identity (and `shardmind update` keys off it), so `shardmind install github:...` resolved the correct latest tag but reported the stale version, and consecutive stale versions can make update detection misfire. generate-changelog.ts already bumps both manifests correctly — the bug was purely ordering. Fix: - Don't create the tag up front. Keep only a pre-flight "tag must not exist" guard on the manual trigger. - After committing the version bump to main, tag THAT commit and push it (-f/--force so the push:tags trigger's pre-bump tag moves forward). - Add a verification step that fails the release if the tagged tree's shard.yaml / vault-manifest version doesn't match the tag (2-component tags like v6.2 are normalized to 6.2.0 for the check). Scope: release pipeline only. No hook-lifecycle changes (PR #96). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a release workflow ordering bug so the git tag is applied to the version-bump commit, ensuring released tags contain manifests (.shardmind/shard.yaml, vault-manifest.json) with the matching version.
Changes:
- Replaces early tag creation with a pre-flight “tag must not already exist” guard for manual releases.
- Tags and force-pushes the tag after committing the changelog/manifests bump to
main. - Adds a verification step to fail the release if the tagged tree’s manifest versions don’t match the tag (with 2-component tag normalization).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if git ls-remote --tags origin "refs/tags/$VERSION" | grep -q .; then | ||
| echo "::error::Tag $VERSION already exists" | ||
| exit 1 | ||
| fi | ||
| git tag "$VERSION" | ||
| git push origin "$VERSION" | ||
|
|
There was a problem hiding this comment.
Fixed in ecba4a5. Restored the tag creation as a local, unpushed staged tag (manual-trigger step) before generate-changelog.ts runs, so getPreviousTag's second-newest assumption holds and prevTag is correct. The later 'Tag the release commit' step moves it onto the bump commit and force-pushes — keeping the no-skew fix.
| shard=$(git show "$VERSION:.shardmind/shard.yaml" | sed -n 's/^version:[[:space:]]*//p' | head -1) | ||
| manifest=$(git show "$VERSION:vault-manifest.json" | sed -n 's/.*"version":[[:space:]]*"\([^"]*\)".*/\1/p' | head -1) | ||
| echo "tag=$VERSION expected=$want shard.yaml=$shard vault-manifest=$manifest" | ||
| if [ "$shard" != "$want" ] || [ "$manifest" != "$want" ]; then | ||
| echo "::error::Tagged tree version skew (shard.yaml=$shard manifest=$manifest, expected $want)" | ||
| exit 1 | ||
| fi |
Make the git tag match the 3-component manifest version ShardMind resolves against. The Resolve-version step now normalizes vX / vX.Y to vX.Y.0 (vX.Y.Z passes through), so workflow_dispatch cuts v6.2.0 rather than v6.2. For the push:tags trigger, a human-pushed 2-component tag (v6.2) is recorded as TRIGGER_TAG and retired after the canonical v6.2.0 tag is created at the bump commit, so no stale duplicate lingers on the pre-bump commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| shard=$(git show "$VERSION:.shardmind/shard.yaml" | sed -n 's/^version:[[:space:]]*//p' | head -1) | ||
| manifest=$(git show "$VERSION:vault-manifest.json" | sed -n 's/.*"version":[[:space:]]*"\([^"]*\)".*/\1/p' | head -1) | ||
| echo "tag=$VERSION expected=$want shard.yaml=$shard vault-manifest=$manifest" | ||
| if [ "$shard" != "$want" ] || [ "$manifest" != "$want" ]; then | ||
| echo "::error::Tagged tree version skew (shard.yaml=$shard manifest=$manifest, expected $want)" | ||
| exit 1 |
There was a problem hiding this comment.
Fixed in ecba4a5. The verify step now always checks vault-manifest.json (present in every vault) and checks .shardmind/shard.yaml only when it exists in the tag (via git cat-file -e), matching the ENOENT-tolerance of the commit step and generate-changelog.ts. (Same concern as the earlier thread on the first review round.)
| if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| echo "::error::Invalid version format: $VERSION (expected vX.Y or vX.Y.Z)" | ||
| exit 1 |
There was a problem hiding this comment.
Fixed in ecba4a5. Error message now reads 'accepted inputs: vX, vX.Y, or vX.Y.Z, with or without the leading v'.
Three fixes from the PR #97 review: - prevTag off-by-one: generate-changelog.ts derives the previous release as the second-newest tag, assuming the current release tag exists. Removing the early tag creation broke that on workflow_dispatch. Restore it as a LOCAL (unpushed) staged tag before the script runs; it's moved onto the bump commit and force-pushed later. - verify step ENOENT-tolerance: always verify vault-manifest.json (present in every vault); verify .shardmind/shard.yaml only when it exists in the tag, so non-ShardMind forks stay releasable like the sibling steps already allow. - error message: list the actual accepted inputs (vX, vX.Y, vX.Y.Z). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Fixes a release-pipeline bug where the git tag was cut before the version-bump commit, so every released tag's tree carried the previous version in its manifests. Surfaced by the shardmind 0.1.3 pre-release smoke test installing the obsidian-mind flagship. Also normalizes release tags to 3-component semver so the tag matches the manifest version ShardMind resolves.
Evidence
The bump commit (
release: update CHANGELOG and manifests for vX) lands onmainafter the tag, so it's never reachable from the tag.Why it matters
ShardMind reads the manifest
version:as the shard's identity, soshardmind install github:breferrari/obsidian-mindresolves the correct latest tag (the new hooks ran,requires.shardmindwas satisfied) but reports the stale version. Worse,shardmind updatekeys off the manifest version — consecutive releases shipping the same stale version can make update detection misfire.Root cause (correction to initial triage)
generate-changelog.tsalready bumps bothshard.yamlandvault-manifest.jsonto 3-component semver —mainHEAD is correctly6.2.0. The bug is purely tag ordering inrelease.yml, so this PR leavesgenerate-changelog.tsuntouched.Fix (
.github/workflows/release.yml)main, tag that commit and push it (-f/--forceso thepush:tagstrigger's pre-bump tag moves forward).shard.yaml/vault-manifest.jsonversion doesn't match the tag — the regression guard for this exact skew.vX/vX.Y→vX.Y.Z(so dispatch cutsv6.2.0, notv6.2). A 2-componentpush:tagstrigger (v6.2) is recorded and the stale duplicate retired oncev6.2.0is created. Old 2-component tags (v6.0/v6.1/v6.2) are left as historical.Backfill (already done, out-of-band)
mainHEAD already had correct6.2.0manifests, so the livev6.2tag was re-pointed tomainHEAD (169df57). Verified:raw.githubusercontent.com/.../v6.2/.shardmind/shard.yamlnow showsversion: 6.2.0.Test plan
6.2→v6.2.0,v6.2.1unchanged,push v6.2→createsv6.2.0+ retiresv6.2curl -sL https://raw.githubusercontent.com/breferrari/obsidian-mind/<tag>/.shardmind/shard.yaml | grep '^version:'matches the 3-component tag, and a freshshardmind installreports@<version>🤖 Generated with Claude Code