-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Copilot Skill: Add skill for generate a release-change-log #44577
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vanzue
wants to merge
3
commits into
main
Choose a base branch
from
dev/vanzue/skill-for-release-generation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+848
−0
Open
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| --- | ||
| name: changelog-generator | ||
| 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. | ||
| --- | ||
|
|
||
| # Changelog Generator | ||
|
|
||
| This skill transforms technical git commits into polished, user-friendly changelogs that your customers and users will actually understand and appreciate. | ||
|
|
||
| ## When to Use This Skill | ||
|
|
||
| - Preparing release notes for a new version | ||
| - Generating changelog between two tags/commits | ||
| - Creating draft release notes from recent commits | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ``` | ||
| Create a changelog from commits since v0.96.1 | ||
| ``` | ||
|
|
||
| ``` | ||
| Create release notes for version 0.97.0 starting from tag v0.96.1 | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Workflow Overview | ||
|
|
||
| ``` | ||
| ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ | ||
| │ 1. Fetch │───▶│ 2. Filter │───▶│ 3. Categorize│───▶│ 4. Generate │ | ||
| │ Commits │ │ & Dedupe │ │ by Module │ │ Descriptions │ | ||
| └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ | ||
| │ │ │ │ | ||
| ▼ ▼ ▼ ▼ | ||
| 📄 github-api 📄 commit- 📄 module- 📄 user-facing- | ||
| reference.md filtering.md mapping.md description.md | ||
| ``` | ||
|
|
||
| ## Sub-Skills Reference | ||
|
|
||
| This skill is composed of the following sub-skills. | ||
|
|
||
| **⚠️ IMPORTANT: Do NOT read all sub-skills at once!** | ||
| - Only read a sub-skill when you reach that step in the workflow | ||
| - This saves context window and improves accuracy | ||
| - Use `read_file` to load a sub-skill only when needed | ||
|
|
||
| | Step | Sub-Skill | When to Read | | ||
| |------|-----------|--------------| | ||
| | Fetch data | [github-api-reference.md](sub-skills/github-api-reference.md) | When fetching commits/PRs | | ||
| | Filter commits | [commit-filtering.md](sub-skills/commit-filtering.md) | When checking if commit should be skipped | | ||
| | Categorize | [module-mapping.md](sub-skills/module-mapping.md) | When determining which module a PR belongs to | | ||
| | Generate text | [user-facing-description.md](sub-skills/user-facing-description.md) | When writing the changelog entry text | | ||
| | Attribution | [contributor-attribution.md](sub-skills/contributor-attribution.md) | When checking if author needs thanks | | ||
| | Large releases | [progress-tracking.md](sub-skills/progress-tracking.md) | Only if processing 50+ commits | | ||
|
|
||
| --- | ||
|
|
||
| ## Step-by-Step Summary | ||
|
|
||
| ### Step 1: Get Commit Range | ||
| ```powershell | ||
| # Count commits between tags | ||
| gh api repos/microsoft/PowerToys/compare/v0.96.0...v0.96.1 --jq '.commits | length' | ||
| ``` | ||
| 👉 Details: [github-api-reference.md](sub-skills/github-api-reference.md) | ||
|
|
||
| ### Step 2: Filter Commits | ||
| - Skip commits already in start tag | ||
| - Skip cherry-picks and backports | ||
| - Deduplicate by PR number | ||
|
|
||
| 👉 Details: [commit-filtering.md](sub-skills/commit-filtering.md) | ||
|
|
||
| ### Step 3: For Each PR, Generate Entry | ||
| 1. Get PR title, body, files, labels | ||
| 2. Determine module from file paths or labels | ||
| 3. Check if user-facing (skip internal changes) | ||
| 4. Transform to user-friendly description | ||
| 5. Add contributor attribution if needed | ||
|
|
||
| 👉 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) | ||
|
|
||
| ### Step 4: Checkpoint (if 50+ commits) | ||
| - Save progress after every 15-20 commits | ||
| - Track processed PRs for deduplication | ||
| - Enable resume from interruption | ||
|
|
||
| 👉 Details: [progress-tracking.md](sub-skills/progress-tracking.md) | ||
|
|
||
| ### Step 5: Format Output | ||
| ```markdown | ||
| ## ✨ What's new | ||
| **Version X.XX (Month Year)** | ||
|
|
||
| **✨ Highlights** | ||
| - [Most impactful change 1] | ||
| - [Most impactful change 2] | ||
|
|
||
| ### [Module Name - Alphabetical] | ||
| - [Description]. Thanks [@contributor](https://github.com/contributor)! | ||
|
|
||
| ### Development | ||
| - [Internal changes] | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Example Output | ||
|
|
||
| ```markdown | ||
| ## ✨ What's new | ||
| **Version 0.96.1 (December 2025)** | ||
|
|
||
| **✨ Highlights** | ||
| - Advanced Paste now supports multiple AI providers. | ||
| - PowerRename can extract photo metadata for renaming. | ||
|
|
||
| ### Advanced Paste | ||
| - Added support for Azure OpenAI, Google Gemini, Mistral, and more. | ||
|
|
||
| ### Awake | ||
| - The countdown timer now stays accurate over long periods. Thanks [@daverayment](https://github.com/daverayment)! | ||
|
|
||
| ### Development | ||
| - Resolved build warnings in Command Palette projects. | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Tips | ||
|
|
||
| 1. **Propose highlights** after all entries are generated | ||
| 2. **Check PR body** when title is unclear | ||
| 3. **Thank external contributors** - see [contributor-attribution.md](sub-skills/contributor-attribution.md) | ||
| 4. **Use progress tracking** for large releases - see [progress-tracking.md](sub-skills/progress-tracking.md) | ||
| 5. **Save output** to `release-change-note-draft.md` | ||
|
|
||
| --- | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| | Problem | Solution | | ||
| |---------|----------| | ||
| | Lost progress mid-generation | Read `release-notes-progress.md` to resume | | ||
| | Duplicate entries | Check processed PR list, dedupe by PR number | | ||
| | Commit already released | Use `git merge-base --is-ancestor` to verify | | ||
| | API rate limited | Check `gh api rate_limit`, wait or use token | | ||
|
|
||
| 👉 See sub-skills for detailed troubleshooting. |
97 changes: 97 additions & 0 deletions
97
.github/skills/changelog-generator/sub-skills/commit-filtering.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # Commit Filtering Rules | ||
|
|
||
| This sub-skill defines rules for filtering commits to include in the changelog. | ||
|
|
||
| ## Filter Out Commits Already in Start Tag | ||
|
|
||
| **CRITICAL: Skip commits that are already included in the start tag to avoid duplicates.** | ||
|
|
||
| This happens when: | ||
| - Cherry-picks from main to stable branch | ||
| - Backported fixes that were already released | ||
| - Commits included in a previous release | ||
|
|
||
| ### Method 1: Git Merge-Base (Local, Most Reliable) | ||
|
|
||
| ```powershell | ||
| $startTag = "v0.96.0" | ||
| $commitSha = "abc1234" | ||
|
|
||
| # Check if commit is ancestor of (already included in) start tag | ||
| # Returns exit code 0 if true, 1 if false | ||
| git merge-base --is-ancestor $commitSha $startTag | ||
| if ($LASTEXITCODE -eq 0) { | ||
| Write-Host "SKIP: Commit $commitSha already in $startTag" | ||
| } else { | ||
| Write-Host "PROCESS: Commit $commitSha is new" | ||
| } | ||
| ``` | ||
|
|
||
| ### Method 2: GitHub API Compare (Auto-Filtered) | ||
|
|
||
| ```powershell | ||
| # The compare API already handles this - it returns only commits | ||
| # that are in the "head" but NOT in the "base" | ||
| $compare = gh api repos/microsoft/PowerToys/compare/v0.96.0...v0.96.1 | ConvertFrom-Json | ||
|
|
||
| # These commits are guaranteed to be NEW (not in v0.96.0) | ||
| $newCommits = $compare.commits | ||
| Write-Host "Found $($newCommits.Count) new commits not in start tag" | ||
| ``` | ||
|
|
||
| ### Method 3: Check Tags Containing Commit | ||
|
|
||
| ```powershell | ||
| $commitSha = "abc1234" | ||
| $tagsContaining = git tag --contains $commitSha | ||
| if ($tagsContaining -match "v0\.96\.0") { | ||
| Write-Host "SKIP: Commit already released in v0.96.0" | ||
| } | ||
| ``` | ||
|
|
||
| ## Batch Filter Script | ||
|
|
||
| ```powershell | ||
| $startTag = "v0.96.0" | ||
| $endTag = "v0.96.1" | ||
|
|
||
| # Get commits from compare (already filtered - only new commits) | ||
| $newCommits = gh api repos/microsoft/PowerToys/compare/$startTag...$endTag --jq '.commits[] | {sha: .sha, message: .commit.message}' | ConvertFrom-Json | ||
|
|
||
| # Additional validation: filter out any merge commits that reference old PRs | ||
| $filteredCommits = $newCommits | Where-Object { | ||
| $sha = $_.sha | ||
| # Double-check: ensure commit is not ancestor of start tag | ||
| git merge-base --is-ancestor $sha $startTag 2>$null | ||
| $LASTEXITCODE -ne 0 # Keep only if NOT an ancestor | ||
| } | ||
|
|
||
| Write-Host "After filtering: $($filteredCommits.Count) commits to process" | ||
| ``` | ||
|
|
||
| ## Skip Rules Summary | ||
|
|
||
| | Condition | Action | | ||
| |-----------|--------| | ||
| | `git merge-base --is-ancestor $sha $startTag` returns 0 | SKIP - already in start tag | | ||
| | Commit message contains "cherry-pick" + old PR number | SKIP - likely backport | | ||
| | PR was merged before start tag date | SKIP - old PR | | ||
| | Same PR number already processed | SKIP - duplicate | | ||
|
|
||
| ## User-Facing vs Non-User-Facing | ||
|
|
||
| **Include in changelog:** | ||
| - New features and capabilities | ||
| - Bug fixes that affect users | ||
| - UI/UX improvements | ||
| - Performance improvements users would notice | ||
| - Breaking changes or behavior modifications | ||
| - Security fixes | ||
|
|
||
| **Exclude from changelog (put in Development section):** | ||
| - Internal refactoring | ||
| - CI/CD changes | ||
| - Code style fixes | ||
| - Test additions/modifications | ||
| - Documentation-only changes | ||
| - Dependency updates (unless user-visible impact) |
82 changes: 82 additions & 0 deletions
82
.github/skills/changelog-generator/sub-skills/contributor-attribution.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| # Contributor Attribution Rules | ||
|
|
||
| This sub-skill defines when and how to credit contributors in changelog entries. | ||
|
|
||
| ## Attribution Rules | ||
|
|
||
| - Check [COMMUNITY.md](../../../COMMUNITY.md) for the "PowerToys core team" section | ||
| - If author is **NOT** in core team → Add `Thanks [@username](https://github.com/username)!` | ||
| - If author **IS** in core team → No attribution needed | ||
| - Microsoft employees working on PowerToys as their job → No attribution needed | ||
|
|
||
| ## Core Team Members | ||
|
|
||
| Current core team members (from COMMUNITY.md) - do NOT thank these: | ||
|
|
||
| ``` | ||
| @craigloewen-msft, @niels9001, @dhowett, @yeelam-gordon, @jamrobot, | ||
|
||
| @lei9444, @shuaiyuanxx, @moooyo, @haoliuu, @chenmy77, @chemwolf6922, | ||
|
||
| @yaqingmi, @zhaoqpcn, @urnotdfs, @zhaopy536, @wang563681252, @vanzue, | ||
|
||
| @zadjii-msft, @khmyznikov, @chatasweetie, @MichaelJolley, @Jaylyn-Barbee, | ||
|
||
| @zateutsch, @crutkas | ||
|
||
| ``` | ||
|
|
||
| ## Check Author Script | ||
|
|
||
| ```powershell | ||
| $coreTeam = @( | ||
| 'craigloewen-msft', 'niels9001', 'dhowett', 'yeelam-gordon', 'jamrobot', | ||
|
||
| 'lei9444', 'shuaiyuanxx', 'moooyo', 'haoliuu', 'chenmy77', 'chemwolf6922', | ||
|
||
| 'yaqingmi', 'zhaoqpcn', 'urnotdfs', 'zhaopy536', 'wang563681252', 'vanzue', | ||
|
||
| 'zadjii-msft', 'khmyznikov', 'chatasweetie', 'MichaelJolley', 'Jaylyn-Barbee', | ||
|
||
| 'zateutsch', 'crutkas' | ||
|
||
| ) | ||
|
|
||
| function Get-Attribution { | ||
| param([string]$author) | ||
|
|
||
| if ($coreTeam -contains $author) { | ||
| return $null # No attribution needed | ||
| } | ||
| return "Thanks [@$author](https://github.com/$author)!" | ||
| } | ||
|
|
||
| # Usage | ||
| $author = gh pr view 12345 --repo microsoft/PowerToys --json author --jq '.author.login' | ||
| $attribution = Get-Attribution $author | ||
| if ($attribution) { | ||
| Write-Host "Add: $attribution" | ||
| } else { | ||
| Write-Host "No attribution needed (core team member)" | ||
| } | ||
| ``` | ||
|
|
||
| ## Attribution Format | ||
|
|
||
| **With attribution:** | ||
| ```markdown | ||
| - The Awake countdown timer now stays accurate over long periods. Thanks [@daverayment](https://github.com/daverayment)! | ||
| ``` | ||
|
|
||
| **Without attribution (core team):** | ||
| ```markdown | ||
| - Added new feature to Command Palette for opening settings. | ||
| ``` | ||
|
|
||
| ## Special Cases | ||
|
|
||
| 1. **Co-authored commits**: Credit the primary author (first in list) | ||
| 2. **Bot accounts** (dependabot, etc.): No attribution | ||
| 3. **Former core team members**: Check if they were core team at time of PR | ||
| 4. **Multiple PRs by same external contributor**: Thank them on each entry | ||
|
|
||
| ## High-Impact Community Members | ||
|
|
||
| These contributors have made significant ongoing contributions and are recognized in COMMUNITY.md: | ||
| - @davidegiacometti | ||
| - @htcfreek | ||
| - @daverayment | ||
| - @jiripolasek | ||
|
||
| - And others listed in the "High impact community members" section | ||
|
|
||
| Always thank them appropriately! | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.