Skip to content

Commit f139f8f

Browse files
committed
Add generate-changelog skill
Part of: eclipse-glsp/glsp#1618
1 parent 0c0fe2f commit f139f8f

1 file changed

Lines changed: 282 additions & 0 deletions

File tree

  • .claude/skills/generate-changelog
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
name: generate-changelog
3+
description: Generate changelog entries from merged PRs since the last release. Fetches PR data, classifies changes as normal or breaking, presents for user review, and creates a PR with the updates.
4+
disable-model-invocation: true
5+
---
6+
7+
# GLSP Changelog Generator
8+
9+
Generate changelog entries by analyzing merged PRs since the last release.
10+
11+
Execute these phases in order:
12+
1. **Data Gathering** — find last release, fetch PRs, classify, generate entries
13+
2. **Changelog Update** — create worktree, write entries into CHANGELOG.md
14+
3. **Review & Approval** — present the actual diff to the user for review
15+
4. **PR Creation** — push and create PR (only after user approves)
16+
17+
---
18+
19+
## Phase 1: Data Gathering
20+
21+
### Step 1.1: Determine repository info
22+
23+
Use the current working directory as the repository. Derive:
24+
- `REPO_DIR`: the repository root (find via `git rev-parse --show-toplevel`)
25+
- `REPO_NAME`: the directory name (e.g. `glsp-client`)
26+
- `GH_REPO`: the GitHub identifier `eclipse-glsp/REPO_NAME`
27+
28+
### Step 1.2: Find the latest release tag
29+
30+
Run:
31+
```bash
32+
git tag --sort=-creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1
33+
```
34+
35+
Record as `LAST_TAG`. Get the tag's date:
36+
```bash
37+
git log -1 --format=%aI $LAST_TAG
38+
```
39+
40+
Record as `TAG_DATE`.
41+
42+
### Step 1.3: Extract category tags from existing CHANGELOG.md
43+
44+
Read `CHANGELOG.md` and extract all unique `[tag]` patterns from changelog entries (pattern: `- [tag] ...`). Build a deduplicated vocabulary list preserving original casing.
45+
46+
### Step 1.4: Fetch merged PRs since the last release
47+
48+
```bash
49+
gh pr list --repo GH_REPO --state merged --search "merged:>TAG_DATE" --json number,title,author,body,labels,mergedAt --limit 100
50+
```
51+
52+
Use the date portion only from `TAG_DATE` (e.g. `2026-02-09`).
53+
54+
### Step 1.5: Filter PRs
55+
56+
**Skip rules** (in order):
57+
1. Author login is `dependabot` or `dependabot[bot]` → skip
58+
2. Title matches version bump patterns → skip:
59+
- Starts with `Switch to` and contains `-next`
60+
- Title is a bare version like `vX.Y.Z`
61+
- Title starts with `Release v`
62+
3. Title contains `update changelog` (case insensitive) → skip
63+
4. Title is purely CI/metadata (readme badges, workflow config) AND body does NOT contain `[x] This PR should be mentioned in the changelog` → skip
64+
65+
**Override**: If the PR body contains `[x] This PR should be mentioned in the changelog`, always include it regardless of rules 2-4. Dependabot PRs are always skipped.
66+
67+
### Step 1.6: Classify each PR
68+
69+
1. If body contains `[x] This PR introduces a breaking change`**breaking**
70+
2. If body contains `[ ] This PR introduces a breaking change`**normal**
71+
3. If no checkbox info, analyze title and body:
72+
- Breaking keywords: "refactor", "rename", "remove", "replace", "migrate", "breaking", "deprecate"
73+
- Clearly non-breaking (bug fix, docs, minor enhancement) → **normal**
74+
- Uncertain → flag for user review
75+
76+
### Step 1.7: Assign category tags
77+
78+
Pick the most fitting tag from the vocabulary (Step 1.3) based on PR title and body. If no tag fits, mark as uncertain: `[???/best-guess]`.
79+
80+
### Step 1.8: Generate changelog entries
81+
82+
#### Entry Format
83+
84+
**Normal changes:**
85+
```
86+
- [tag] Description [#N](https://github.com/eclipse-glsp/REPO_NAME/pull/N)
87+
```
88+
89+
**Breaking changes** with migration sub-items:
90+
```
91+
- [tag] Description [#N](https://github.com/eclipse-glsp/REPO_NAME/pull/N)
92+
- Migration detail 1
93+
- Migration detail 2
94+
```
95+
96+
**Multiple PRs for the same change:**
97+
```
98+
- [tag] Description [#N](url) [#M](url)
99+
```
100+
101+
#### Style Guide
102+
103+
**Formatting:**
104+
- Entry prefix: `- ` (dash + exactly 3 spaces)
105+
- Sub-item indent: 4 spaces + `- ` (4 spaces from parent dash)
106+
- Sub-sub-item indent: 8 spaces + `- `
107+
- Single space between `[tag]` and description text
108+
- Single space before PR link at end of line
109+
- PR links are mandatory, full URLs: `[#123](https://github.com/eclipse-glsp/REPO_NAME/pull/123)`
110+
111+
**Wording:**
112+
- Always start with a **present tense imperative verb** (not past tense)
113+
- Common verbs: Fix, Improve, Add, Update, Extend, Ensure, Introduce, Remove, Refactor, Rename, Provide, Allow, Support
114+
- **Bug fixes**: "Fix a bug that caused/prevented...", "Fix X behavior"
115+
- **Features**: "Introduce...", "Add support for...", "Provide..."
116+
- **Enhancements**: "Improve...", "Extend...", "Ensure that..."
117+
- **Refactors**: "Refactor...", "Rework...", "Rename..."
118+
- Be specific — never "Fix various issues"
119+
120+
**Capitalization:**
121+
- Tags are always lowercase: `[diagram]`, not `[Diagram]`
122+
- Description starts lowercase after the tag (unless proper noun or code element)
123+
- Section headers: Title Case (`### Potentially Breaking Changes`)
124+
125+
**Description cleanup from PR title:**
126+
- Remove prefixes: `GLSP-1234:`, `GH-123:`, `fix:`, `feat:`, `chore:`
127+
- Rephrase bug-report style to changelog style:
128+
- BAD: "Edit label UI does not resize on graph zoom"
129+
- GOOD: "Fix edit label UI not resizing on graph zoom"
130+
- Keep concise — one line
131+
132+
**Breaking changes:**
133+
- Describe what changed, why it's breaking, and how to migrate
134+
- Extract migration sub-items from the PR body's "What it does" section
135+
136+
---
137+
138+
## Phase 2: Changelog Update
139+
140+
### Step 2.1: Create a git worktree
141+
142+
Determine the main branch:
143+
```bash
144+
git symbolic-ref refs/remotes/origin/HEAD | sed 's|refs/remotes/origin/||'
145+
```
146+
147+
Fetch latest and create worktree:
148+
```bash
149+
git fetch origin
150+
git worktree add REPO_DIR-changelog-update origin/MAIN_BRANCH
151+
```
152+
153+
All subsequent file operations happen in the worktree.
154+
155+
### Step 2.2: Determine the version section
156+
157+
Read `CHANGELOG.md` in the worktree.
158+
159+
**Active section detection:**
160+
- An active section has the `- active` suffix (e.g. `## v2.7.0 - active`)
161+
- If an active section exists → merge new entries into it
162+
- If the topmost section is a released version (no `- active` suffix) → create a new active section above it
163+
164+
**Creating a new section:**
165+
- Bump the minor version of `LAST_TAG` (e.g. `v2.6.0``v2.7.0`)
166+
- Insert after the title line, before the first `## ` heading:
167+
168+
```markdown
169+
## v2.7.0 - active
170+
171+
### Changes
172+
173+
- [tag] Entry [#N](url)
174+
175+
### Potentially Breaking Changes
176+
177+
- [tag] Entry [#N](url)
178+
- Sub-item detail
179+
```
180+
181+
Only include "Potentially Breaking Changes" if there are breaking entries.
182+
183+
**Merging into existing active section:**
184+
- Check PR numbers against existing entries to avoid duplicates
185+
- Append new entries to the appropriate subsection
186+
- Create missing subsections as needed
187+
188+
### Step 2.3: Write the updated CHANGELOG.md
189+
190+
Use the Edit tool. Match existing formatting conventions.
191+
192+
---
193+
194+
## Phase 3: Review & Approval
195+
196+
### Step 3.1: Show the diff
197+
198+
```bash
199+
git -C WORKTREE_DIR diff CHANGELOG.md
200+
```
201+
202+
Present the diff to the user.
203+
204+
### Step 3.2: Prompt for uncertain items
205+
206+
List any entries flagged as uncertain (category or breaking status) and ask the user to resolve them.
207+
208+
Even if nothing is uncertain, ask:
209+
> "Does everything look correct, or would you like to adjust any entries?"
210+
211+
### Step 3.3: Collect user feedback
212+
213+
- **Approve as-is** → proceed to Phase 4
214+
- **Request edits** → apply changes, show updated diff, ask again
215+
- **Resolve uncertain items** → apply, show updated diff
216+
217+
**Do NOT proceed to Phase 4 until the user explicitly approves.**
218+
219+
---
220+
221+
## Phase 4: PR Creation
222+
223+
### Step 4.1: Determine the branch name
224+
225+
Check if `changelog-update` exists on remote:
226+
```bash
227+
git -C WORKTREE_DIR ls-remote --heads origin changelog-update
228+
```
229+
230+
If it exists, increment: `changelog-update-2`, `changelog-update-3`, etc.
231+
232+
### Step 4.2: Create branch, commit, and push
233+
234+
```bash
235+
cd WORKTREE_DIR
236+
git checkout -b BRANCH_NAME
237+
git add CHANGELOG.md
238+
git commit -m "Update changelog"
239+
git push -u origin BRANCH_NAME
240+
```
241+
242+
### Step 4.3: Create the PR
243+
244+
Use the repo's `.github/PULL_REQUEST_TEMPLATE.md` structure:
245+
246+
```bash
247+
gh pr create --repo GH_REPO --title "Update changelog" --body "$(cat <<'EOF'
248+
#### What it does
249+
Updates the changelog with entries for PRs merged since the last release (LAST_TAG).
250+
251+
#### How to test
252+
Review the changelog entries for accuracy.
253+
254+
#### Follow-ups
255+
None.
256+
257+
#### Changelog
258+
259+
- [ ] This PR should be mentioned in the changelog
260+
- [ ] This PR introduces a breaking change
261+
EOF
262+
)"
263+
```
264+
265+
Report the PR URL.
266+
267+
### Step 4.4: Label referenced PRs
268+
269+
Add the `changelog` label to every PR mentioned in the new entries:
270+
```bash
271+
gh pr edit PR_NUMBER --repo GH_REPO --add-label "changelog"
272+
```
273+
274+
Report which PRs were labeled.
275+
276+
### Step 4.5: Clean up the worktree
277+
278+
```bash
279+
git -C REPO_DIR worktree remove REPO_DIR-changelog-update
280+
```
281+
282+
Report completion with PR URL and labeled PRs.

0 commit comments

Comments
 (0)