Skip to content

feat(scripts): support stable and tagged (prerelease) version releases - #85

Open
GOODBOY008 wants to merge 10 commits into
mainfrom
docs/release-version-skill
Open

feat(scripts): support stable and tagged (prerelease) version releases#85
GOODBOY008 wants to merge 10 commits into
mainfrom
docs/release-version-skill

Conversation

@GOODBOY008

@GOODBOY008 GOODBOY008 commented Aug 11, 2026

Copy link
Copy Markdown
Owner

What

Makes stable (v2.8.0) and tagged (v2.8.0-beta.1, v2.8.0-rc.1) releases first-class in the r-shell release tooling, end to end — with release-tooling guardrails borrowed from semantic-release / changesets and the openusage Tauri app.

Changes

src/lib/version-bump.mjs (new) — single source of truth for all pure version/CHANGELOG/tag logic, shared by the CLI scripts and the unit tests. Lives under src/ so Vitest transforms it inside the project root (importing ESM from scripts/ outside the root trips a vite-node bug on Windows — see Notes).

scripts/bump-version.mjs — thin CLI on top of the lib, with stable major/minor/patch, prerelease [identifier], and stable bump types:

  • 2.7.0 → 2.8.0-beta.1 (opens the next minor line), 2.8.0-beta.1 → 2.8.0-beta.2 (continues), 2.8.0-beta.3 → 2.8.0-rc.1 (switches identifier), 2.8.0-beta.3 → 2.8.0 (finalize)
  • Robust semver parsing (including build metadata, which is dropped on any bump)
  • Preflight guardrails: refuses to bump when the four version files disagree or the working tree has uncommitted tracked changes (--force bypasses)
  • --dry-run plan preview, --yes to skip the confirmation prompt, --help
  • Prerelease/stable bumps rename the CHANGELOG section for the same release line instead of inserting duplicates; insertion is robust (works without an Unreleased section) and asserted after writing, and renamed headings no longer duplicate the - YYYY-MM-DD date
  • Cargo.lock updated by editing the root r-shell entry directly (like cargo set-version) with a cargo build fallback and post-edit verification

scripts/verify-release-tag.mjs (new, via pnpm run version:verify "vX.Y.Z") — validates a release tag's semver shape and compares it against package.json, Cargo.toml, Cargo.lock, and tauri.conf.json; fails with a per-file report on any mismatch.

.github/workflows/release.yml:

  • New validate-tag job fails fast before any build when the tag is malformed or mismatches the project version
  • prerelease: ${{ startsWith(github.ref, 'refs/tags/') && contains(github.ref_name, '-') }} — tagged prereleases are now created as GitHub prereleases (never Latest); previously a hardcoded false could let a v2.8.0-rc.1 tag auto-become Latest and hijack releases/latest
  • upload-updater-json / update-homebrew skip any tag with a dash (stable tags are always vX.Y.Z), so tagged prereleases can never hijack the stable updater channel or the Homebrew cask
  • concurrency group serializes overlapping release runs

package.jsonversion:prerelease, version:stable, and version:verify scripts.

.github/skills/release-version/SKILL.md — documents both release kinds: stable (--latest, drives in-app updater + Homebrew) vs tagged prerelease (--prerelease, never Latest), including tag naming, CHANGELOG handling, the new guardrails / --dry-run, and a pre-tag version:verify sanity check.

DocsAGENTS.md, README.md, scripts/README.md, .github/copilot-instructions.md updated.

Tests

  • 61 unit tests in src/__tests__/bump-version.test.ts (was 29) covering version transitions, semver edge cases, version-file drift detection, Cargo.lock rewriting, robust CHANGELOG insertion/rename (including the duplicate-date regression), and tag verification
  • Full suite green: 626 passed (50 files) locally; the CI test matrix (macOS, ubuntu, Windows) is green on this branch

Notes

  • The original branch's CI was red: Windows failed to load bump-version.test.ts with SyntaxError: Invalid or unexpected token, because Vitest cannot transform ESM imported from outside the project root (scripts/); ubuntu also flaked on the file-browser follow test. Moving the shared logic into src/lib/ fixed the Windows failure — the full matrix now passes (Windows runs 646 tests incl. merged main).
  • Rebased onto the PR's existing three commits (this branch is a direct descendant of the original docs/release-version-skill tip), with the enhancement as focused follow-up commits. The b1f6cd5 note from the base PR still applies.

