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.
225 lines
7.2 KiB
225 lines
7.2 KiB
#!/usr/bin/env python3
|
|
import subprocess
|
|
import re
|
|
import json
|
|
|
|
def run(cmd_list):
|
|
return subprocess.check_output(cmd_list, text=True).strip()
|
|
|
|
# Get merge commits since v3.0.3
|
|
merge_log = run(["git", "log", "v3.0.3..v3.0", "--merges", "--pretty=format:%H %s"])
|
|
lines = merge_log.split('\n')
|
|
pr_map = []
|
|
for line in lines:
|
|
if 'Merge pull request' in line:
|
|
hash_, subject = line.split(' ', 1)
|
|
match = re.search(r'#(\d+)', subject)
|
|
if match:
|
|
pr_num = match.group(1)
|
|
# get second parent commit hash
|
|
try:
|
|
second_parent = run(["git", "rev-parse", f"{hash_}^2"])
|
|
except subprocess.CalledProcessError:
|
|
second_parent = hash_
|
|
pr_map.append((pr_num, hash_, second_parent, subject))
|
|
|
|
print(f'Processed {len(pr_map)} PRs')
|
|
|
|
# Fetch PR details using gh
|
|
pr_details = {}
|
|
for pr_num, merge_hash, head_hash, subject in pr_map:
|
|
try:
|
|
data = run(["gh", "pr", "view", str(pr_num), "--json", "title,body,number,url"])
|
|
pr = json.loads(data)
|
|
pr['merge_hash'] = merge_hash
|
|
pr['head_hash'] = head_hash
|
|
pr_details[pr_num] = pr
|
|
except subprocess.CalledProcessError as e:
|
|
print(f'Failed to fetch PR {pr_num}: {e}')
|
|
continue
|
|
|
|
# Manual categorization based on PR title and analysis
|
|
categories = {
|
|
'New Features': {
|
|
'PostgreSQL': [],
|
|
'MySQL': [],
|
|
'Monitoring': [],
|
|
'Configuration': [],
|
|
'Performance': [],
|
|
'Other': [],
|
|
},
|
|
'Bug Fixes': {
|
|
'MySQL': [],
|
|
'PostgreSQL': [],
|
|
'Monitoring': [],
|
|
'Configuration': [],
|
|
'Security': [],
|
|
'Other': [],
|
|
},
|
|
'Improvements': {
|
|
'Performance': [],
|
|
'Refactoring': [],
|
|
'Monitoring': [],
|
|
'Other': [],
|
|
},
|
|
'Documentation': [],
|
|
'Testing': [],
|
|
'Build/Packaging': [],
|
|
'Other': [],
|
|
}
|
|
|
|
# Mapping PR numbers to categories (manually curated)
|
|
category_map = {
|
|
'5259': ('Bug Fixes', 'MySQL'),
|
|
'5257': ('New Features', 'MySQL'),
|
|
'5258': ('Documentation', None),
|
|
'5254': ('New Features', 'PostgreSQL'),
|
|
'5237': ('New Features', 'PostgreSQL'),
|
|
'5250': ('Bug Fixes', 'MySQL'),
|
|
'5251': ('Testing', None),
|
|
'4889': ('New Features', 'MySQL'),
|
|
'5247': ('Bug Fixes', 'Configuration'),
|
|
'5245': ('Documentation', None),
|
|
'4901': ('New Features', 'MySQL'),
|
|
'5199': ('Bug Fixes', 'Monitoring'),
|
|
'5241': ('Testing', None),
|
|
'5232': ('Bug Fixes', 'MySQL'),
|
|
'5240': ('Improvements', 'Performance'),
|
|
'5225': ('Improvements', 'Performance'),
|
|
'5230': ('Build/Packaging', None),
|
|
'5115': ('Documentation', None),
|
|
'5229': ('Documentation', None),
|
|
'5215': ('Documentation', None),
|
|
'5203': ('New Features', 'MySQL'),
|
|
'5207': ('Testing', None),
|
|
'5200': ('Other', None),
|
|
'5198': ('Testing', None),
|
|
'5228': ('New Features', 'Monitoring'),
|
|
'5226': ('Improvements', 'Performance'),
|
|
}
|
|
|
|
for pr_num, pr in pr_details.items():
|
|
if pr_num in category_map:
|
|
cat, subcat = category_map[pr_num]
|
|
if subcat:
|
|
categories[cat][subcat].append(pr)
|
|
else:
|
|
if isinstance(categories[cat], list):
|
|
categories[cat].append(pr)
|
|
else:
|
|
categories[cat]['Other'].append(pr)
|
|
else:
|
|
categories['Other'].append(pr)
|
|
|
|
# Generate release notes
|
|
out_lines = []
|
|
out_lines.append('# ProxySQL 3.0.4 Release Notes\n')
|
|
out_lines.append('\n')
|
|
out_lines.append('This release of ProxySQL 3.0.4 includes new features, bug fixes, and improvements across PostgreSQL, MySQL, monitoring, and configuration management.\n')
|
|
out_lines.append('\n')
|
|
out_lines.append(f'Release commit: {pr_map[0][1][:8]} (faa64a57)\n')
|
|
out_lines.append('\n')
|
|
|
|
# Helper to format entry
|
|
def format_entry(pr):
|
|
head_short = pr['head_hash'][:8]
|
|
title = pr['title']
|
|
url = pr['url']
|
|
return f'- {title} ({head_short}, #{pr["number"]})\n'
|
|
|
|
# New Features
|
|
if any(any(subcat) for subcat in categories['New Features'].values()):
|
|
out_lines.append('## New Features:\n')
|
|
for subcat in ['PostgreSQL', 'MySQL', 'Monitoring', 'Configuration', 'Performance', 'Other']:
|
|
entries = categories['New Features'][subcat]
|
|
if entries:
|
|
out_lines.append(f'### {subcat}:\n')
|
|
for pr in entries:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Bug Fixes
|
|
if any(any(subcat) for subcat in categories['Bug Fixes'].values()):
|
|
out_lines.append('## Bug Fixes:\n')
|
|
for subcat in ['MySQL', 'PostgreSQL', 'Monitoring', 'Configuration', 'Security', 'Other']:
|
|
entries = categories['Bug Fixes'][subcat]
|
|
if entries:
|
|
out_lines.append(f'### {subcat}:\n')
|
|
for pr in entries:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Improvements
|
|
if any(any(subcat) for subcat in categories['Improvements'].values()):
|
|
out_lines.append('## Improvements:\n')
|
|
for subcat in ['Performance', 'Refactoring', 'Monitoring', 'Other']:
|
|
entries = categories['Improvements'][subcat]
|
|
if entries:
|
|
out_lines.append(f'### {subcat}:\n')
|
|
for pr in entries:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Documentation
|
|
if categories['Documentation']:
|
|
out_lines.append('## Documentation:\n')
|
|
for pr in categories['Documentation']:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Testing
|
|
if categories['Testing']:
|
|
out_lines.append('## Testing:\n')
|
|
for pr in categories['Testing']:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Build/Packaging
|
|
if categories['Build/Packaging']:
|
|
out_lines.append('## Build/Packaging:\n')
|
|
for pr in categories['Build/Packaging']:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
# Other (if any)
|
|
if categories['Other']:
|
|
out_lines.append('## Other Changes:\n')
|
|
for pr in categories['Other']:
|
|
out_lines.append(format_entry(pr))
|
|
out_lines.append('\n')
|
|
|
|
out_lines.append('\n')
|
|
out_lines.append('## Hashes\n')
|
|
out_lines.append('\n')
|
|
out_lines.append('The release commit is: `faa64a570d19fe35af43494db0babdee3e3cdc89`\n')
|
|
out_lines.append('\n')
|
|
|
|
with open('RELEASE_NOTES-3.0.4-formatted.md', 'w') as f:
|
|
f.writelines(out_lines)
|
|
|
|
print('Generated RELEASE_NOTES-3.0.4-formatted.md')
|
|
|
|
# Also generate a more detailed changelog with commit messages
|
|
detailed = []
|
|
detailed.append('# ProxySQL 3.0.4 Detailed Changelog\n')
|
|
detailed.append('\n')
|
|
detailed.append('This changelog includes all individual commits since ProxySQL 3.0.3.\n')
|
|
detailed.append('\n')
|
|
|
|
# Get all non-merge commits
|
|
commits = run(["git", "log", "v3.0.3..v3.0", "--no-merges", "--pretty=format:%H|%s|%b"]).split('\n')
|
|
for line in commits:
|
|
parts = line.split('|', 2)
|
|
if len(parts) < 2:
|
|
continue
|
|
hash_, subject, body = parts[0], parts[1], parts[2] if len(parts) > 2 else ''
|
|
detailed.append(f'- {hash_[:8]} {subject}\n')
|
|
if body.strip():
|
|
for bline in body.strip().split('\n'):
|
|
if bline.strip():
|
|
detailed.append(f' {bline.strip()}\n')
|
|
|
|
with open('CHANGELOG-3.0.4-commits.md', 'w') as f:
|
|
f.writelines(detailed)
|
|
|
|
print('Generated CHANGELOG-3.0.4-commits.md') |