Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 62 additions & 17 deletions .github/skills/release-version/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
---
name: release-version
description: "Release a new r-shell version and create a published GitHub release with contributor credits. Use when: releasing, publishing, bumping version, tagging, creating release notes, gh release create, version bump, patch release, minor release, major release."
argument-hint: "bump type: patch | minor | major"
description: "Release a new r-shell version and create a published GitHub release with contributor credits. Supports both stable releases (vX.Y.Z) and tagged prerelease versions (vX.Y.Z-beta.N / -rc.N). Use when: releasing, publishing, bumping version, tagging, creating release notes, gh release create, version bump, patch release, minor release, major release, prerelease, beta, rc, tagged release, stable release."
argument-hint: "bump type: patch | minor | major | prerelease [identifier] | stable"
---

# Release New Version & Create GitHub Release

Bumps the project version across all config files, updates the CHANGELOG, pushes a tag, and creates a **published** GitHub release using `gh`, with release notes that credit the contributors.
Bumps the project version across all config files, updates the CHANGELOG, pushes a tag, and creates a **published** GitHub release using `gh`, with release notes that credit the contributors. Two release kinds are supported:

- **Stable release** — `vX.Y.Z` (e.g. `v2.8.0`), published as the repo's **Latest** release. The Release workflow uploads `latest.json` (the in-app updater manifest) and updates the Homebrew cask, so every stable user sees it.
- **Tagged (prerelease) release** — `vX.Y.Z-<id>.<n>` (e.g. `v2.8.0-beta.1`, `v2.8.0-rc.1`), published as a GitHub **prerelease** (never Latest). The Release workflow skips `latest.json` and Homebrew for prerelease tags, so stable users are never offered a prerelease and Homebrew is untouched.

Both trigger the same `release.yml` build on a pushed `v*` tag; only the release **kind** differs.

## When to Use
- Releasing a new patch, minor, or major version of r-shell
- Releasing a new patch, minor, or major version of r-shell (stable)
- Releasing a tagged prerelease of r-shell (`-alpha`, `-beta`, `-rc`) before it goes stable
- Creating a GitHub release (published) with changelog notes and contributor credits
- Tagging a new version and pushing to origin

Expand All @@ -26,27 +32,40 @@ Bumps the project version across all config files, updates the CHANGELOG, pushes

### 1. Determine Bump Type

Ask (or infer from the argument) whether this is a `patch`, `minor`, or `major` bump:
Ask (or infer from the argument) which kind of release this is:

| Bump type | Release kind | When | Example |
|-----------|--------------|------|---------|
| `patch` | Stable | Bug fixes, small tweaks | `1.2.3 → 1.2.4` |
| `minor` | Stable | New features, backward-compatible | `1.2.3 → 1.3.0` |
| `major` | Stable | Breaking changes | `1.2.3 → 2.0.0` |
| `prerelease` | Tagged | A pre-release of the next version | `2.7.0 → 2.8.0-beta.1` |
| `stable` | Tagged → Stable | Finalize a prerelease to stable | `2.8.0-beta.3 → 2.8.0` |

| Type | When | Example |
|------|------|---------|
| `patch` | Bug fixes, small tweaks | `1.2.3 → 1.2.4` |
| `minor` | New features, backward-compatible | `1.2.3 → 1.3.0` |
| `major` | Breaking changes | `1.2.3 → 2.0.0` |
For prereleases, an optional identifier selects the prerelease line (`alpha`, `beta`, `rc`, ...) and defaults to `beta`:
- `2.8.0-beta.1 → 2.8.0-beta.2` continues the same beta line
- `2.8.0-beta.3 → 2.8.0-rc.1` switches from beta to the rc line
- `2.8.0-beta.3 → 2.8.0` (via `stable`) promotes the prerelease to the stable release

### 2. Run the Version Bump Script

```bash
# Replace <type> with patch, minor, or major
# Replace <type> with patch, minor, major, prerelease [identifier], or stable
pnpm run version:<type>
# e.g.:
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 on lines +56 to +60
```

This updates **all four** version locations atomically and creates a git commit:
- `package.json`
- `src-tauri/Cargo.toml`
- `src-tauri/Cargo.lock`
- `src-tauri/tauri.conf.json`
- `CHANGELOG.md` (adds a skeleton section)
- `CHANGELOG.md` (adds a skeleton section — for prerelease/stable bumps it renames the existing release-line section instead of adding duplicates)

Read the new version from `package.json`:
```bash
Expand Down Expand Up @@ -93,11 +112,14 @@ If a commit's PR number can't be resolved, omit `in #PR`; if the author has no G

Add a release headline as the first paragraph after the version header (see existing entries for the pattern: `### 🔖 R-Shell X.Y — Codename`).

