A generic, reusable GitHub Action that extracts structured release notes from merged pull requests. This action parses PR content, normalizes labels, and optionally generates AI-powered summaries suitable for end users.
Dogfooded: This repository uses itself to generate release notes. See DOGFOODING.md for details.
- Extracts structured data from merged PRs (title, body, labels, authors, timestamps)
- Parses PR body sections (What was done, Why, User impact, etc.)
- Normalizes labels into high-level tags (feature, fix, refactor, infra, docs)
- Optionally generates AI-powered summaries with user-friendly language
- Outputs machine-readable JSON for downstream processing
- Defensive parsing handles missing sections and empty content
- Company-agnostic and fully open source
name: Generate Release Notes
on:
pull_request:
types: [closed]
jobs:
release-notes:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Generate Release Note
id: release-note
uses: gorilli-team/release-note-ai@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
generate_summary: false
- name: Display Release Note
run: |
echo '${{ steps.release-note.outputs.release_note }}'name: Generate Release Notes with AI
on:
pull_request:
types: [closed]
jobs:
release-notes:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Generate Release Note
id: release-note
uses: gorilli-team/release-note-ai@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
generate_summary: true
model: claude-3-5-sonnet-20241022
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Post to API
run: |
curl -X POST https://your-api.com/release-notes \
-H "Content-Type: application/json" \
-d '${{ steps.release-note.outputs.release_note }}'name: Release Notes Pipeline
on:
pull_request:
types: [closed]
jobs:
generate-and-publish:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Generate Release Note
id: release-note
uses: gorilli-team/release-note-ai@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
generate_summary: true
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
- name: Save to artifact
run: |
echo '${{ steps.release-note.outputs.release_note }}' > release-note.json
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: release-note
path: release-note.json
- name: Send to backend
run: |
curl -X POST ${{ secrets.BACKEND_URL }}/release-notes \
-H "Authorization: Bearer ${{ secrets.API_TOKEN }}" \
-H "Content-Type: application/json" \
-d '${{ steps.release-note.outputs.release_note }}'| Input | Required | Default | Description |
|---|---|---|---|
github_token |
Yes | - | GitHub token for API access (usually secrets.GITHUB_TOKEN) |
generate_summary |
No | false |
Whether to generate AI-powered summary |
model |
No | claude-3-5-sonnet-20241022 |
AI model to use for summarization (only used if generate_summary is true) |
anthropic_api_key |
Conditional | - | Anthropic API key (required only if generate_summary is true) |
A JSON string with the following structure:
{
"title": "User-friendly title (max 80 chars)",
"description": "Brief one-sentence summary",
"changes": [
"First user-facing change",
"Second user-facing change",
"Third user-facing change"
],
"tags": ["feature", "fix", "docs"],
"pr": {
"number": 123,
"url": "https://github.com/owner/repo/pull/123",
"authors": ["username1", "username2"],
"mergedAt": "2024-01-15T10:30:00Z"
},
"raw": {
"title": "Original PR title",
"body": "Full PR body content...",
"labels": ["enhancement", "bug", "documentation"]
}
}For best results, structure your pull request body with these sections:
## What was done
- Added new authentication flow
- Updated user profile page
- Fixed session timeout issue
## Why
To improve security and user experience by implementing OAuth 2.0.
## User Impact
Users will now be able to log in using their Google or GitHub accounts.
## Technical Details
- Implemented OAuth 2.0 using `passport.js`
- Added new `/auth` routes
- Updated session managementThe action will parse these sections and extract relevant information. If sections are missing, it falls back gracefully to parsing the raw PR body.
The action normalizes GitHub labels into high-level tags:
| Label | Normalized Tag |
|---|---|
bug, fix, bugfix |
fix |
feature, enhancement, feat |
feature |
refactor, refactoring |
refactor |
infrastructure, infra, ci, deployment |
infra |
documentation, docs |
docs |
chore, maintenance |
chore |
dependencies, deps |
dependencies |
security |
security |
breaking, breaking-change |
breaking-change |
Unrecognized labels are preserved as-is.
- Node.js 20+
- Yarn
yarn installyarn buildThis compiles TypeScript and bundles the action using @vercel/ncc.
Since this is a GitHub Action, local testing requires:
- Setting up environment variables that mimic GitHub Actions context
- Using tools like act to run actions locally
Example with act:
act pull_request --secret GITHUB_TOKEN=your_token --eventpath test-event.jsonsrc/
├── index.ts # Main entrypoint, orchestrates the workflow
├── types.ts # TypeScript interfaces and types
├── parser.ts # PR body parsing and label normalization
└── summarizer.ts # AI summarization logic (Anthropic API)
- Separation of Concerns: Parsing, summarization, and orchestration are separate modules
- Defensive Parsing: Handles missing sections, empty bodies, and malformed content gracefully
- Fallback Strategy: If AI summarization fails, falls back to parsed content
- No External Dependencies: Only uses official GitHub Actions and Anthropic APIs
- Output Preservation: Always includes raw PR data alongside processed content
This repository uses gorilli-team/release-note-ai to generate release notes for its own PRs. When you merge a PR to main, the action automatically:
- Generates a structured release note with AI summary
- Posts a comment on the PR with the generated note
- Saves the release note as a GitHub artifact
This ensures the action is continuously tested on real-world usage. See DOGFOODING.md for complete details on how we use the action on itself.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
See CONTRIBUTING.md and DEVELOPMENT.md for detailed guidelines.
MIT License - see LICENSE file for details.
For issues, questions, or contributions, please open an issue on GitHub.