AI-powered release notes generation from pull requests between two git refs, using GitHub Copilot CLI.
Give it two tags (or branches, or SHAs), and it analyzes every PR merged between them — reading titles, bodies, labels, and diffs — to produce structured, human-readable release notes.
- Zero configuration — works out of the box with sensible defaults
- Team-customizable — drop a style guide at
.github/release-notes-instructions.mdand the action follows your conventions (categories, tone, skip rules, attribution format) - Structured output — get markdown and JSON so you can feed notes into releases, changelogs, Slack, or dashboards
- Uncertainty flagging — entries the AI isn't confident about are separated for human review
- Security hardened — 4 rounds of adversarial review; prompt injection, workflow command injection, and secret exfiltration mitigations built in
This project is under active development and maintained by the GitHub CLI & Desktop team. Contributions are welcome — see CONTRIBUTING.md to get started.
- A GitHub Actions runner (Ubuntu, macOS, or Windows)
- An active GitHub Copilot license
- A fine-grained PAT with the
Copilot Requests: Readpermission (see Authentication)
- name: Generate release notes
uses: github/copilot-release-notes@main
with:
base-ref: v1.0.0
head-ref: v1.1.0
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}This action requires a COPILOT_GITHUB_TOKEN — a GitHub fine-grained personal access token with the "Copilot Requests: Read" permission. The token owner must have an active GitHub Copilot license.
- Create a fine-grained PAT with:
- Resource owner: Your organization
- Permissions:
Copilot Requests: Read
- Add it as a repository or organization secret named
COPILOT_GITHUB_TOKEN - Pass it via
envin your workflow (see examples below)
Note: This is separate from
GITHUB_TOKEN. The action usesGITHUB_TOKEN(automatically provided) for PR API calls, andCOPILOT_GITHUB_TOKENfor AI generation.
| Input | Required | Default | Description |
|---|---|---|---|
base-ref |
Yes | — | Tag, branch, or SHA to compare from (e.g., v1.0.0) |
head-ref |
No | HEAD |
Tag, branch, or SHA to compare to |
instructions |
No | Auto-discovered | Path to a markdown style guide (see Custom Instructions) |
model |
No | Copilot default | Model override (e.g., gpt-4o, claude-sonnet-4) |
pr-strategy |
No | merge-commits |
How to find PRs: merge-commits or github-api |
| Output | Description |
|---|---|
release-notes |
Formatted markdown text |
release-notes-json |
JSON array of entries with description, pr, author, and optional tag |
skipped-prs |
JSON array of PRs excluded with reasons |
uncertain-entries |
JSON array of entries flagged for human review |
name: Release Notes
on:
workflow_dispatch:
inputs:
base-ref:
description: 'Previous release tag'
required: true
head-ref:
description: 'New release tag'
required: true
jobs:
release-notes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate release notes
id: notes
uses: github/copilot-release-notes@main
with:
base-ref: ${{ inputs.base-ref }}
head-ref: ${{ inputs.head-ref }}
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- name: Print notes
run: echo "${{ steps.notes.outputs.release-notes }}" - name: Generate release notes
id: notes
uses: github/copilot-release-notes@main
with:
base-ref: v1.0.0
head-ref: v1.1.0
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- name: Create release
uses: softprops/action-gh-release@v2
with:
tag_name: v1.1.0
body: ${{ steps.notes.outputs.release-notes }} - uses: actions/checkout@v4
with:
repository: cli/cli
fetch-depth: 0
- name: Generate release notes
uses: github/copilot-release-notes@main
with:
base-ref: v2.74.0
head-ref: v2.75.0
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - name: Generate release notes
uses: github/copilot-release-notes@main
with:
base-ref: v3.5.6
head-ref: v3.5.7
instructions: .github/release-notes-instructions.md
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}The action automatically discovers a style guide at .github/release-notes-instructions.md in the checked-out repository. You can also pass an explicit path via the instructions input.
Your instructions file is a markdown document that tells the AI how your team writes release notes. You can control:
- Categories/tags — define your own groupings (e.g.,
[New],[Fixed],✨ Features,🐛 Fixes) - What to skip — tell it to ignore CI changes, dependency bumps, refactors, etc.
- Writing style — tone, tense, length, attribution format
- Entry format — how each bullet should look (e.g.,
description by @author in #PR)
# Release Notes Style Guide
## Categories
Prefix each entry with one of these tags:
- `[New]` — Significant new features (use sparingly)
- `[Added]` — Smaller features and additions
- `[Fixed]` — Bug fixes (describe what works now)
- `[Improved]` — Enhancements to existing features
## What to Skip
Do NOT generate entries for:
- CI/CD changes, test-only changes, internal refactoring
- Dependency bumps (unless fixing a security vulnerability)
## Style
- Write for users, not developers
- Use present tense: "Add", "Fix", "Update"
- Be specific but concise (10-100 characters)# Release Notes Instructions
## Categories
- **✨ Features** — New features, commands, flags
- **🐛 Fixes** — Bug fixes
- **📚 Docs & Chores** — Docs, refactors, CI, tests
- **:dependabot: Dependencies** — Dependency bumps
## Entry Format
Each entry must follow: `<description> by @<author> in #<pr_number>`
## Rules
Include ALL PRs. Nothing should be silently skipped.Without any instructions file, the action generates a flat list of bullet points summarizing every PR — no categories, no skipping.
Scans git log for merge commits (Merge pull request #N) and squash commits ((#N) in title). Fast, no API calls, works offline. Misses rebase-merged PRs.
Uses the GitHub API to find PRs associated with commits. Catches more PR types but requires API access and is slower for large ranges.
- Discover PRs — finds all PRs merged between
base-refandhead-ref - Fetch metadata — retrieves title, body, labels, and author for each PR via GitHub API
- Build prompt — assembles PR data + your instructions into a structured prompt with security guardrails
- Run Copilot CLI — sends the prompt to GitHub Copilot, which can also run
git diffto inspect actual code changes - Parse output — extracts structured JSON from the AI response
- Format — produces markdown (grouped by tag if instructions define categories) and sets all outputs
- Rebase-merged PRs are not detected by either strategy (a known GitHub API limitation for commit-based lookups)
- AI output is non-deterministic — the same inputs may produce slightly different notes across runs. Human review is recommended for important releases.
- Large releases (100+ PRs) may hit prompt size limits. Consider splitting into smaller ranges.
This action has been through 4 rounds of adversarial security review. Key protections:
- Restricted tools — Copilot CLI is only granted
shell(git)(nocat,grep, filesystem access) - Minimal environment — only
PATH,HOME, andGITHUB_TOKENare passed to the subprocess - Prompt armor — PR content is sandboxed in delimited sections with injection-resistant formatting
- Input sanitization — PR titles, bodies, labels, and authors are sanitized for delimiter injection
- Output sanitization — all output is sanitized to prevent GitHub Actions workflow command injection (
::commands) - Process isolation — real timeout with SIGTERM + guaranteed SIGKILL fallback
npm install
npm test # run 42 unit tests
npx ncc build src/index.ts -o dist # rebuild dist/Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the terms of the MIT open source license. Please refer to the LICENSE file for the full terms.
This project is maintained by the @github/gh-cli-and-desktop team.
For bug reports and feature requests, please open an issue. See SUPPORT.md for more details.
If you discover a security vulnerability, please see SECURITY.md for reporting instructions. Do not open a public issue.
This project has adopted the Contributor Covenant Code of Conduct.