Skip to content

Commit fa44bad

Browse files
tidy-devCopilot
andcommitted
Add README with usage docs, examples, and security details
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4e8fccc commit fa44bad

1 file changed

Lines changed: 242 additions & 0 deletions

File tree

README.md

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# Copilot Release Notes
2+
3+
AI-powered release notes generation from pull requests between two git refs, using GitHub Copilot CLI.
4+
5+
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.
6+
7+
## Features
8+
9+
- **Zero configuration** — works out of the box with sensible defaults
10+
- **Team-customizable** — drop a style guide at `.github/release-notes-instructions.md` and the action follows your conventions (categories, tone, skip rules, attribution format)
11+
- **Structured output** — get markdown *and* JSON so you can feed notes into releases, changelogs, Slack, or dashboards
12+
- **Uncertainty flagging** — entries the AI isn't confident about are separated for human review
13+
- **Security hardened** — 4 rounds of adversarial review; prompt injection, workflow command injection, and secret exfiltration mitigations built in
14+
15+
## Quick Start
16+
17+
```yaml
18+
- name: Generate release notes
19+
uses: desktop/copilot-release-notes@main
20+
with:
21+
base-ref: v1.0.0
22+
head-ref: v1.1.0
23+
env:
24+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
25+
```
26+
27+
## Authentication
28+
29+
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.
30+
31+
1. Create a [fine-grained PAT](https://github.com/settings/personal-access-tokens/new) with:
32+
- **Resource owner:** Your organization
33+
- **Permissions:** `Copilot Requests: Read`
34+
2. Add it as a repository or organization secret named `COPILOT_GITHUB_TOKEN`
35+
3. Pass it via `env` in your workflow (see examples below)
36+
37+
> **Note:** This is separate from `GITHUB_TOKEN`. The action uses `GITHUB_TOKEN` (automatically provided) for PR API calls, and `COPILOT_GITHUB_TOKEN` for AI generation.
38+
39+
## Inputs
40+
41+
| Input | Required | Default | Description |
42+
|---|---|---|---|
43+
| `base-ref` | **Yes** | — | Tag, branch, or SHA to compare from (e.g., `v1.0.0`) |
44+
| `head-ref` | No | `HEAD` | Tag, branch, or SHA to compare to |
45+
| `instructions` | No | Auto-discovered | Path to a markdown style guide (see [Custom Instructions](#custom-instructions)) |
46+
| `model` | No | Copilot default | Model override (e.g., `gpt-4o`, `claude-sonnet-4`) |
47+
| `pr-strategy` | No | `merge-commits` | How to find PRs: `merge-commits` or `github-api` |
48+
49+
## Outputs
50+
51+
| Output | Description |
52+
|---|---|
53+
| `release-notes` | Formatted markdown text |
54+
| `release-notes-json` | JSON array of entries with `description`, `pr`, `author`, and optional `tag` |
55+
| `skipped-prs` | JSON array of PRs excluded with reasons |
56+
| `uncertain-entries` | JSON array of entries flagged for human review |
57+
58+
## Examples
59+
60+
### Basic — generate notes between two tags
61+
62+
```yaml
63+
name: Release Notes
64+
on:
65+
workflow_dispatch:
66+
inputs:
67+
base-ref:
68+
description: 'Previous release tag'
69+
required: true
70+
head-ref:
71+
description: 'New release tag'
72+
required: true
73+
74+
jobs:
75+
release-notes:
76+
runs-on: ubuntu-latest
77+
steps:
78+
- uses: actions/checkout@v4
79+
with:
80+
fetch-depth: 0
81+
82+
- name: Generate release notes
83+
id: notes
84+
uses: desktop/copilot-release-notes@main
85+
with:
86+
base-ref: ${{ inputs.base-ref }}
87+
head-ref: ${{ inputs.head-ref }}
88+
env:
89+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
90+
91+
- name: Print notes
92+
run: echo "${{ steps.notes.outputs.release-notes }}"
93+
```
94+
95+
### Create a GitHub Release
96+
97+
```yaml
98+
- name: Generate release notes
99+
id: notes
100+
uses: desktop/copilot-release-notes@main
101+
with:
102+
base-ref: v1.0.0
103+
head-ref: v1.1.0
104+
env:
105+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
106+
107+
- name: Create release
108+
uses: softprops/action-gh-release@v2
109+
with:
110+
tag_name: v1.1.0
111+
body: ${{ steps.notes.outputs.release-notes }}
112+
```
113+
114+
### Cross-repo — generate notes for a different repository
115+
116+
```yaml
117+
- uses: actions/checkout@v4
118+
with:
119+
repository: cli/cli
120+
fetch-depth: 0
121+
122+
- name: Generate release notes
123+
uses: desktop/copilot-release-notes@main
124+
with:
125+
base-ref: v2.74.0
126+
head-ref: v2.75.0
127+
env:
128+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
129+
```
130+
131+
### With custom instructions
132+
133+
```yaml
134+
- name: Generate release notes
135+
uses: desktop/copilot-release-notes@main
136+
with:
137+
base-ref: v3.5.6
138+
head-ref: v3.5.7
139+
instructions: .github/release-notes-instructions.md
140+
env:
141+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
142+
```
143+
144+
## Custom Instructions
145+
146+
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.
147+
148+
Your instructions file is a markdown document that tells the AI how your team writes release notes. You can control:
149+
150+
- **Categories/tags** — define your own groupings (e.g., `[New]`, `[Fixed]`, `✨ Features`, `🐛 Fixes`)
151+
- **What to skip** — tell it to ignore CI changes, dependency bumps, refactors, etc.
152+
- **Writing style** — tone, tense, length, attribution format
153+
- **Entry format** — how each bullet should look (e.g., `description by @author in #PR`)
154+
155+
### Example: simple category-based guide
156+
157+
```markdown
158+
# Release Notes Style Guide
159+
160+
## Categories
161+
Prefix each entry with one of these tags:
162+
- `[New]` — Significant new features (use sparingly)
163+
- `[Added]` — Smaller features and additions
164+
- `[Fixed]` — Bug fixes (describe what works now)
165+
- `[Improved]` — Enhancements to existing features
166+
167+
## What to Skip
168+
Do NOT generate entries for:
169+
- CI/CD changes, test-only changes, internal refactoring
170+
- Dependency bumps (unless fixing a security vulnerability)
171+
172+
## Style
173+
- Write for users, not developers
174+
- Use present tense: "Add", "Fix", "Update"
175+
- Be specific but concise (10-100 characters)
176+
```
177+
178+
### Example: include-everything guide (like cli/cli)
179+
180+
```markdown
181+
# Release Notes Instructions
182+
183+
## Categories
184+
- **✨ Features** — New features, commands, flags
185+
- **🐛 Fixes** — Bug fixes
186+
- **📚 Docs & Chores** — Docs, refactors, CI, tests
187+
- **:dependabot: Dependencies** — Dependency bumps
188+
189+
## Entry Format
190+
Each entry must follow: `<description> by @<author> in #<pr_number>`
191+
192+
## Rules
193+
Include ALL PRs. Nothing should be silently skipped.
194+
```
195+
196+
Without any instructions file, the action generates a flat list of bullet points summarizing every PR — no categories, no skipping.
197+
198+
## PR Discovery Strategies
199+
200+
### `merge-commits` (default)
201+
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.
202+
203+
### `github-api`
204+
Uses the GitHub API to find PRs associated with commits. Catches more PR types but requires API access and is slower for large ranges.
205+
206+
## How It Works
207+
208+
1. **Discover PRs** — finds all PRs merged between `base-ref` and `head-ref`
209+
2. **Fetch metadata** — retrieves title, body, labels, and author for each PR via GitHub API
210+
3. **Build prompt** — assembles PR data + your instructions into a structured prompt with security guardrails
211+
4. **Run Copilot CLI** — sends the prompt to GitHub Copilot, which can also run `git diff` to inspect actual code changes
212+
5. **Parse output** — extracts structured JSON from the AI response
213+
6. **Format** — produces markdown (grouped by tag if instructions define categories) and sets all outputs
214+
215+
## Known Limitations
216+
217+
- **Rebase-merged PRs** are not detected by either strategy (a known GitHub API limitation for commit-based lookups)
218+
- **AI output is non-deterministic** — the same inputs may produce slightly different notes across runs. Human review is recommended for important releases.
219+
- **Large releases** (100+ PRs) may hit prompt size limits. Consider splitting into smaller ranges.
220+
221+
## Security
222+
223+
This action has been through 4 rounds of adversarial security review. Key protections:
224+
225+
- **Restricted tools** — Copilot CLI is only granted `shell(git)` (no `cat`, `grep`, filesystem access)
226+
- **Minimal environment** — only `PATH`, `HOME`, and `GITHUB_TOKEN` are passed to the subprocess
227+
- **Prompt armor** — PR content is sandboxed in delimited sections with injection-resistant formatting
228+
- **Input sanitization** — PR titles, bodies, labels, and authors are sanitized for delimiter injection
229+
- **Output sanitization** — all output is sanitized to prevent GitHub Actions workflow command injection (`::` commands)
230+
- **Process isolation** — real timeout with SIGTERM + guaranteed SIGKILL fallback
231+
232+
## Development
233+
234+
```bash
235+
npm install
236+
npm test # run 42 unit tests
237+
npx ncc build src/index.ts -o dist # rebuild dist/
238+
```
239+
240+
## License
241+
242+
MIT

0 commit comments

Comments
 (0)