mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
9.4 KiB
276 lines
9.4 KiB
#!/usr/bin/env python3
|
|
"""
|
|
Orchestrate release notes generation workflow.
|
|
|
|
This script runs all required steps to prepare data for LLM analysis,
|
|
then generates a comprehensive prompt for the LLM to create release notes
|
|
and changelogs.
|
|
|
|
Workflow:
|
|
1. Collect PR data from GitHub
|
|
2. Generate structured commit data
|
|
3. Create analysis files
|
|
4. Generate LLM prompt with instructions
|
|
"""
|
|
|
|
import subprocess
|
|
import json
|
|
import argparse
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
|
|
def run_cmd(cmd_list, verbose=False):
|
|
"""Run command and return output."""
|
|
if verbose:
|
|
print(f"Running: {' '.join(cmd_list)}")
|
|
try:
|
|
result = subprocess.run(cmd_list, capture_output=True, text=True, check=True)
|
|
return result.stdout.strip()
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error running command: {' '.join(cmd_list)}", file=sys.stderr)
|
|
print(f"Error output: {e.stderr}", file=sys.stderr)
|
|
return None
|
|
except Exception as e:
|
|
print(f"Exception running command {' '.join(cmd_list)}: {e}", file=sys.stderr)
|
|
return None
|
|
|
|
|
|
def generate_llm_prompt(from_tag, to_tag, data_files, output_dir, verbose=False):
|
|
"""Generate comprehensive prompt for LLM."""
|
|
|
|
# Read some data to include in prompt
|
|
pr_summary = ""
|
|
try:
|
|
with open(data_files['pr_summary'], 'r') as f:
|
|
pr_summary = f.read()[:2000] # First 2000 chars
|
|
except:
|
|
pass
|
|
|
|
prompt = f"""
|
|
# ProxySQL Release Notes Generation Task
|
|
|
|
## Context
|
|
You need to generate release notes and changelogs for ProxySQL version {to_tag} (changes since {from_tag}).
|
|
|
|
## Available Data Files
|
|
The following files have been prepared for your analysis:
|
|
|
|
1. **PR Data**: `{data_files['pr_data']}` - JSON with all PR details (titles, descriptions, labels, commits)
|
|
2. **PR Summary**: `{data_files['pr_summary']}` - Markdown summary of all PRs
|
|
3. **Structured Notes**: `{data_files['structured_notes']}` - Commit-level organized data
|
|
4. **Commit Categorization**: `{data_files['commit_categories']}` - Commits categorized by type
|
|
|
|
## Task Requirements
|
|
|
|
### 1. Generate Release Notes (like ProxySQL v3.0.3 format)
|
|
- **Descriptive content**: Not just PR titles, but explanations of what each feature/fix does and why it matters
|
|
- **Logical grouping**: Organize under categories like:
|
|
- PostgreSQL Improvements
|
|
- MySQL Protocol Enhancements
|
|
- Monitoring & Diagnostics
|
|
- Bug Fixes (with subcategories: MySQL, PostgreSQL, Monitoring, Security)
|
|
- Performance Optimizations
|
|
- Documentation
|
|
- Testing
|
|
- Build/Packaging
|
|
- Other Changes
|
|
- **Backtick formatting**: Use `backticks` around all technical terms:
|
|
- Function names: `Read_Global_Variables_from_configfile()`
|
|
- Variable names: `wait_timeout`, `cur_cmd_cmnt`
|
|
- SQL queries: `SELECT @@version`, `SELECT VERSION()`
|
|
- Protocol commands: `COM_PING`, `CLIENT_DEPRECATE_EOF`
|
|
- Configuration options: `cache_empty_result=0`
|
|
- Metrics: `PgSQL_Monitor_ssl_connections_OK`
|
|
- **Commit references**: Include relevant commit hashes (short form) and PR numbers
|
|
- **Remove WIP/skip-ci tags**: Make all entries production-ready
|
|
- **Include release hash**: The final commit is `faa64a570d19fe35af43494db0babdee3e3cdc89`
|
|
|
|
### 2. Generate Detailed Changelog
|
|
- List all changes with commit hashes and PR references
|
|
- Include brief descriptions from commit messages
|
|
- Categorize changes for easy reference
|
|
|
|
### 3. Generate Commit List (optional)
|
|
- Complete list of all commits since {from_tag}
|
|
|
|
## Example Structure (from ProxySQL 3.0.3)
|
|
```
|
|
# ProxySQL 3.0.3 Release Notes
|
|
|
|
This release of ProxySQL 3.0.3 includes a significant number of new features...
|
|
|
|
## New Features:
|
|
|
|
### PostgreSQL Extended Query Protocol Support:
|
|
- Add PostgreSQL extended query (prepared statement) support (24fecc1f, #5044)
|
|
- Lays groundwork for handling PostgreSQL extended query protocol...
|
|
- Added `Describe` message handling (a741598a, #5044)
|
|
- Added `Close` statement handling (4d0618c2, #5044)
|
|
|
|
### Build System & Dependencies:
|
|
- Upgrade `coredumper` to Percona fork hash `8f2623b` (a315f128, #5171)
|
|
- Upgrade `curl` to v8.16.0 (40414de1, #5154)
|
|
```
|
|
|
|
## Your Output Should Be:
|
|
1. **`ProxySQL-{to_tag}-Release-Notes.md`** - Main release notes
|
|
2. **`CHANGELOG-{to_tag}-detailed.md`** - Detailed changelog
|
|
3. **`CHANGELOG-{to_tag}-commits.md`** - Complete commit list (optional)
|
|
|
|
## Analysis Approach
|
|
1. Review the PR data to understand scope and significance of changes
|
|
2. Identify major themes and group related changes
|
|
3. Write descriptive explanations, not just copy titles
|
|
4. Apply backtick formatting consistently
|
|
5. Verify all technical terms are properly formatted
|
|
|
|
## Available Data Preview
|
|
{pr_summary[:500]}...
|
|
"""
|
|
|
|
prompt_file = os.path.join(output_dir, f"llm-prompt-{to_tag}.md")
|
|
with open(prompt_file, 'w') as f:
|
|
f.write(prompt)
|
|
|
|
if verbose:
|
|
print(f"LLM prompt written to {prompt_file}")
|
|
|
|
return prompt_file
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Orchestrate release notes generation workflow.',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Examples:
|
|
%(prog)s --from-tag v3.0.3 --to-tag v3.0.4 --output-dir release-data
|
|
%(prog)s --from-tag v3.0.3 --to-tag v3.0.4 --verbose
|
|
"""
|
|
)
|
|
parser.add_argument('--from-tag', required=True, help='Starting tag/branch')
|
|
parser.add_argument('--to-tag', required=True, help='Ending tag/branch')
|
|
parser.add_argument('--output-dir', default='release-data', help='Output directory for data files')
|
|
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Create output directory
|
|
output_dir = Path(args.output_dir)
|
|
output_dir.mkdir(exist_ok=True)
|
|
|
|
if args.verbose:
|
|
print(f"Starting release notes workflow for {args.from_tag} to {args.to_tag}")
|
|
print(f"Output directory: {output_dir}")
|
|
|
|
data_files = {}
|
|
|
|
# Step 1: Collect PR data
|
|
if args.verbose:
|
|
print("\n1. Collecting PR data...")
|
|
|
|
pr_data_file = output_dir / f"pr-data-{args.to_tag}.json"
|
|
pr_summary_file = output_dir / f"pr-summary-{args.to_tag}.md"
|
|
|
|
cmd_list = ["python", str(Path(__file__).parent / "collect_pr_data.py"), "--from-tag", args.from_tag, "--to-tag", args.to_tag, "--output", str(pr_data_file)]
|
|
if args.verbose:
|
|
cmd_list.append("--verbose")
|
|
|
|
result = run_cmd(cmd_list, args.verbose)
|
|
if result is None:
|
|
print("Failed to collect PR data", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
data_files['pr_data'] = str(pr_data_file)
|
|
data_files['pr_summary'] = str(pr_summary_file)
|
|
|
|
# Step 2: Generate structured notes
|
|
if args.verbose:
|
|
print("\n2. Generating structured notes...")
|
|
|
|
structured_file = output_dir / f"structured-notes-{args.to_tag}.md"
|
|
cmd_list = ["python", str(Path(__file__).parent / "generate_structured_notes.py"), "--input", str(pr_data_file), "--output", str(structured_file)]
|
|
if args.verbose:
|
|
cmd_list.append("--verbose")
|
|
|
|
result = run_cmd(cmd_list, args.verbose)
|
|
if result is None:
|
|
print("Failed to generate structured notes", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
data_files['structured_notes'] = str(structured_file)
|
|
|
|
# Step 3: Categorize commits
|
|
if args.verbose:
|
|
print("\n3. Categorizing commits...")
|
|
|
|
commit_cat_file = output_dir / f"commit-categories-{args.to_tag}.md"
|
|
cmd_list = ["python", str(Path(__file__).parent / "categorize_commits.py"), "--from-tag", args.from_tag, "--to-tag", args.to_tag, "--output-format", "markdown"]
|
|
result = run_cmd(cmd_list, args.verbose)
|
|
if result is not None:
|
|
with open(commit_cat_file, 'w') as f:
|
|
f.write(result)
|
|
if result is None:
|
|
print("Failed to categorize commits", file=sys.stderr)
|
|
|
|
data_files['commit_categories'] = str(commit_cat_file)
|
|
|
|
# Step 4: Generate LLM prompt
|
|
if args.verbose:
|
|
print("\n4. Generating LLM prompt...")
|
|
|
|
prompt_file = generate_llm_prompt(
|
|
args.from_tag,
|
|
args.to_tag,
|
|
data_files,
|
|
output_dir,
|
|
args.verbose
|
|
)
|
|
|
|
# Step 5: Create workflow summary
|
|
summary = f"""
|
|
# Release Notes Workflow Summary
|
|
|
|
## Generated Files
|
|
- PR Data: {data_files['pr_data']}
|
|
- PR Summary: {data_files['pr_summary']}
|
|
- Structured Notes: {data_files['structured_notes']}
|
|
- Commit Categories: {data_files.get('commit_categories', 'N/A')}
|
|
- LLM Prompt: {prompt_file}
|
|
|
|
## Next Steps
|
|
1. Review the generated files in {output_dir}
|
|
2. Use the LLM prompt to generate release notes
|
|
3. The LLM should create:
|
|
- `ProxySQL-{args.to_tag}-Release-Notes.md`
|
|
- `CHANGELOG-{args.to_tag}-detailed.md`
|
|
- `CHANGELOG-{args.to_tag}-commits.md` (optional)
|
|
|
|
## LLM Instructions
|
|
Provide the LLM with:
|
|
1. Access to all files in {output_dir}
|
|
2. The prompt: {prompt_file}
|
|
3. Instructions to write descriptive release notes with backtick formatting
|
|
|
|
## Verification Checklist
|
|
- [ ] All technical terms have backticks
|
|
- [ ] No WIP/skip-ci tags remain
|
|
- [ ] Changes are grouped logically
|
|
- [ ] Descriptions explain what/why, not just copy titles
|
|
- [ ] Commit hashes and PR numbers are referenced
|
|
"""
|
|
|
|
summary_file = output_dir / "workflow-summary.md"
|
|
with open(summary_file, 'w') as f:
|
|
f.write(summary)
|
|
|
|
if args.verbose:
|
|
print(f"\nWorkflow summary written to {summary_file}")
|
|
print("\n✅ Workflow completed!")
|
|
print(f"\nNext: Provide the LLM with files in {output_dir} and prompt: {prompt_file}")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |