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.
proxysql/scripts/release-tools/orchestrate_release.py

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()