```markdown
The `**Full Changelog**` line must use the actual previous tag → new tag (for a prerelease, `PREV_TAG` is the previous tag and `NEW_TAG` is `v${VERSION}`, e.g. `v2.8.0-beta.1`):

**Full Changelog**: https://github.com/GOODBOY008/r-shell/compare/v2.7.0...v2.8.0
```markdown
**Full Changelog**: https://github.com/GOODBOY008/r-shell/compare/<PREV_TAG>...<NEW_TAG>
```

> For a prerelease, the CHANGELOG section header is the exact prerelease version (`## [2.8.0-beta.1]`); it is renamed to `## [2.8.0]` when the prerelease is finalized. Keep the notes under whichever header matches the version you are releasing.

After editing, amend the commit to include the updated CHANGELOG:
```bash
git add CHANGELOG.md
Expand Down Expand Up @@ -133,7 +155,10 @@ If the file is empty, do NOT continue — fix the CHANGELOG header format first.

### 6. Create the GitHub Release (Published)

The release is created in a **published** state — visible immediately to users and triggering any release notifications/webhooks. Use `--notes-file` (not `--notes`) to pass multiline content reliably:
The release is created in a **published** state — visible immediately to users and triggering any release notifications/webhooks. Use `--notes-file` (not `--notes`) to pass multiline content reliably.

**Stable release** (`v2.8.0`) — mark it `--latest` so it drives the in-app updater and becomes the repo's "Latest":

```bash
VERSION=$(node -p "require('./package.json').version")

Expand All @@ -146,7 +171,21 @@ gh release create "v${VERSION}" \
rm -f "${NOTES_FILE}"
```

The `--latest` flag marks this release as the repo's current "Latest" release. Do **not** use `--draft` — the release should publish immediately.
**Tagged (prerelease) release** (`v2.8.0-beta.1`, `v2.8.0-rc.1`) — use `--prerelease` **instead of** `--latest`. Do **not** mark a prerelease as latest: the Release workflow's `upload-updater-json` and `update-homebrew` jobs skip prerelease tags, so leaving `--latest` off keeps the stable updater channel and Homebrew pointing at the last stable version.

```bash
VERSION=$(node -p "require('./package.json').version")

gh release create "v${VERSION}" \
--title "v${VERSION}" \
--notes-file "${NOTES_FILE}" \
--prerelease \
--repo GOODBOY008/r-shell

rm -f "${NOTES_FILE}"
```

Neither path uses `--draft` — the release should publish immediately.

> The release notes already include the `### Contributors` section added in step 3.

Expand All @@ -159,12 +198,18 @@ gh release view "v${VERSION}" --repo GOODBOY008/r-shell

Check the output includes the release body text (not just "See the assets…"). If the body is empty, the notes file was empty or the `awk` pattern didn't match — re-run step 5 to debug, then use `gh release edit "v${VERSION}" --notes-file <file> --repo GOODBOY008/r-shell` to fix it.

**For a stable release**, also confirm it is marked "Latest" (`gh release view` shows the tag without a `prerelease:` line), so `releases/latest/download/latest.json` serves this version to the in-app updater.

**For a tagged (prerelease) release**, confirm:
- `gh release view` shows it as **Pre-release** (`prerelease: true` in the API: `gh api repos/GOODBOY008/r-shell/releases/tags/v${VERSION} --jq .prerelease`).
- `latest.json` was **not** attached to this release (check the assets list), and the stable `releases/latest` endpoint still points at the last stable release — stable users must not be offered a prerelease.

## Decision Points

- **Changelog already accurate?** Skip step 3's changelog edits (but still add the `### Contributors` section) and the amend.
- **Want to keep the release hidden until you publish it manually?** Add `--draft` to the `gh release create` command in step 6.
- **Attaching build artifacts?** Add file paths after the tag in `gh release create`: `gh release create "v${VERSION}" ./dist/*.dmg ./dist/*.exe --latest ...`
- **Pre-release?** Append `--prerelease` to the `gh release create` command (this replaces `--latest`).
- **Stable vs tagged (prerelease)?** A stable release uses `--latest` and updates the in-app updater + Homebrew. A tagged prerelease (`-alpha`/`-beta`/`-rc`) uses `--prerelease` instead of `--latest`; the Release workflow skips `latest.json` and Homebrew for prerelease tags, so stable users and Homebrew are never switched to a prerelease. Finalize a prerelease with `pnpm run version:stable` before tagging it as `vX.Y.Z`.

## Prerequisites

Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,13 @@ jobs:
args: ${{ matrix.args }}

