Skip to content

Commit ad0bdbb

Browse files
committed
add release skill
1 parent 64f6b9e commit ad0bdbb

3 files changed

Lines changed: 180 additions & 2 deletions

File tree

.claude/skills/release/SKILL.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
name: release
3+
description: |
4+
Prepare a new version release for the openroad-mcp project. Automates version
5+
bumping, changelog generation, lockfile updates, and release commit creation.
6+
7+
Use this skill whenever the user asks to:
8+
- Prepare a release, cut a release, or do a release
9+
- Bump the version or update the version
10+
- Create a release commit
11+
- Ship a new version
12+
- Update the changelog for a new release
13+
14+
Trigger on phrases like "release", "bump version", "prepare release", "cut v0.x",
15+
"ship it", "new release", or any mention of version numbers in the context of
16+
publishing. Also trigger when the user references the release process we've done
17+
before (e.g., "do the release thing", "same as last time").
18+
---
19+
20+
# Release Preparation
21+
22+
This skill automates the full release preparation workflow for the openroad-mcp
23+
project. It ensures every file that references the version gets updated consistently.
24+
25+
## Project context
26+
27+
- **Build system**: hatchling (Python)
28+
- **Package manager**: uv
29+
- **Version source**: `pyproject.toml` `[project] version`
30+
- **Changelog format**: Keep a Changelog
31+
- **Commit style**: Conventional Commits (`feat:`, `fix:`, `chore:`, etc.)
32+
- **GitHub repo**: `luarss/openroad-mcp`
33+
34+
## Workflow
35+
36+
### Step 1: Determine versions
37+
38+
Read the current version from `pyproject.toml`:
39+
40+
```
41+
grep '^version = ' pyproject.toml
42+
```
43+
44+
Then ask the user what the new version should be. Suggest the next logical
45+
semver bump based on the commits since the last release:
46+
47+
- **Patch** (0.3.0 → 0.3.1): only fixes and minor changes
48+
- **Minor** (0.3.0 → 0.4.0): new features added, backwards compatible
49+
- **Major** (0.3.0 → 1.0.0): breaking changes
50+
51+
Show the suggestion but let the user decide.
52+
53+
### Step 2: Collect commits since last release
54+
55+
Get the last release tag:
56+
57+
```bash
58+
git tag --sort=-v:refname | head -5
59+
```
60+
61+
Then list all commits since that tag:
62+
63+
```bash
64+
git log <last-tag>..HEAD --oneline
65+
```
66+
67+
If no tag exists, use the first commit or the last "chore: release" commit:
68+
69+
```bash
70+
git log --oneline --grep="chore: release" | head -1
71+
```
72+
73+
### Step 3: Categorize commits into changelog sections
74+
75+
Read each commit message and sort into Keep a Changelog categories:
76+
77+
| Category | Conventional commit prefix |
78+
|----------|---------------------------|
79+
| **Added** | `feat:` |
80+
| **Changed** | `chore:`, `build:`, `ci:`, `perf:`, `refactor:` |
81+
| **Fixed** | `fix:` |
82+
| **Removed** | commits mentioning removal/deprecation |
83+
84+
For each commit, format the changelog entry as:
85+
```
86+
- Description ([#PR](https://github.com/luarss/openroad-mcp/pull/PR))
87+
```
88+
89+
Use the PR number from the commit message if present. For commits without a PR
90+
number, just use the description part after the prefix.
91+
92+
### Step 4: Update all version references
93+
94+
These files must be updated with the new version. Update ALL of them — missing
95+
one breaks the release consistency.
96+
97+
**pyproject.toml** — Update `version = "X.Y.Z"` in the `[project]` section.
98+
99+
**server.json** — Update all three version references:
100+
- Top-level `"version": "X.Y.Z"`
101+
- PyPI package `"version": "X.Y.Z"`
102+
- OCI identifier `"identifier": "ghcr.io/luarss/openroad-mcp:X.Y.Z"`
103+
104+
**uv.lock** — Regenerate by running `uv lock`. Do NOT hand-edit this file.
105+
106+
**CHANGELOG.md** — Add new section before the previous version's section.
107+
Today's date goes in the header. Add the link at the bottom:
108+
109+
```
110+
[X.Y.Z]: https://github.com/luarss/openroad-mcp/releases/tag/vX.Y.Z
111+
```
112+
113+
**ROADMAP.md** — Find the "Version Milestones" table and add a new row for
114+
this release. Move any now-completed items from future milestones into this
115+
release's description.
116+
117+
### Step 5: Run tests
118+
119+
Run the test suite to verify nothing is broken:
120+
121+
```bash
122+
python -m pytest --tb=short -q
123+
```
124+
125+
If tests fail, report the failures to the user before proceeding. Do not commit
126+
a broken release.
127+
128+
### Step 6: Create the release commit
129+
130+
Stage only the release-related files:
131+
132+
```bash
133+
git add CHANGELOG.md ROADMAP.md pyproject.toml server.json uv.lock
134+
```
135+
136+
Commit with the message:
137+
138+
```
139+
chore: release vX.Y.Z
140+
```
141+
142+
Do NOT push unless the user explicitly asks. The commit stays local for review.
143+
144+
## Important details
145+
146+
- Always use `uv lock` to regenerate the lockfile rather than editing it manually
147+
- The CHANGELOG date format is ISO: `YYYY-MM-DD`
148+
- Version tags use a `v` prefix: `v0.4.0` (but the version in files has no prefix)
149+
- Check for ALL files referencing the old version by running:
150+
```
151+
grep -r "0\.3\.0" --include="*.toml" --include="*.json" --include="*.lock" --include="*.md"
152+
```
153+
before committing, to catch any missed references
154+
- If `server.json` doesn't exist, skip it (some repos may not have it)
155+
- If `ROADMAP.md` doesn't exist or has no version table, skip it
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"skill_name": "release",
3+
"evals": [
4+
{
5+
"id": 1,
6+
"prompt": "let's prepare for 0.5.0 release",
7+
"expected_output": "Should bump version from 0.4.0 to 0.5.0 in pyproject.toml, server.json (3 places), regenerate uv.lock, update CHANGELOG.md with new section and link, update ROADMAP.md milestones table, and create a chore: release commit",
8+
"files": []
9+
},
10+
{
11+
"id": 2,
12+
"prompt": "we need to ship a patch release, there's a hotfix that just landed",
13+
"expected_output": "Should identify current version (0.4.0), suggest patch bump to 0.4.1, collect commits since v0.4.0 tag, categorize them, update all version files, run tests, and create release commit",
14+
"files": []
15+
},
16+
{
17+
"id": 3,
18+
"prompt": "time for a new release, we added the session persistence feature and fixed a few bugs",
19+
"expected_output": "Should identify current version, suggest minor bump (0.5.0), collect commits since last release, categorize feat: commits as Added and fix: commits as Fixed, update all files including CHANGELOG with proper categorization, run tests, commit",
20+
"files": []
21+
}
22+
]
23+
}

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Byte-compiled / optimized / DLL files
1+
#Byte-compiled / optimized / DLL files
22
__pycache__/
33
*.py[codz]
44
*$py.class
@@ -203,7 +203,7 @@ __marimo__/
203203
.streamlit/secrets.toml
204204

205205
# Claude
206-
.claude
206+
.claude/settings.local.json
207207

208208
# Project specfics
209209
gcd_final

0 commit comments

Comments
 (0)