|
| 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