-
Notifications
You must be signed in to change notification settings - Fork 34
feat: Add release notes generator workflow #105
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
Changes from 1 commit
fe3cfe7
481832a
1d03fc8
5153ddc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "name": "Release Notes Generator", | ||
| "description": "Generate structured release notes from git commits and tags with automatic categorization into features, bug fixes, breaking changes, and enhancements", | ||
| "systemPrompt": "You are a release notes generation specialist helping users create professional, structured release notes from git commit history.\n\n## Your Role\n\nHelp users generate comprehensive release notes by:\n1. Analyzing git commits between version tags\n2. Automatically categorizing changes (features, bug fixes, breaking changes, enhancements)\n3. Extracting PR numbers and commit hashes\n4. Generating markdown-formatted release notes ready for GitHub releases\n\n## Available Commands\n\n- `/generate` - Interactive guided release notes generation\n\n## How to Help Users\n\n**Conversational Approach**: Guide users through providing:\n- Current version tag (required)\n- Previous version tag (optional but recommended)\n- Repository path (optional, defaults to current directory)\n- Repository URL (optional, for generating clickable links)\n\n**Automatic Installation**: The utility-mcp-server package will be installed automatically if needed.\n\n**Output Location**: All generated files go to `artifacts/release-notes/`\n\n## Process Flow\n\n1. **Gather Information**: Get version tags, repo path, and URL from user\n2. **Install Tool**: Ensure utility-mcp-server Python package is available\n3. **Generate Notes**: Call the generation tool with user's parameters\n4. **Save Output**: Save to `artifacts/release-notes/RELEASE_NOTES_<version>.md`\n5. **Present Results**: Show the user the generated notes and statistics\n\n## Tool Details\n\nYou use the `generate_release_notes` function from utility-mcp-server which:\n- Parses git log between tags\n- Recognizes conventional commit formats (feat:, fix:, BREAKING CHANGE:, etc.)\n- Categorizes by component (UI/UX, API, Database, CLI, etc.)\n- Extracts PR numbers from patterns like #123, (#123), PR #123\n- Generates professional markdown with emoji indicators\n\n## Best Practices\n\n- Always ask for both current and previous version tags for meaningful diffs\n- Encourage users to provide repository URL for clickable PR/commit links\n- Explain commit message best practices if notes seem sparse\n- Save both the markdown and statistics for user reference\n\n## Quality Guidelines\n\n- Verify git tags exist before attempting generation\n- Handle errors gracefully with helpful messages\n- If no commits found, explain possible reasons (tags don't exist, no changes between tags)\n- Show statistics to help users understand the scope of changes", | ||
| "startupPrompt": "Greet the user briefly as a release notes generation assistant. Explain that you can generate structured release notes from git commits between version tags, automatically categorizing changes into features, bug fixes, breaking changes, and enhancements. Ask what repository and version tags they'd like to generate release notes for. Keep it concise (2-3 sentences).", | ||
| "results": { | ||
| "Release Notes": "artifacts/release-notes/RELEASE_NOTES_*.md", | ||
| "Statistics": "artifacts/release-notes/stats_*.json", | ||
| "Generation Scripts": "artifacts/release-notes/generate_*.py" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,142 @@ | ||||||||||||||||
| # /generate - Generate Release Notes | ||||||||||||||||
|
|
||||||||||||||||
| Generate structured release notes from git commits between two version tags with automatic categorization. | ||||||||||||||||
|
|
||||||||||||||||
| ## Usage | ||||||||||||||||
|
|
||||||||||||||||
| ``` | ||||||||||||||||
| /generate [current_version] [previous_version] [repo_path] [repo_url] | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| All parameters are optional - if not provided, you'll be prompted conversationally. | ||||||||||||||||
|
|
||||||||||||||||
| ## Examples | ||||||||||||||||
|
|
||||||||||||||||
| ``` | ||||||||||||||||
| /generate v1.0.0 v0.9.0 | ||||||||||||||||
| /generate v2.0.0 v1.9.0 /path/to/repo | ||||||||||||||||
| /generate v1.5.0 v1.4.0 /path/to/repo https://github.com/org/repo | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| ## Process | ||||||||||||||||
|
|
||||||||||||||||
| ### 1. Gather Information | ||||||||||||||||
|
|
||||||||||||||||
| Collect from user (if not in command): | ||||||||||||||||
| - Current version tag (required) | ||||||||||||||||
| - Previous version tag (optional) | ||||||||||||||||
| - Repository path (optional, defaults to current directory) | ||||||||||||||||
| - Repository URL (optional, for clickable links) | ||||||||||||||||
|
|
||||||||||||||||
| ### 2. Validate Environment | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| # Verify git repository | ||||||||||||||||
| git -C <repo_path> status | ||||||||||||||||
|
|
||||||||||||||||
| # List and verify tags | ||||||||||||||||
| git -C <repo_path> tag -l | ||||||||||||||||
| git -C <repo_path> tag -l | grep -x <version> | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| ### 3. Install Tool | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| python3 -c "import utility_mcp_server" 2>/dev/null || pip install utility-mcp-server | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| ### 4. Create Generation Script | ||||||||||||||||
|
|
||||||||||||||||
| Save to `artifacts/release-notes/generate_<version>.py`: | ||||||||||||||||
|
|
||||||||||||||||
| ```python | ||||||||||||||||
| #!/usr/bin/env python3 | ||||||||||||||||
| import asyncio | ||||||||||||||||
| import json | ||||||||||||||||
| from pathlib import Path | ||||||||||||||||
| from utility_mcp_server.src.tools.release_notes_tool import generate_release_notes | ||||||||||||||||
|
|
||||||||||||||||
| async def main(): | ||||||||||||||||
| # Ensure output directory exists | ||||||||||||||||
| Path("artifacts/release-notes").mkdir(parents=True, exist_ok=True) | ||||||||||||||||
|
|
||||||||||||||||
| # Generate release notes | ||||||||||||||||
| result = await generate_release_notes( | ||||||||||||||||
| version="<VERSION>", | ||||||||||||||||
| previous_version="<PREVIOUS_VERSION>", | ||||||||||||||||
| repo_path="<REPO_PATH>", | ||||||||||||||||
| repo_url="<REPO_URL>", | ||||||||||||||||
| release_date=None # Uses today's date | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| if result.get("status") == "success": | ||||||||||||||||
| # Save release notes | ||||||||||||||||
| notes_file = "artifacts/release-notes/RELEASE_NOTES_<VERSION>.md" | ||||||||||||||||
| with open(notes_file, "w") as f: | ||||||||||||||||
| f.write(result["release_notes"]) | ||||||||||||||||
| print(f"β Release notes saved to: {notes_file}") | ||||||||||||||||
|
|
||||||||||||||||
| # Save statistics | ||||||||||||||||
| if "statistics" in result: | ||||||||||||||||
| stats_file = "artifacts/release-notes/stats_<VERSION>.json" | ||||||||||||||||
| with open(stats_file, "w") as f: | ||||||||||||||||
| json.dump(result["statistics"], f, indent=2) | ||||||||||||||||
| print(f"β Statistics saved to: {stats_file}") | ||||||||||||||||
|
|
||||||||||||||||
| # Display release notes | ||||||||||||||||
| print("\n" + "="*80) | ||||||||||||||||
| print(result["release_notes"]) | ||||||||||||||||
| print("="*80 + "\n") | ||||||||||||||||
|
|
||||||||||||||||
| # Display statistics | ||||||||||||||||
| if "statistics" in result: | ||||||||||||||||
| print("π Statistics:") | ||||||||||||||||
| for key, value in result["statistics"].items(): | ||||||||||||||||
| print(f" {key}: {value}") | ||||||||||||||||
|
|
||||||||||||||||
| return result | ||||||||||||||||
| else: | ||||||||||||||||
| error_msg = result.get("error", "Unknown error") | ||||||||||||||||
| print(f"β Error: {error_msg}") | ||||||||||||||||
| return result | ||||||||||||||||
|
|
||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||
| asyncio.run(main()) | ||||||||||||||||
| ``` | ||||||||||||||||
|
|
||||||||||||||||
| ### 5. Execute | ||||||||||||||||
|
|
||||||||||||||||
| ```bash | ||||||||||||||||
| cd artifacts/release-notes && python3 generate_<version>.py | ||||||||||||||||
| ``` | ||||||||||||||||
|
Comment on lines
+107
to
+111
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Path inconsistency between script and execution. The execution step changes directory to π§ Proposed fixEither execute from the repository root: -### 5. Execute
-
-```bash
-cd artifacts/release-notes && python3 generate_<version>.py
-```
+### 5. Execute
+
+```bash
+python3 artifacts/release-notes/generate_<version>.py
+```Or update the script to use absolute paths or adjust for the current directory. π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||
|
|
||||||||||||||||
| ### 6. Present Results | ||||||||||||||||
|
|
||||||||||||||||
| Show the user: | ||||||||||||||||
| 1. Generated release notes (formatted) | ||||||||||||||||
| 2. Statistics summary | ||||||||||||||||
| 3. File locations | ||||||||||||||||
| 4. Next steps | ||||||||||||||||
|
|
||||||||||||||||
| ## Output | ||||||||||||||||
|
|
||||||||||||||||
| Files created in `artifacts/release-notes/`: | ||||||||||||||||
| - `RELEASE_NOTES_<version>.md` - Main release notes | ||||||||||||||||
| - `stats_<version>.json` - Statistics | ||||||||||||||||
| - `generate_<version>.py` - Generation script | ||||||||||||||||
|
|
||||||||||||||||
| ## Error Handling | ||||||||||||||||
|
|
||||||||||||||||
| Handle gracefully: | ||||||||||||||||
| - Tags don't exist β List available tags | ||||||||||||||||
| - No commits β Explain possible causes | ||||||||||||||||
| - Not a git repo β Verify path | ||||||||||||||||
| - Installation fails β Check Python/pip | ||||||||||||||||
|
|
||||||||||||||||
| ## Tips | ||||||||||||||||
|
|
||||||||||||||||
| Suggest to users: | ||||||||||||||||
| - Use conventional commits (`feat:`, `fix:`, etc.) | ||||||||||||||||
| - Include PR numbers in commits | ||||||||||||||||
| - Provide repository URL for links | ||||||||||||||||
| - Tag releases consistently | ||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Python | ||
| __pycache__/ | ||
| *.py[cod] | ||
| *$py.class | ||
| *.so | ||
| .Python | ||
| env/ | ||
| venv/ | ||
| .venv/ | ||
| ENV/ | ||
| *.egg-info/ | ||
| dist/ | ||
| build/ | ||
|
|
||
| # IDEs | ||
| .vscode/ | ||
| .idea/ | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
| .DS_Store | ||
|
|
||
| # Output artifacts (generated at runtime) | ||
| artifacts/ | ||
|
|
||
| # Logs | ||
| *.log | ||
| .claude/logs/ | ||
|
|
||
| # Temporary files | ||
| *.tmp | ||
| .temp/ | ||
| tmp/ | ||
|
|
||
| # Environment | ||
| .env | ||
| .env.local | ||
|
|
||
| # Test outputs | ||
| test-output/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| # How to Add the /generate Command | ||
|
|
||
| The system has security restrictions that prevent automatic creation of files in `.claude/commands/`. | ||
|
|
||
| You'll need to add the command file manually. Here's how: | ||
|
|
||
| ## Quick Method | ||
|
|
||
| I've created the command content for you at: | ||
| ``` | ||
| /workspace/artifacts/release-notes-workflow/generate_command_temp.md | ||
| ``` | ||
|
|
||
| **Simply rename and move it:** | ||
|
|
||
| ```bash | ||
| cd /workspace/artifacts/release-notes-workflow | ||
| mv generate_command_temp.md .claude/commands/generate.md | ||
| ``` | ||
|
|
||
| ## Alternative: Create Directly in Git | ||
|
|
||
| If you've already pushed to GitHub and are working in a clone: | ||
|
|
||
| ```bash | ||
| cd /path/to/your/workflows-repo/workflows/release-notes-generator | ||
|
|
||
| # Create the file directly | ||
| cat > .claude/commands/generate.md << 'EOF' | ||
| # /generate - Generate Release Notes | ||
|
|
||
| Generate structured release notes from git commits between two version tags with automatic categorization. | ||
|
|
||
| ## Usage | ||
|
|
||
| \`\`\` | ||
| /generate [current_version] [previous_version] [repo_path] [repo_url] | ||
| \`\`\` | ||
|
|
||
| All parameters are optional - if not provided, you'll be prompted conversationally. | ||
|
|
||
| ## Examples | ||
|
|
||
| \`\`\` | ||
| /generate v1.0.0 v0.9.0 | ||
| /generate v2.0.0 v1.9.0 /path/to/repo | ||
| /generate v1.5.0 v1.4.0 /path/to/repo https://github.com/org/repo | ||
| \`\`\` | ||
|
|
||
| ## Process | ||
|
|
||
| ### 1. Gather Information | ||
|
|
||
| Collect from user (if not in command): | ||
| - Current version tag (required) | ||
| - Previous version tag (optional) | ||
| - Repository path (optional, defaults to current directory) | ||
| - Repository URL (optional, for clickable links) | ||
|
|
||
| ### 2. Validate Environment | ||
|
|
||
| \`\`\`bash | ||
| # Verify git repository | ||
| git -C <repo_path> status | ||
|
|
||
| # List and verify tags | ||
| git -C <repo_path> tag -l | ||
| git -C <repo_path> tag -l | grep -x <version> | ||
| \`\`\` | ||
|
|
||
| ### 3. Install Tool | ||
|
|
||
| \`\`\`bash | ||
| python3 -c "import utility_mcp_server" 2>/dev/null || pip install utility-mcp-server | ||
| \`\`\` | ||
|
|
||
| ### 4. Create Generation Script | ||
|
|
||
| Save to \`artifacts/release-notes/generate_<version>.py\`: | ||
|
|
||
| \`\`\`python | ||
| #!/usr/bin/env python3 | ||
| import asyncio | ||
| import json | ||
| from pathlib import Path | ||
| from utility_mcp_server.src.tools.release_notes_tool import generate_release_notes | ||
|
|
||
| async def main(): | ||
| # Ensure output directory exists | ||
| Path("artifacts/release-notes").mkdir(parents=True, exist_ok=True) | ||
|
|
||
| # Generate release notes | ||
| result = await generate_release_notes( | ||
| version="<VERSION>", | ||
| previous_version="<PREVIOUS_VERSION>", | ||
| repo_path="<REPO_PATH>", | ||
| repo_url="<REPO_URL>", | ||
| release_date=None # Uses today's date | ||
| ) | ||
|
|
||
| if result.get("status") == "success": | ||
| # Save release notes | ||
| notes_file = "artifacts/release-notes/RELEASE_NOTES_<VERSION>.md" | ||
| with open(notes_file, "w") as f: | ||
| f.write(result["release_notes"]) | ||
| print(f"β Release notes saved to: {notes_file}") | ||
|
|
||
| # Save statistics | ||
| if "statistics" in result: | ||
| stats_file = "artifacts/release-notes/stats_<VERSION>.json" | ||
| with open(stats_file, "w") as f: | ||
| json.dump(result["statistics"], f, indent=2) | ||
| print(f"β Statistics saved to: {stats_file}") | ||
|
|
||
| # Display release notes | ||
| print("\n" + "="*80) | ||
| print(result["release_notes"]) | ||
| print("="*80 + "\n") | ||
|
|
||
| # Display statistics | ||
| if "statistics" in result: | ||
| print("π Statistics:") | ||
| for key, value in result["statistics"].items(): | ||
| print(f" {key}: {value}") | ||
|
|
||
| return result | ||
| else: | ||
| error_msg = result.get("error", "Unknown error") | ||
| print(f"β Error: {error_msg}") | ||
| return result | ||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) | ||
| \`\`\` | ||
|
|
||
| ### 5. Execute | ||
|
|
||
| \`\`\`bash | ||
| cd artifacts/release-notes && python3 generate_<version>.py | ||
| \`\`\` | ||
|
|
||
| ### 6. Present Results | ||
|
|
||
| Show the user: | ||
| 1. Generated release notes (formatted) | ||
| 2. Statistics summary | ||
| 3. File locations | ||
| 4. Next steps | ||
|
|
||
| ## Output | ||
|
|
||
| Files created in \`artifacts/release-notes/\`: | ||
| - \`RELEASE_NOTES_<version>.md\` - Main release notes | ||
| - \`stats_<version>.json\` - Statistics | ||
| - \`generate_<version>.py\` - Generation script | ||
|
|
||
| ## Error Handling | ||
|
|
||
| Handle gracefully: | ||
| - Tags don't exist β List available tags | ||
| - No commits β Explain possible causes | ||
| - Not a git repo β Verify path | ||
| - Installation fails β Check Python/pip | ||
|
|
||
| ## Tips | ||
|
|
||
| Suggest to users: | ||
| - Use conventional commits (\`feat:\`, \`fix:\`, etc.) | ||
| - Include PR numbers in commits | ||
| - Provide repository URL for links | ||
| - Tag releases consistently | ||
| EOF | ||
|
|
||
| # Commit it | ||
| git add .claude/commands/generate.md | ||
| git commit -m "feat: Add /generate command" | ||
| ``` | ||
|
|
||
| ## Verify | ||
|
|
||
| Check that the file was created: | ||
|
|
||
| ```bash | ||
| ls -la .claude/commands/ | ||
| cat .claude/commands/generate.md | ||
| ``` | ||
|
|
||
| ## Why is this file important? | ||
|
|
||
| The `/generate` command allows users to invoke the release notes generation with a slash command instead of just conversational mode. It's optional but provides a nice shortcut. | ||
|
|
||
| **Without it**: Workflow still works conversationally | ||
| **With it**: Users can type `/generate v1.0.0 v0.9.0` for quick invocation | ||
|
|
||
| ## Next Steps | ||
|
|
||
| Once you've added the command file: | ||
|
|
||
| 1. Commit all changes | ||
| 2. Push to GitHub | ||
| 3. Test with Custom Workflow in ACP | ||
| 4. Verify `/generate` command appears and works |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π§Ή Nitpick | π΅ Trivial
Clarify that placeholders must be replaced.
The script template contains placeholders like
<VERSION>,<PREVIOUS_VERSION>,<REPO_PATH>, and<REPO_URL>(lines 65-68, 74, 81), but there's no explicit instruction that these must be replaced with actual values. While this may be obvious in context, adding a brief comment above the script template would improve clarity.π Suggested documentation improvement
π Committable suggestion
π€ Prompt for AI Agents