# Generate and upload latest.json for the in-app updater.
# Skips pre-release tags so a beta/alpha never becomes the `latest` release
# and hijack the updater manifest for stable users.
# Skips prerelease tags (vX.Y.Z-<id>.<n>) so a beta/rc never becomes the
# `latest` release and hijack the updater manifest for stable users. Stable
# tags are always vX.Y.Z (no dash), so `!contains('-')` is the robust test.
upload-updater-json:
needs: release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, 'alpha') && !contains(github.ref_name, 'beta')
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')
permissions:
contents: write
steps:
Expand Down Expand Up @@ -247,11 +248,13 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Update Homebrew tap (requires HOMEBREW_TAP_TOKEN secret)
# Update Homebrew tap (requires HOMEBREW_TAP_TOKEN secret).
# Skips prerelease tags just like upload-updater-json — a beta/rc must not
# replace the stable cask.
update-homebrew:
needs: generate-checksums
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, 'alpha') && !contains(github.ref_name, 'beta')
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref_name, '-')
steps:
- name: Update Homebrew Cask
uses: peter-evans/repository-dispatch@v4
Expand Down
11 changes: 8 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,16 @@ pnpm lint:fix
### Version Bumping

```bash
pnpm run version:patch # 0.7.1 → 0.7.2
pnpm run version:minor # 0.7.1 → 0.8.0
pnpm run version:major # 0.7.1 → 1.0.0
pnpm run version:patch # 0.7.1 → 0.7.2 (stable)
pnpm run version:minor # 0.7.1 → 0.8.0 (stable)
pnpm run version:major # 0.7.1 → 1.0.0 (stable)
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 +110 to +112
```

Stable releases tag as `vX.Y.Z` and publish as the GitHub **Latest** release; tagged prereleases tag as `vX.Y.Z-<id>.<n>` (e.g. `v0.8.0-beta.1`) and publish with `--prerelease`, never as Latest. See `.github/skills/release-version/SKILL.md` for the full release procedure.

Updates `package.json`, `Cargo.toml`, `Cargo.lock`, `tauri.conf.json`, `CHANGELOG.md` and creates a git commit.

---
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,12 @@ pnpm test:e2e # E2E
### Version Bumping

```bash
pnpm run version:patch # 2.2.0 → 2.2.1
pnpm run version:minor # 2.2.0 → 2.3.0
pnpm run version:major # 2.2.0 → 3.0.0
pnpm run version:patch # 2.2.0 → 2.2.1 (stable)
pnpm run version:minor # 2.2.0 → 2.3.0 (stable)
pnpm run version:major # 2.2.0 → 3.0.0 (stable)
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 on lines +287 to +289
```

---
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"tauri": "tauri",
"version:patch": "node scripts/bump-version.mjs patch",
"version:minor": "node scripts/bump-version.mjs minor",
"version:major": "node scripts/bump-version.mjs major"
"version:major": "node scripts/bump-version.mjs major",
"version:prerelease": "node scripts/bump-version.mjs prerelease",
"version:stable": "node scripts/bump-version.mjs stable"
},
"dependencies": {
"@codemirror/autocomplete": "^6.20.3",
Expand Down
16 changes: 16 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ This directory contains utility scripts for R-Shell development and maintenance.
pnpm run version:patch
pnpm run version:minor
pnpm run version:major
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 on lines +16 to +18

# Direct usage
node scripts/bump-version.mjs patch
node scripts/bump-version.mjs minor --no-commit
node scripts/bump-version.mjs major --skip-changelog
node scripts/bump-version.mjs prerelease beta
node scripts/bump-version.mjs stable
```

**Features:**
Expand All @@ -26,6 +31,15 @@ node scripts/bump-version.mjs major --skip-changelog
- ✅ Interactive confirmation
- ✅ Automatic git commit
- ✅ CHANGELOG.md template generation
- ✅ Stable (`major`/`minor`/`patch`) and tagged prerelease (`prerelease`/`stable`) bumps

### Bump Types

- `major` / `minor` / `patch` — stable release bump (`2.7.0 -> 2.8.0`); a fresh CHANGELOG section is inserted.
- `prerelease [identifier]` — tagged prerelease bump. From a stable version it opens the next minor line (`2.7.0 -> 2.8.0-beta.1`); from a prerelease it continues the same identifier (`2.8.0-beta.1 -> 2.8.0-beta.2`) or switches to another one at `.1` (`2.8.0-beta.3 -> 2.8.0-rc.1`). Identifier defaults to `beta`.
- `stable` — finalize a prerelease to its base version (`2.8.0-beta.3 -> 2.8.0`). Errors if the current version is already stable.

For `prerelease` / `stable`, the CHANGELOG section for the release line is **renamed** (e.g. `## [2.8.0-beta.2]` → `## [2.8.0-beta.3]`, or → `## [2.8.0]` on finalize) instead of inserting a new one each time, so draft notes carry over without accumulating duplicate sections.

### bump-version.sh

Expand All @@ -43,6 +57,8 @@ node scripts/bump-version.mjs major --skip-changelog
- ✅ Colored output
- ✅ Same functionality as Node.js version

> ⚠️ The bash script supports only **stable** bumps (`major`/`minor`/`patch`). Use `bump-version.mjs` for prerelease (`prerelease [identifier]`) and finalize (`stable`) bumps.

## Options

Both scripts support the same options:
Expand Down
Loading
Loading