Add 'prerelease [identifier]' and 'stable' bump types to bump-version.mjs so
both stable (vX.Y.Z) and tagged prerelease (vX.Y.Z-<id>.<n>) releases can be
driven from the npm scripts. Prerelease/stable bumps rename the CHANGELOG
section for the same release line instead of inserting duplicate sections.

Adds version:prerelease / version:stable npm scripts and unit tests.
…tags

The upload-updater-json and update-homebrew jobs only skipped tags containing
'alpha' or 'beta', so an rc tag (vX.Y.Z-rc.N) slipped through and would have
replaced the stable latest.json / cask with a prerelease. Skip any tag with a
dash (stable tags are always vX.Y.Z) so tagged prereleases never hijack the
stable updater channel.
The release-version skill now covers both release kinds end-to-end: stable
releases (vX.Y.Z, published with --latest, drives the in-app updater +
Homebrew) and tagged prerelease releases (vX.Y.Z-<id>.<n>, published with
--prerelease, never Latest). Also documents the prerelease bump types,
CHANGELOG section handling, and verification steps.
Copilot AI lite review requested due to automatic review settings August 11, 2026 10:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support in R-Shell’s release tooling for tagged prereleases (e.g. v2.8.0-beta.1, v2.8.0-rc.1) and finalizing to stable (e.g. v2.8.0), covering version math, CHANGELOG handling, npm scripts, workflow safety-guards, and documentation.

Changes:

  • Refactors scripts/bump-version.mjs to export pure semver utilities, add prerelease [identifier] + stable bump types, and adjust CHANGELOG section behavior for prerelease lines.
  • Adds/updates pnpm scripts and docs to expose the new bump commands and explain stable vs prerelease release flow.
  • Hardens release.yml gating so any dashed tag (vX.Y.Z-*) cannot update stable channels (latest.json, Homebrew).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
