File: gen_release_notes.py

package info (click to toggle)
perfetto 54.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 133,812 kB
  • sloc: cpp: 338,350; python: 74,464; sql: 46,895; ansic: 18,340; javascript: 2,557; java: 2,160; sh: 1,444; yacc: 776; xml: 563; makefile: 226
file content (322 lines) | stat: -rwxr-xr-x 14,114 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#!/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()