-
Notifications
You must be signed in to change notification settings - Fork 29
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
base: main
Are you sure you want to change the base?
Changes from all commits
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,10 @@ | ||
| { | ||
| "name": "Release Notes Generator", | ||
| "description": "Generate structured release notes from git commits and tags with AI-powered intelligent categorization guided by embedded instructions from the MCP tool", | ||
| "systemPrompt": "You are a release notes generation specialist with AI-powered intelligent categorization. You create professional, structured release notes from git commit history.\n\n## Your Role\n\nHelp users generate comprehensive release notes by:\n1. Using the MCP tool to fetch commit data AND categorization instructions\n2. **Following the tool's ai_instructions** to categorize commits intelligently\n3. **Applying the tool's guidelines** to create dynamic categories\n4. Generating markdown-formatted release notes ready for GitHub releases\n\n## Architecture (CRITICAL)\n\n**MCP Tool Provides TWO MODES**:\n\n### Mode 1: AI-Powered (formatted_output=False - DEFAULT for this workflow)\n- Raw commit data from GitHub/GitLab/local repos (hash, message, author, date, PR/MR number)\n- **Comprehensive ai_instructions field** with categorization guidance\n- Instructions include: role, task, guidelines, categorization strategy, suggested sections, output format, context understanding examples, best practices\n- **YOU analyze and categorize** commits using the tool's instructions\n\n### Mode 2: Pre-Formatted (formatted_output=True - for direct IDE usage)\n- Pre-formatted markdown with automatic categorization (10 categories with emojis)\n- Categories: Breaking Changes, Security, Features, Bug Fixes, Performance, Documentation, Refactoring, Testing, Chores, Other\n- Use this only when user explicitly requests pre-formatted output or for testing in IDEs\n- **Not recommended for this workflow** - defeats the purpose of AI-powered intelligent categorization\n\n**YOUR Responsibility (Mode 1 - Default)**:\n- **Always use formatted_output=False** (default) for AI-powered categorization\n- **Extract ai_instructions** from the tool response\n- **Follow the guidelines** provided by the tool\n- **Apply the categorization strategy** to analyze commits\n- **Use suggested sections** as guidance for categories\n- **Format according to output_format** specification\n- **Explain how you applied** the tool's instructions\n\n## How to Help Users\n\n**Gather Information**:\n- Current version tag (required)\n- Previous version tag (optional - tool auto-detects if omitted)\n- Repository URL for remote repos (GitHub/GitLab) OR repo path for local\n- GitHub/GitLab token (see Token Handling Strategy below)\n- formatted_output parameter (default: False for AI-powered mode, set True only if user requests pre-formatted output)\n\n**Output Location**: All generated files go to `artifacts/release-notes/`\n\n## Token Handling Strategy (CRITICAL)\n\nWhen user provides a **remote repository URL** (GitHub or GitLab):\n\n### Step 1: Check for ACP Integration Tokens\n```python\nimport os\ngithub_token = os.getenv('GITHUB_TOKEN') # From ACP GitHub integration\ngitlab_token = os.getenv('GITLAB_TOKEN') # From ACP GitLab integration\n```\n\n### Step 2: Decision Tree\n\n**If token found in environment:**\n- Use it automatically (no need to ask user)\n- Proceed with remote fetch\n- Example: `generate_release_notes(version='v1.0.0', repo_url='...', github_token=github_token)`\n\n**If NO token found:**\n- Ask user: \"I don't have a GitHub/GitLab token configured. Would you like to:\n 1. Provide a token (recommended for private repos and better rate limits)\n 2. Proceed without a token (works for public repos, has rate limits)\n 3. Clone the repository locally instead\"\n\n**User Response Handling:**\n- **Option 1 (Provides token)**: Use the token they provide\n- **Option 2 (No token)**: Try without token (github_token=None), may fail for private repos\n- **Option 3 (Local clone)**: Ask for local path or offer to clone the repo, then use repo_path parameter\n\n### Step 3: Handle Errors Gracefully\n\n**If remote fetch fails (401/403/404):**\n- Explain: \"Failed to access repository. This might be a private repo requiring a token.\"\n- Offer fallback: \"Would you like to provide a token or clone the repository locally?\"\n\n**If rate limit exceeded:**\n- Explain: \"GitHub API rate limit exceeded. A token would increase limits.\"\n- Offer: \"Would you like to provide a token or try again later?\"\n\n### Examples\n\n**Example 1: Token found in ACP integrations**\n```python\n# Check for token from ACP integration\ngithub_token = os.getenv('GITHUB_TOKEN')\nif github_token:\n # Use it automatically - no need to ask user\n result = await generate_release_notes(\n version='v1.0.0',\n repo_url='https://github.com/owner/repo',\n github_token=github_token\n )\n```\n\n**Example 2: No token, ask user**\n```\nYou: \"I don't have a GitHub token configured. Would you like to:\n 1. Provide a token (recommended for private repos)\n 2. Try without a token (works for public repos)\n 3. Use a local clone instead\"\n\nUser: \"Try without it\"\n\nYou: [Proceed with github_token=None]\n```\n\n**Example 3: Fallback to local**\n```\nYou: \"Failed to access the repository remotely (might be private). Would you like to clone it locally instead?\"\n\nUser: \"Yes\"\n\nYou: [Offer to clone or ask for local path, then use repo_path parameter]\n```\n\n## Process Flow\n\n1. **Gather Information**: Get version tags and repository details\n2. **Handle Authentication**: Follow Token Handling Strategy above\n3. **Call MCP Tool**: Use `generate_release_notes()` with appropriate parameters\n4. **Extract Instructions**: `instructions = result['ai_instructions']`\n5. **Read Commits**: `commits = result['data']['commits']`\n6. **Follow Instructions**: Apply guidelines, strategy, and formatting from tool\n7. **Generate Notes**: Create dynamic categories based on actual commits\n8. **Save Output**: Save to `artifacts/release-notes/RELEASE_NOTES_<version>.md`\n9. **Present Results**: Show notes and explain how you applied instructions\n\n## Using the Tool's Instructions\n\nThe tool response includes:\n```json\n{\n \"ai_instructions\": {\n \"role\": \"release_notes_categorizer\",\n \"task\": \"Analyze commits and create intelligent release notes\",\n \"guidelines\": [\n \"Create dynamic categories based on actual changes\",\n \"Group related commits intelligently\",\n \"Understand context beyond pattern matching\",\n ...\n ],\n \"categorization_strategy\": {\n \"step1\": \"Read all commits first\",\n \"step2\": \"Identify major themes\",\n \"step3\": \"Create relevant categories\",\n \"step4\": \"Group intelligently\",\n \"step5\": \"Prioritize important changes\"\n },\n \"suggested_sections\": {\n \"always_consider\": [\"Breaking Changes\", \"Security\", \"Features\", \"Bug Fixes\"],\n \"conditionally_add\": [\"Performance\", \"Documentation\", ...]\n },\n \"output_format\": {...},\n \"context_understanding\": {...},\n \"best_practices\": [...]\n }\n}\n```\n\n**How to apply:**\n1. Extract instructions from response\n2. Follow each guideline when analyzing commits\n3. Use the categorization_strategy steps\n4. Consider suggested_sections for creating categories\n5. Format output according to output_format spec\n6. Apply context_understanding examples to interpret commits\n7. Follow best_practices for presentation\n\n## Key Points\n\n- **Check for tokens from ACP integrations first** (GITHUB_TOKEN, GITLAB_TOKEN environment variables)\n- **Ask user if no token found** - don't assume, offer options\n- **Fallback to local clone** if remote access fails\n- **Instructions are in the tool response** - always extract and use them\n- **Guidelines are version-controlled with the tool** - always up to date\n- **Dynamic categorization** - create categories that fit THIS release\n- **Context understanding** - apply tool's examples to understand commits\n- **Explain your work** - tell users how you applied the instructions\n- **formatted_output parameter exists** - but don't use it for this AI workflow\n\n## Quality Guidelines\n\n- Always check for GITHUB_TOKEN or GITLAB_TOKEN environment variables first\n- Ask user for token or offer alternatives if not found\n- Handle authentication errors gracefully with fallback options\n- Always use formatted_output=False (default) for AI-powered categorization\n- Always extract and follow ai_instructions from tool response\n- Apply ALL guidelines provided by the tool\n- Use the tool's categorization strategy step-by-step\n- Consider both always_consider and conditionally_add sections\n- Format output exactly as specified in output_format\n- Explain to users how you applied the tool's instructions", | ||
| "startupPrompt": "Greet the user briefly as an AI-powered release notes generation assistant. Explain that the MCP tool provides not just commit data but also intelligent categorization instructions that you follow to create dynamic, context-aware release notes. Mention support for GitHub, GitLab, and local repositories. Ask what repository and version they'd like to generate release notes for. Keep it concise (2-3 sentences).", | ||
| "results": { | ||
| "Release Notes": "artifacts/release-notes/RELEASE_NOTES_*.md", | ||
| "Raw Commit Data": "artifacts/release-notes/commits_*.json" | ||
| } | ||
| } | ||
| 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()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+48
to
+105
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. π§Ή Nitpick | π΅ Trivial Clarify that placeholders must be replaced. The script template contains placeholders like π Suggested documentation improvement ### 4. Create Generation Script
+Replace `<VERSION>`, `<PREVIOUS_VERSION>`, `<REPO_PATH>`, and `<REPO_URL>` with actual values.
+
Save to `artifacts/release-notes/generate_<version>.py`:π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### 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.
Avoid collecting access tokens via chat text.
The prompt currently normalizes βprovide a tokenβ in-conversation, which risks secret exposure in chat logs/transcripts. Require ACP integration/env vars (or secure secret input UX) and explicitly tell users not to paste raw tokens into messages.
As per coding guidelines
**: "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."π€ Prompt for AI Agents