Skip to content

Commit 94cbea9

Browse files
committed
Skill set for release generation
1 parent d9709b2 commit 94cbea9

File tree

7 files changed

+809
-0
lines changed

7 files changed

+809
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
name: changelog-generator
3+
description: Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
4+
---
5+
6+
# Changelog Generator
7+
8+
This skill transforms technical git commits into polished, user-friendly changelogs that your customers and users will actually understand and appreciate.
9+
10+
## When to Use This Skill
11+
12+
- Preparing release notes for a new version
13+
- Generating changelog between two tags/commits
14+
- Creating draft release notes from recent commits
15+
16+
## Quick Start
17+
18+
```
19+
Create a changelog from commits since v0.96.1
20+
```
21+
22+
```
23+
Create release notes for version 0.97.0 starting from tag v0.96.1
24+
```
25+
26+
---
27+
28+
## Workflow Overview
29+
30+
```
31+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
32+
│ 1. Fetch │───▶│ 2. Filter │───▶│ 3. Categorize│───▶│ 4. Generate │
33+
│ Commits │ │ & Dedupe │ │ by Module │ │ Descriptions │
34+
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
35+
│ │ │ │
36+
▼ ▼ ▼ ▼
37+
📄 github-api 📄 commit- 📄 module- 📄 user-facing-
38+
reference.md filtering.md mapping.md description.md
39+
```
40+
41+
## Sub-Skills Reference
42+
43+
This skill is composed of the following sub-skills.
44+
45+
**⚠️ IMPORTANT: Do NOT read all sub-skills at once!**
46+
- Only read a sub-skill when you reach that step in the workflow
47+
- This saves context window and improves accuracy
48+
- Use `read_file` to load a sub-skill only when needed
49+
50+
| Step | Sub-Skill | When to Read |
51+
|------|-----------|--------------|
52+
| Fetch data | [github-api-reference.md](sub-skills/github-api-reference.md) | When fetching commits/PRs |
53+
| Filter commits | [commit-filtering.md](sub-skills/commit-filtering.md) | When checking if commit should be skipped |
54+
| Categorize | [module-mapping.md](sub-skills/module-mapping.md) | When determining which module a PR belongs to |
55+
| Generate text | [user-facing-description.md](sub-skills/user-facing-description.md) | When writing the changelog entry text |
56+
| Attribution | [contributor-attribution.md](sub-skills/contributor-attribution.md) | When checking if author needs thanks |
57+
| Large releases | [progress-tracking.md](sub-skills/progress-tracking.md) | Only if processing 50+ commits |
58+
59+
---
60+
61+
## Step-by-Step Summary
62+
63+
### Step 1: Get Commit Range
64+
```powershell
65+
# Count commits between tags
66+
gh api repos/microsoft/PowerToys/compare/v0.96.0...v0.96.1 --jq '.commits | length'
67+
```
68+
👉 Details: [github-api-reference.md](sub-skills/github-api-reference.md)
69+
70+
### Step 2: Filter Commits
71+
- Skip commits already in start tag
72+
- Skip cherry-picks and backports
73+
- Deduplicate by PR number
74+
75+
👉 Details: [commit-filtering.md](sub-skills/commit-filtering.md)
76+
77+
### Step 3: For Each PR, Generate Entry
78+
1. Get PR title, body, files, labels
79+
2. Determine module from file paths or labels
80+
3. Check if user-facing (skip internal changes)
81+
4. Transform to user-friendly description
82+
5. Add contributor attribution if needed
83+
84+
👉 Details: [user-facing-description.md](sub-skills/user-facing-description.md), [module-mapping.md](sub-skills/module-mapping.md), [contributor-attribution.md](sub-skills/contributor-attribution.md)
85+
86+
### Step 4: Checkpoint (if 50+ commits)
87+
- Save progress after every 15-20 commits
88+
- Track processed PRs for deduplication
89+
- Enable resume from interruption
90+
91+
👉 Details: [progress-tracking.md](sub-skills/progress-tracking.md)
92+
93+
### Step 5: Format Output
94+
```markdown
95+
## ✨ What's new
96+
**Version X.XX (Month Year)**
97+
98+
**✨ Highlights**
99+
- [Most impactful change 1]
100+
- [Most impactful change 2]
101+
102+
### [Module Name - Alphabetical]
103+
- [Description]. Thanks [@contributor](https://github.com/contributor)!
104+
105+
### Development
106+
- [Internal changes]
107+
```
108+
109+
---
110+
111+
## Example Output
112+
113+
```markdown
114+
## ✨ What's new
115+
**Version 0.96.1 (December 2025)**
116+
117+
**✨ Highlights**
118+
- Advanced Paste now supports multiple AI providers.
119+
- PowerRename can extract photo metadata for renaming.
120+
121+
### Advanced Paste
122+
- Added support for Azure OpenAI, Google Gemini, Mistral, and more.
123+
124+
### Awake
125+
- The countdown timer now stays accurate over long periods. Thanks [@daverayment](https://github.com/daverayment)!
126+
127+
### Development
128+
- Resolved build warnings in Command Palette projects.
129+
```
130+
131+
---
132+
133+
## Tips
134+
135+
1. **Propose highlights** after all entries are generated
136+
2. **Check PR body** when title is unclear
137+
3. **Thank external contributors** - see [contributor-attribution.md](sub-skills/contributor-attribution.md)
138+
4. **Use progress tracking** for large releases - see [progress-tracking.md](sub-skills/progress-tracking.md)
139+
5. **Save output** to `release-change-note-draft.md`
140+
141+
---
142+
143+
## Troubleshooting
144+
145+
| Problem | Solution |
146+
|---------|----------|
147+
| Lost progress mid-generation | Read `release-notes-progress.md` to resume |
148+
| Duplicate entries | Check processed PR list, dedupe by PR number |
149+
| Commit already released | Use `git merge-base --is-ancestor` to verify |
150+
| API rate limited | Check `gh api rate_limit`, wait or use token |
151+
152+
👉 See sub-skills for detailed troubleshooting.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Commit Filtering Rules
2+
3+
This sub-skill defines rules for filtering commits to include in the changelog.
4+
5+
## Filter Out Commits Already in Start Tag
6+
7+
**CRITICAL: Skip commits that are already included in the start tag to avoid duplicates.**
8+
9+
This happens when:
10+
- Cherry-picks from main to stable branch
11+
- Backported fixes that were already released
12+
- Commits included in a previous release
13+
14+
### Method 1: Git Merge-Base (Local, Most Reliable)
15+
16+
```powershell
17+
$startTag = "v0.96.0"
18+
$commitSha = "abc1234"
19+
20+
# Check if commit is ancestor of (already included in) start tag
21+
# Returns exit code 0 if true, 1 if false
22+
git merge-base --is-ancestor $commitSha $startTag
23+
if ($LASTEXITCODE -eq 0) {
24+
Write-Host "SKIP: Commit $commitSha already in $startTag"
25+
} else {
26+
Write-Host "PROCESS: Commit $commitSha is new"
27+
}
28+
```
29+
30+
### Method 2: GitHub API Compare (Auto-Filtered)
31+
32+
```powershell
33+
# The compare API already handles this - it returns only commits
34+
# that are in the "head" but NOT in the "base"
35+
$compare = gh api repos/microsoft/PowerToys/compare/v0.96.0...v0.96.1 | ConvertFrom-Json
36+
37+
# These commits are guaranteed to be NEW (not in v0.96.0)
38+
$newCommits = $compare.commits
39+
Write-Host "Found $($newCommits.Count) new commits not in start tag"
40+
```
41+
42+
### Method 3: Check Tags Containing Commit
43+
44+
```powershell
45+
$commitSha = "abc1234"
46+
$tagsContaining = git tag --contains $commitSha
47+
if ($tagsContaining -match "v0\.96\.0") {
48+
Write-Host "SKIP: Commit already released in v0.96.0"
49+
}
50+
```
51+
52+
## Batch Filter Script
53+
54+
```powershell
55+
$startTag = "v0.96.0"
56+
$endTag = "v0.96.1"
57+
58+
# Get commits from compare (already filtered - only new commits)
59+
$newCommits = gh api repos/microsoft/PowerToys/compare/$startTag...$endTag --jq '.commits[] | {sha: .sha, message: .commit.message}' | ConvertFrom-Json
60+
61+
# Additional validation: filter out any merge commits that reference old PRs
62+
$filteredCommits = $newCommits | Where-Object {
63+
$sha = $_.sha
64+
# Double-check: ensure commit is not ancestor of start tag
65+
git merge-base --is-ancestor $sha $startTag 2>$null
66+
$LASTEXITCODE -ne 0 # Keep only if NOT an ancestor
67+
}
68+
69+
Write-Host "After filtering: $($filteredCommits.Count) commits to process"
70+
```
71+
72+
## Skip Rules Summary
73+
74+
| Condition | Action |
75+
|-----------|--------|
76+
| `git merge-base --is-ancestor $sha $startTag` returns 0 | SKIP - already in start tag |
77+
| Commit message contains "cherry-pick" + old PR number | SKIP - likely backport |
78+
| PR was merged before start tag date | SKIP - old PR |
79+
| Same PR number already processed | SKIP - duplicate |
80+
81+
## User-Facing vs Non-User-Facing
82+
83+
**Include in changelog:**
84+
- New features and capabilities
85+
- Bug fixes that affect users
86+
- UI/UX improvements
87+
- Performance improvements users would notice
88+
- Breaking changes or behavior modifications
89+
- Security fixes
90+
91+
**Exclude from changelog (put in Development section):**
92+
- Internal refactoring
93+
- CI/CD changes
94+
- Code style fixes
95+
- Test additions/modifications
96+
- Documentation-only changes
97+
- Dependency updates (unless user-visible impact)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Contributor Attribution Rules
2+
3+
This sub-skill defines when and how to credit contributors in changelog entries.
4+
5+
## Attribution Rules
6+
7+
- Check [COMMUNITY.md](../../../COMMUNITY.md) for the "PowerToys core team" section
8+
- If author is **NOT** in core team → Add `Thanks [@username](https://github.com/username)!`
9+
- If author **IS** in core team → No attribution needed
10+
- Microsoft employees working on PowerToys as their job → No attribution needed
11+
12+
## Core Team Members
13+
14+
Current core team members (from COMMUNITY.md) - do NOT thank these:
15+
16+
```
17+
@craigloewen-msft, @niels9001, @dhowett, @yeelam-gordon, @jamrobot,
18+
@lei9444, @shuaiyuanxx, @moooyo, @haoliuu, @chenmy77, @chemwolf6922,
19+
@yaqingmi, @zhaoqpcn, @urnotdfs, @zhaopy536, @wang563681252, @vanzue,
20+
@zadjii-msft, @khmyznikov, @chatasweetie, @MichaelJolley, @Jaylyn-Barbee,
21+
@zateutsch, @crutkas
22+
```
23+
24+
## Check Author Script
25+
26+
```powershell
27+
$coreTeam = @(
28+
'craigloewen-msft', 'niels9001', 'dhowett', 'yeelam-gordon', 'jamrobot',
29+
'lei9444', 'shuaiyuanxx', 'moooyo', 'haoliuu', 'chenmy77', 'chemwolf6922',
30+
'yaqingmi', 'zhaoqpcn', 'urnotdfs', 'zhaopy536', 'wang563681252', 'vanzue',
31+
'zadjii-msft', 'khmyznikov', 'chatasweetie', 'MichaelJolley', 'Jaylyn-Barbee',
32+
'zateutsch', 'crutkas'
33+
)
34+
35+
function Get-Attribution {
36+
param([string]$author)
37+
38+
if ($coreTeam -contains $author) {
39+
return $null # No attribution needed
40+
}
41+
return "Thanks [@$author](https://github.com/$author)!"
42+
}
43+
44+
# Usage
45+
$author = gh pr view 12345 --repo microsoft/PowerToys --json author --jq '.author.login'
46+
$attribution = Get-Attribution $author
47+
if ($attribution) {
48+
Write-Host "Add: $attribution"
49+
} else {
50+
Write-Host "No attribution needed (core team member)"
51+
}
52+
```
53+
54+
## Attribution Format
55+
56+
**With attribution:**
57+
```markdown
58+
- The Awake countdown timer now stays accurate over long periods. Thanks [@daverayment](https://github.com/daverayment)!
59+
```
60+
61+
**Without attribution (core team):**
62+
```markdown
63+
- Added new feature to Command Palette for opening settings.
64+
```
65+
66+
## Special Cases
67+
68+
1. **Co-authored commits**: Credit the primary author (first in list)
69+
2. **Bot accounts** (dependabot, etc.): No attribution
70+
3. **Former core team members**: Check if they were core team at time of PR
71+
4. **Multiple PRs by same external contributor**: Thank them on each entry
72+
73+
## High-Impact Community Members
74+
75+
These contributors have made significant ongoing contributions and are recognized in COMMUNITY.md:
76+
- @davidegiacometti
77+
- @htcfreek
78+
- @daverayment
79+
- @jiripolasek
80+
- And others listed in the "High impact community members" section
81+
82+
Always thank them appropriately!

0 commit comments

Comments
 (0)