blob: b569d44c8bc66dca82640cace6398db93f619b07 [file] [log] [blame]
#!/usr/bin/env python3
"""
Experimental changelog and release notes generation tool for Perfetto.
This script automates the process of generating release announcements by:
1. Extracting commit logs since the last release
2. Guiding the user through AI-assisted CHANGELOG updates
3. Generating a complete release announcement
Usage: python tools/release/gen_release_notes.py [--since-tag TAG] [--output-dir DIR]
"""
import argparse
import subprocess
import sys
from pathlib import Path
def get_git_commits_since_tag(since_tag=None):
"""Extract git commits since the specified tag or auto-detect the latest release tag."""
if not since_tag:
try:
result = subprocess.run(['git', 'tag', '--sort=-version:refname'],
capture_output=True,
text=True,
check=True)
tags = result.stdout.strip().split('\n')
release_tags = [tag for tag in tags if tag.startswith('v') and '.' in tag]
if not release_tags:
print("No release tags found. Please specify --since-tag manually.")
sys.exit(1)
since_tag = release_tags[0]
print(f"Auto-detected latest release tag: {since_tag}")
except subprocess.CalledProcessError:
print("Failed to get git tags. Make sure you're in a git repository.")
sys.exit(1)
try:
result = subprocess.run(['git', 'log', '--oneline', f'{since_tag}..HEAD'],
capture_output=True,
text=True,
check=True)
commits = result.stdout.strip()
if not commits:
print(f"No commits found since {since_tag}")
sys.exit(1)
return since_tag, commits
except subprocess.CalledProcessError:
print(f"Failed to get commits since {since_tag}. Make sure the tag exists.")
sys.exit(1)
def detect_current_version():
"""Detect current version tag or prompt user for it."""
try:
result = subprocess.run(
['git', 'describe', '--tags', '--exact-match', 'HEAD'],
capture_output=True,
text=True,
check=True)
current_version = result.stdout.strip()
print(f"Current version detected: {current_version}")
return current_version
except subprocess.CalledProcessError:
return input("Enter the current version tag (e.g., v52.0): ").strip()
def write_commits_to_file(commits, output_file):
"""Write the commit log to a file."""
with open(output_file, 'w') as f:
f.write(commits)
print(f"Commits written to: {output_file}")
def generate_changelog_update_prompt(commits_file):
"""Generate the prompt for AI to update the changelog."""
prompt = f"""# Changelog Update Prompt for Perfetto Release
Please analyze the commits and current CHANGELOG to generate an updated changelog that includes all unreleased changes.
## Input Files:
- Commit log: {commits_file}
- Current CHANGELOG: Use the Read tool to read the CHANGELOG file directly
## Instructions:
1. **Read both files carefully** - The commit log shows all changes since the last release, the CHANGELOG shows what's already documented
2. **Identify unreleased changes** that should be added to the CHANGELOG:
- Look for commits that represent user-facing changes
- Focus on new features, bug fixes, performance improvements, breaking changes
- Skip internal refactoring, CI changes, and minor code cleanup unless they have user impact
- Group related commits together logically
3. **Follow Perfetto's CHANGELOG format** (based on existing structure):
- Categories: "Tracing service and probes:", "SQL Standard library:", "Trace Processor:", "UI:", "SDK:", "Tools:", "Docs:"
- Use bullet points with asterisks (*)
- Each entry should be concise but descriptive
- Include technical details but keep accessible to users
- Use consistent indentation and formatting
4. **Add missing entries** from the unreleased commits:
- Compare commits against existing CHANGELOG entries
- Add any significant changes that are missing
- Maintain logical grouping within categories
- Ensure no duplicate entries
5. **Output format**:
- Provide the complete updated CHANGELOG content
- Keep the existing "Unreleased:" section and enhance it with missing changes
- Preserve all existing content below the unreleased section
- Follow the exact formatting style seen in the current CHANGELOG
## Important Notes:
- Focus on changes that affect end users, not internal development
- Maintain the established writing style and technical level
- Use the same terminology and phrasing patterns as existing entries
- Group related commits into single changelog entries where appropriate
- Preserve existing formatting and structure exactly
## Expected Output:
Use the Edit tool to update the CHANGELOG file directly at: CHANGELOG
Update the existing "Unreleased:" section with any missing changes from the commits, maintaining the exact same format and structure as the existing file.
"""
return prompt
def generate_release_notes_prompt(commits_file, since_tag, current_version):
"""Generate the prompt for AI release notes generation."""
github_compare_url = f"https://github.com/google/perfetto/compare/{since_tag}...{current_version}"
github_changelog_url = f"https://github.com/google/perfetto/blob/{current_version}/CHANGELOG"
prompt = f"""You are a technical release notes writer for Perfetto, a performance analysis and tracing platform. Your task is to transform raw changelog entries into engaging, well-structured release notes.
## Example Input (Raw Changelog):
```
Unreleased:
Tracing service and probes:
* Added support for exclusive single-tenant features in ftrace data source.
These features can only be used by a single tracing session.
* Added support for tracing_cpumask, tracefs options and ftrace filtering
by TID as exclusive features.
* Added support for polling Adreno GPU frequency in SysStatsDataSource.
* Deprecated: "resolve_process_fds" option in "linux.process_stats" data
source. Asynchronous scraping is too unreliable and there are no known
maintainers or users.
SQL Standard library:
* Added new power analysis capabilities with expanded Wattson device support
and IRQ power attribution for more accurate power profiling.
* Added suspend-aware CPU utilization metrics for better analysis of
power-managed systems.
* Added anr_type column to android_anrs table for improved ANR debugging.
* Added `android.bitmaps` module with timeseries information about bitmap
usage in Android.
Trace Processor:
* Significantly improved performance with optimized data structures and
MurmurHash implementation, resulting in faster trace loading and query
execution.
* Added slice_self_dur table for more efficient self-duration calculations.
* Added regexp_extract function for improved string processing in queries.
* Added support for `sibling_merge_behavior` and `sibling_merge_key` in
`TrackDescriptor` for TrackEvent, allowing for finer-grained control over
how tracks are merged.
UI:
* Added comprehensive dark mode support with theme-aware colors throughout
the interface.
* Introduced bulk track settings management allowing users to configure
multiple tracks simultaneously.
* Added startup commands feature for automated trace analysis workflows.
* Fixed numerous crashes and performance issues, including flamegraph
crashes and selection performance problems.
```
## Example Output (Polished Release Notes):
# Perfetto v52.0 Release Notes
We're excited to announce Perfetto v52.0, packed with significant improvements to the user experience, performance analysis capabilities, and recording infrastructure.
## 🌙 Comprehensive Dark Mode Support
The Perfetto UI now features a complete dark mode implementation with theme-aware colors throughout the entire interface. This long-requested feature makes it comfortable to analyze traces in low-light environments and provides a modern, professional appearance that many developers prefer.
## 🎛️ Advanced TrackEvent Control & Visualization
SDK users and developers converting external traces to Perfetto format now have fine-grained control over track display and merging behavior. The new `sibling_merge_behavior` and `sibling_merge_key` options in `TrackDescriptor` allow you to:
- Force tracks with the same name to be displayed separately
- Merge tracks with different names into a single UI track
- Override the default name-based merging logic
Additionally, counter tracks can now share Y-axis ranges using the `y_axis_share_key` in `CounterDescriptor`, making it easier to compare related metrics with the same units.
Learn more about [converting custom data to Perfetto format](https://perfetto.dev/docs/getting-started/converting) and [advanced synthetic track event configuration](https://perfetto.dev/docs/reference/synthetic-track-event).
## ⚡ Trace Processor Performance & New Features
This release delivers significant performance improvements and new analysis capabilities:
- **Faster trace loading**: Optimized data structures and MurmurHash implementation result in noticeably faster trace loading and query execution
- **New analysis tools**: The `slice_self_dur` table provides efficient self-duration calculations, while the `regexp_extract` function enhances string processing in SQL queries
## 📱 Enhanced Android Analysis Capabilities
Android developers gain powerful new debugging and performance analysis tools:
- **Better ANR debugging**: The `anr_type` column in the android_anrs table provides more detailed ANR classification
- **Bitmap tracking**: New `android.bitmaps` module offers timeseries information about bitmap usage
## 🔧 Additional Improvements
- Fixed numerous crashes and performance issues throughout the UI
- Enhanced support for polling Adreno GPU frequency data
---
For complete details, see the [changelog]({github_changelog_url}) or [view all changes on GitHub]({github_compare_url}). Download Perfetto v52.0 from our [releases page](https://github.com/google/perfetto/releases), get started at [docs.perfetto.dev](https://docs.perfetto.dev), or try the UI directly at [ui.perfetto.dev](https://ui.perfetto.dev).
## Instructions:
1. Follow the exact structure, tone, and formatting of the example output above
2. Transform technical changelog entries into user-focused benefits
3. Group related features into thematic sections with emoji headers
4. Use enthusiastic but professional language
5. Include code formatting for technical terms (backticks)
6. Add "Learn more" placeholder links for complex features
7. Bold key feature names in bullet points
8. End with the standard closing paragraph (adapt version number)
9. Focus on what users can DO with the new features, not just what was added
## Input Files:
- Commit log: {commits_file}
- Updated CHANGELOG: Use the Read tool to read the CHANGELOG file directly
## Auto-Generated Links (use these exact URLs):
- **Changelog**: {github_changelog_url}
- **Full changes**: {github_compare_url}
- **Documentation**: https://perfetto.dev/docs/ (primary documentation site)
- **UI only**: https://ui.perfetto.dev
- **Releases**: https://github.com/google/perfetto/releases
Transform the provided changelog into release notes matching this style and structure exactly."""
return prompt
def main():
parser = argparse.ArgumentParser(
description='Generate Perfetto release notes')
parser.add_argument(
'--since-tag',
help='Git tag to start from (auto-detects latest if not specified)')
parser.add_argument(
'--output-dir',
default='/tmp',
help='Directory to write output files (default: /tmp)')
args = parser.parse_args()
if not Path('.git').exists():
print("This script must be run from the root of a git repository.")
sys.exit(1)
output_dir = Path(args.output_dir)
output_dir.mkdir(exist_ok=True)
print("=== Perfetto Release Notes Generator ===\n")
print("Step 1: Extracting commits since last release...")
since_tag, commits = get_git_commits_since_tag(args.since_tag)
current_version = detect_current_version()
commits_file = output_dir / f'commits_since_{since_tag}.txt'
write_commits_to_file(commits, commits_file)
print("\nStep 2: Generating changelog update prompt...")
changelog_update_prompt = generate_changelog_update_prompt(commits_file)
changelog_update_prompt_file = output_dir / 'changelog_update_prompt.txt'
with open(changelog_update_prompt_file, 'w') as f:
f.write(changelog_update_prompt)
print(f"Changelog update prompt written to: {changelog_update_prompt_file}")
print("\n" + "=" * 60)
print("NEXT STEP: Changelog Update")
print("=" * 60)
print(f"1. Copy the prompt from: {changelog_update_prompt_file}")
print(f"2. Provide it to an AI along with the commit file: {commits_file}")
print("3. The AI will read CHANGELOG directly and update it in place")
print("4. Return here and press Enter when the CHANGELOG has been updated...")
input("\nPress Enter when the CHANGELOG has been updated...")
print("\nStep 3: Generating release notes prompt...")
release_notes_prompt = generate_release_notes_prompt(commits_file, since_tag,
current_version)
release_notes_prompt_file = output_dir / 'release_notes_prompt.txt'
with open(release_notes_prompt_file, 'w') as f:
f.write(release_notes_prompt)
print(f"Release notes prompt written to: {release_notes_prompt_file}")
print("\n" + "=" * 60)
print("FINAL STEP: Generate Release Notes")
print("=" * 60)
print(f"1. Copy the prompt from: {release_notes_prompt_file}")
print(
f"2. In a NEW AI conversation, provide the prompt along with: {commits_file}"
)
print("3. The AI will generate publication-ready release notes!")
print("\n" + "=" * 60)
print("Release notes generation ready!")
print("=" * 60)
if __name__ == '__main__':
main()