scripts/bump-version.mjs Implements prerelease/stable bumping, exports version math, and updates CHANGELOG logic.
src/__tests__/bump-version.test.ts Adds unit tests for version transitions and CHANGELOG section behavior.
package.json Adds version:prerelease and version:stable scripts.
.github/workflows/release.yml Ensures stable-channel updater/Homebrew jobs only run for non-dashed tags.
.github/skills/release-version/SKILL.md Documents stable vs tagged prerelease release procedure and verification.
scripts/README.md Documents new bump commands and prerelease behavior.
README.md Updates version bumping examples to include prerelease/stable flows.
AGENTS.md Updates contributor-facing version bumping guidance for prerelease/stable.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/bump-version.mjs Outdated
Comment on lines +141 to +146
function renameSection(changelog, fromVersion, toVersion, date) {
return changelog.replace(
new RegExp(`^## \\[${escapeRegex(fromVersion)}\\]`, 'm'),
`## [${toVersion}] - ${date}`
);
}
Comment thread scripts/README.md
Comment on lines +16 to +18
pnpm run version:prerelease # stable -> 2.8.0-beta.1, or 2.8.0-beta.1 -> 2.8.0-beta.2
pnpm run version:prerelease rc # continue/switch the prerelease line (alpha|beta|rc|...)
pnpm run version:stable # finalize a prerelease -> stable (2.8.0-beta.3 -> 2.8.0)
Comment thread README.md
Comment on lines +287 to +289
pnpm run version:prerelease # 2.2.0 → 2.3.0-beta.1, or 2.3.0-beta.1 → 2.3.0-beta.2 (tagged)
pnpm run version:prerelease rc # 2.3.0-beta.3 → 2.3.0-rc.1 (switch prerelease line)
pnpm run version:stable # 2.3.0-beta.3 → 2.3.0 (finalize to stable)
Comment thread AGENTS.md
Comment on lines +110 to +112
pnpm run version:prerelease # 0.7.1 → 0.8.0-beta.1, or 0.8.0-beta.1 → 0.8.0-beta.2 (tagged)
pnpm run version:prerelease rc # 0.8.0-beta.3 → 0.8.0-rc.1 (switch prerelease line)
pnpm run version:stable # 0.8.0-beta.3 → 0.8.0 (finalize to stable)
Comment on lines +56 to +60
pnpm run version:patch # 2.7.0 -> 2.7.1 (stable)
pnpm run version:minor # 2.7.0 -> 2.8.0 (stable)
pnpm run version:prerelease # 2.7.0 -> 2.8.0-beta.1 (tagged)
pnpm run version:prerelease rc # 2.8.0-beta.3 -> 2.8.0-rc.1 (tagged)
pnpm run version:stable # 2.8.0-beta.3 -> 2.8.0 (finalize)
Comment thread scripts/bump-version.mjs Outdated
Comment on lines +148 to +169
function insertSection(changelog, version, date) {
const newSection = `
## [${version}] - ${date}

### Added

- _Add new features here_

### Changed

- _Add changes here_

### Fixed

- _Add bug fixes here_
`;
// Insert after the Unreleased section
return changelog.replace(
/(## \[Unreleased\][^\n]*\n\n[^\n]*\n\n)/,
`$1${newSection}\n`
);
}
r-shell agent added 7 commits August 21, 2026 23:22
…verification

Extends PR #85's bump-version.mjs with release-tooling best practices
borrowed from semantic-release / changesets and the openusage Tauri app:

- Preflight guardrails: refuse to bump when the four version files
  (package.json, Cargo.toml, Cargo.lock, tauri.conf.json) disagree, or
  when the working tree has uncommitted tracked changes (--force bypass).
- --dry-run prints the plan and CHANGELOG action without writing anything;
  --yes skips the interactive prompt for CI/agents.
- Cargo.lock is updated by rewriting the root "r-shell" entry directly
  (like cargo set-version) instead of a full cargo build, with a cargo
  fallback and a post-edit verification.
- CHANGELOG insertion is now robust (handles missing No Unreleased
  sections, multi-line entries, top-of-file insert) and asserts the
  section exists after updating; renameSection no longer leaves a
  duplicated "- YYYY-MM-DD" date on renamed headings.
- New scripts/verify-release-tag.mjs validates a tag's semver shape and
  compares it against every version file (used by CI and version:verify).

Tests: 61 unit tests for the module (was 29), full suite 626 passed.
Release hardening informed by openusage's publish workflow and
tauri-apps/tauri-action semantics:

- New validate-tag job fails fast before any build when the tag is not a
  valid semver tag (vX.Y.Z or vX.Y.Z-<prerelease>) or does not match the
  version in every version file.
- tauri-action now creates tagged prereleases (vX.Y.Z-<id>.<n>) with
  prerelease: true; with the previous hardcoded false a prerelease tag
  could be auto-marked "Latest" and hijack releases/latest for stable
  users.
- concurrency group serializes overlapping release runs so two tags can
  never race on the latest.json manifest upload.
- SKILL.md: note the pre-flight checks and --dry-run/--yes flags on the
  bump step, add a version:verify sanity check before tagging, and mention
  the workflow's validate-tag gate and auto-prerelease behavior.
- scripts/README.md: document verify-release-tag.mjs, the new options
  (--dry-run/--yes/--force), and the direct Cargo.lock update.
- AGENTS.md / README.md: add version:verify and the guardrail summary.
docs/VERSION_BUMP.md no longer exists; the authoritative release
procedure now lives in .github/skills/release-version/SKILL.md.
Replaces the stale docs/VERSION_BUMP.md reference with the release-version
skill and adds the prerelease/stable/verify commands to the instructions.
The '✓'/'⚠️'/'—'/'…' glyphs made Vitest fail to load the module on
Windows (and ubuntu) CI with 'SyntaxError: Invalid or unexpected token'
- a pre-existing failure already present on this branch before the
enhancement. Replace them with ASCII equivalents in log output and
comments so the release tooling parses identically everywhere
(verified pure-ASCII across the whole version-bumping dependency graph).
…orm tests

Vitest fails to transform ESM imported from outside the project root
(scripts/) on Windows CI with 'SyntaxError: Invalid or unexpected token'.
The failure predates this enhancement (the original PR head had the same
red windows run) and is specific to out-of-root imports in the test
graph.

Move all pure version/CHANGELOG/tag logic into src/lib/version-bump.mjs
- inside the vitest transform root, with no Node built-ins and no
import.meta.url in the shared module - and turn both CLI scripts into
thin shells importing from it. Unit tests now import only from src/, so
the module transforms identically on macOS, ubuntu, and windows.

Also drop the leftover non-ASCII glyphs from the previous attempt; the
whole versioning dependency graph is now pure ASCII.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants