PR Changelog Generator
Automatically generate release notes and changelogs from merged pull requests.
This workflow analyzes PRs, categorizes changes, and creates user-facing release notes with proper formatting.
Implementation
1import { relay } from "@relayplane/workflows";23const result = await relay4 .workflow("pr-changelog")56 // Step 1: Categorize pull requests7 .step("categorize-prs")8 .with("openai:gpt-4o")9 .prompt(`Categorize these merged pull requests:1011{{pullRequests}}1213Categories:14- ๐ Features: New functionality15- ๐ Bug Fixes: Defect repairs16- โก Performance: Speed/efficiency improvements17- ๐ Security: Security patches18- ๐ Documentation: Docs updates19- ๐งน Chores: Refactoring, dependencies, CI/CD20- โ ๏ธ Breaking Changes: API changes requiring migration2122For each PR:23- Category (one primary)24- User-facing: yes/no25- Breaking change: yes/no26- Summary (1 sentence, non-technical language)2728Return as JSON array.`)2930 // Step 2: Generate user-facing descriptions31 .step("write-descriptions")32 .with("anthropic:claude-3.5-sonnet")33 .depends("categorize-prs")34 .prompt(`Write user-facing descriptions for these changes:3536{{categorize-prs.output}}3738For each user-facing change:39- Translate technical jargon to user benefits40- Focus on "what" not "how"41- Be specific about impact42- Keep to 1-2 sentences43- Use active voice4445Example:46โ "Refactored API client to use connection pooling"47โ
"API requests are now 3x faster with improved connection handling"4849Skip internal/chores unless significant.`)5051 // Step 3: Identify breaking changes52 .step("breaking-changes")53 .with("anthropic:claude-3.5-sonnet")54 .depends("categorize-prs")55 .prompt(`Document breaking changes and migration steps:5657{{categorize-prs.output}}5859For each breaking change:60- What changed (API, behavior, etc.)61- Why we made this change62- Migration steps (specific code examples)63- Deprecation timeline if applicable6465Format for developer documentation.`)6667 // Step 4: Generate changelog68 .step("generate-changelog")69 .with("anthropic:claude-3.5-sonnet")70 .depends("categorize-prs", "write-descriptions", "breaking-changes")71 .prompt(`Create release changelog:7273Categorized PRs: {{categorize-prs.output}}74Descriptions: {{write-descriptions.output}}75Breaking Changes: {{breaking-changes.output}}7677Version: {{version}}78Release Date: {{releaseDate}}7980Format:81# Release {{version}} - {{releaseDate}}8283## โ ๏ธ Breaking Changes84[If any, with migration guides]8586## ๐ New Features87- Feature 1 (#PR_NUMBER)88- Feature 2 (#PR_NUMBER)8990## ๐ Bug Fixes91- Fix description (#PR_NUMBER)9293## โก Performance Improvements94- Improvement (#PR_NUMBER)9596## ๐ Documentation97- Doc updates (#PR_NUMBER)9899## ๐ Contributors100[@username1, @username2]101102Use emoji, link to PR numbers, credit contributors.103Exclude chores/internal changes.`)104105 .run({106 pullRequests: mergedPRs.map(pr => ({107 number: pr.number,108 title: pr.title,109 body: pr.body,110 author: pr.author,111 labels: pr.labels,112 })),113 version: "v3.2.0",114 releaseDate: new Date().toISOString().split('T')[0],115 });116117// Save to CHANGELOG.md118const changelog = result.steps["generate-changelog"].output;119await prependToFile("CHANGELOG.md", changelog + "\n\n");120121// Post to GitHub Releases122await github.repos.createRelease({123 owner: repo.owner,124 repo: repo.name,125 tag_name: "v3.2.0",126 name: "Release v3.2.0",127 body: changelog,128});Automated Release Flow
1// GitHub Actions workflow2import { relay } from "@relayplane/workflows";3import { Octokit } from "@octokit/rest";45async function generateReleaseNotes(fromTag: string, toTag: string) {6 const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });78 // Get all PRs merged between tags9 const compare = await octokit.repos.compareCommits({10 owner: "myorg",11 repo: "myrepo",12 base: fromTag,13 head: toTag,14 });1516 const prNumbers = compare.data.commits17 .map(c => c.commit.message.match(/#(\d+)/)?.[1])18 .filter(Boolean);1920 const prs = await Promise.all(21 prNumbers.map(num =>22 octokit.pulls.get({23 owner: "myorg",24 repo: "myrepo",25 pull_number: parseInt(num!),26 })27 )28 );2930 // Generate changelog31 const changelog = await relay32 .workflow("pr-changelog")33 .run({34 pullRequests: prs.map(pr => pr.data),35 version: toTag,36 releaseDate: new Date().toISOString().split('T')[0],37 });3839 return changelog.steps["generate-changelog"].output;40}4142// In CI/CD43const notes = await generateReleaseNotes("v3.1.0", "v3.2.0");44await createGitHubRelease({ tag: "v3.2.0", notes });Conventional Commits Integration
1// Parse conventional commits for automatic categorization2import { relay } from "@relayplane/workflows";34async function parseConventionalCommits(commits: string[]) {5 const categorized = commits.map(commit => {6 const match = commit.match(/^(\w+)(\(.+\))?!?: (.+)/);7 if (!match) return null;89 const [, type, scope, description] = match;10 const breaking = commit.includes('!:');1112 return {13 type, // feat, fix, docs, chore, etc.14 scope: scope?.replace(/[()]/g, ''),15 description,16 breaking,17 };18 }).filter(Boolean);1920 const prData = categorized.map(c => ({21 title: c.description,22 type: c.type,23 breaking: c.breaking,24 }));2526 return await relay27 .workflow("pr-changelog")28 .run({ pullRequests: prData, version: "v3.2.0" });29}Sample Output
1# Release v3.2.0 - 2024-11-1823## โ ๏ธ Breaking Changes45**API Authentication now requires Bearer tokens**6Previously, API keys could be passed via query parameters. For security, we now require authentication via the \`Authorization\` header.78Migration:9\`\`\`diff10- fetch('https://api.example.com/data?api_key=xxx')11+ fetch('https://api.example.com/data', {12+ headers: { 'Authorization': 'Bearer xxx' }13+ })14\`\`\`1516Timeline: Query param auth deprecated immediately, removed in v4.0.0 (Jan 2025)1718## ๐ New Features1920- **Multi-model workflows**: Chain steps across OpenAI, Anthropic, and Google models in a single workflow (#247)21- **Webhook retry logic**: Automatically retry failed webhook deliveries with exponential backoff (#251)22- **Team workspaces**: Collaborate on workflows with team members and role-based permissions (#256)2324## ๐ Bug Fixes2526- Fixed workflow execution timeout not being respected (#243)27- Resolved memory leak in long-running scheduled jobs (#248)28- Corrected timezone handling for cron schedules (#253)2930## โก Performance Improvements3132- Reduced workflow cold start time by 60% through better caching (#245)33- Database query optimization decreased API latency by 200ms (#249)3435## ๐ Documentation3637- Added 25 production-ready workflow examples (#258)38- Created migration guide for v2 to v3 upgrade (#259)3940## ๐ Contributors4142Thank you to @sarah-dev, @mike-engineer, @alex-designer, and 12 other contributors for making this release possible!4344**Full Changelog**: https://github.com/org/repo/compare/v3.1.0...v3.2.0Benefits
- Consistency: Same format for every release
- Time Savings: Auto-generate in seconds vs 30+ minutes manual
- User-Focused: Non-technical language for product updates
- Complete: Never forget to document a change
Pro Tip: Combine with semantic versioning to automatically determine version bumps based on change types (breaking = major, feat = minor, fix = patch)