Skip to content

Commit 3742c9c

Browse files
authored
Add generate-changelog skill (#129)
1 parent b3d06e0 commit 3742c9c

1 file changed

Lines changed: 236 additions & 0 deletions

File tree

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

0 commit comments

Comments
 (0)