diff --git a/.agents/skills/adding-release-notes/SKILL.md b/.agents/skills/adding-release-notes/SKILL.md new file mode 100644 index 00000000000..c47b3e699b1 --- /dev/null +++ b/.agents/skills/adding-release-notes/SKILL.md @@ -0,0 +1,87 @@ +--- +name: adding-release-notes +description: Adds user-facing change descriptions to DevTools release notes. Use when documenting improvements, fixes, or new features in the NEXT_RELEASE_NOTES.md file. +--- + +# Adding Release Notes + +This skill helps automate adding release notes to `packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md`. + +## Workflow +Copy this checklist into your response to track progress: + +```markdown +Release Notes Progress: +- [ ] Step 1: Formulate the entry (past tense) +- [ ] Step 2: Find the PR number (if not already known) +- [ ] Step 3: Determine the section (Inspector, Memory, etc.) +- [ ] Step 4: Add the entry (use scripts/add_note.dart) +- [ ] Step 5: Add images (if applicable) +``` + +## Guidelines + +### 1. Identify the PR Number +If the PR number is unknown, use the following methods to find it: +- **Local Branch**: Identify the branch name using `git branch` or `git log`. If the branch is pushed to origin, it often has a linked PR. +- **GitHub CLI (`gh`)**: Use the GitHub CLI to find the PR associated with the current branch. + - **IMPORTANT**: Always use `PAGER=cat` to prevent `gh` from hanging in non-interactive terminals. + - Command: `PAGER=cat gh pr list --head --json number,title` +- **Search by Change Description**: Search open PRs using keywords from your change title or description. + - Command: `PAGER=cat gh pr list --search "" --limit 5` +- **Web Search**: If CLI tools fail, use `search_web` to find the PR on GitHub: + - Query: `site:github.com/flutter/devtools "Add support for searching within the log details view"` + +### 2. Formulate the Entry +- **Tense**: Always use **past tense** (e.g., "Added", "Improved", "Fixed"). +- **Punctuation**: Always end entries with a **period**. +- **Template**: `* . [#](https://github.com/flutter/devtools/pull/)` +- **Placeholder**: Use `TODO` if you have exhausted all search methods and the PR has not been created yet. +- **Images**: If adding an image, indent it by two spaces to align with the bullet point, and ensure there is only one newline between the text and the image. + - Correct Format: + ```markdown + - Added support for XYZ. [#TODO](https://github.com/flutter/devtools/pull/TODO) + ![](images/my_feature.png) + ``` +- **Examples**: + - `* Added support for XYZ. [#12345](https://github.com/flutter/devtools/pull/12345)` + - `* Fixed a crash in the ABC screen. [#67890](https://github.com/flutter/devtools/pull/67890)` + +### 3. User-Facing Changes Only +- **Criteria**: Focus on **what** changed for the user, not **how** it was implemented. +- **Avoid**: Technical details like "Implemented XYZ with a new controller", "Updated the build method", or naming internal classes. +- **Example (Bad)**: `* Implemented log details search using SearchControllerMixin. [#TODO](https://github.com/flutter/devtools/pull/TODO)` +- **Example (Good)**: `* Added search support to the log details view. [#TODO](https://github.com/flutter/devtools/pull/TODO)` + +### 4. Determine Section +Match the change to the section in `NEXT_RELEASE_NOTES.md`: +- `General updates` +- `Inspector updates` +- `Performance updates` +- `CPU profiler updates` +- `Memory updates` +- `Debugger updates` +- `Network profiler updates` +- `Logging updates` +- `App size tool updates` +- `Deep links tool updates` +- `VS Code sidebar updates` +- `DevTools extension updates` +- `Advanced developer mode updates` + +### 5. Add to NEXT_RELEASE_NOTES.md +Use the provided utility script to insert the note safely. The script handles replacing the TODO placeholder if it's the first entry in that section. + +```bash +dart .agents/skills/adding-release-notes/scripts/add_note.dart "Inspector updates" "Added XYZ support" TODO +``` + +### 6. Optional: Images +Add images to `packages/devtools_app/release_notes/images/` and reference them: +```markdown +![Accessible description](images/screenshot.png "Hover description") +``` +**Constraint**: Use **dark mode** for screenshots. + +## Resources +- [README.md](../../packages/devtools_app/release_notes/README.md): Official project guidance. diff --git a/.agents/skills/adding-release-notes/scripts/add_note.dart b/.agents/skills/adding-release-notes/scripts/add_note.dart new file mode 100644 index 00000000000..42ca9f52aab --- /dev/null +++ b/.agents/skills/adding-release-notes/scripts/add_note.dart @@ -0,0 +1,72 @@ +// Copyright 2019 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. + +import 'dart:io'; + +void main(List args) { + if (args.length < 3) { + print('Usage: dart add_note.dart
'); + exit(1); + } + + final section = args[0].trim(); + final note = args[1].trim(); + final pr = args[2].trim(); + + final prLink = pr == 'TODO' + ? '[TODO](https://github.com/flutter/devtools/pull/TODO)' + : '[#$pr](https://github.com/flutter/devtools/pull/$pr)'; + + final filePath = 'packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md'; + final file = File(filePath); + + if (!file.existsSync()) { + print('Error: $filePath not found.'); + exit(1); + } + + var content = file.readAsStringSync(); + + if (!content.contains('## $section')) { + print("Error: Section '$section' not found."); + exit(1); + } + + final noteWithPeriod = note.endsWith('.') ? note : '$note.'; + final newEntry = '- $noteWithPeriod $prLink\n'; + + // Check for TODO placeholder. + const todoText = 'TODO: Remove this section if there are not any updates.'; + final todoPattern = RegExp( + '## ${RegExp.escape(section)}\\s*\\n\\s*${RegExp.escape(todoText)}\\s*\\n*', + ); + + if (todoPattern.hasMatch(content)) { + content = content.replaceFirst(todoPattern, '## $section\n\n$newEntry\n'); + } else { + // Append to existing list in the section. + final sectionHeader = '## $section'; + final sectionStart = content.indexOf(sectionHeader); + + // Find the next section start or the end of the file. + var nextSectionStart = content.indexOf('\n## ', sectionStart + 1); + if (nextSectionStart == -1) { + nextSectionStart = + content.indexOf('\n# Full commit history', sectionStart + 1); + } + if (nextSectionStart == -1) { + nextSectionStart = content.length; + } + + var sectionContent = + content.substring(sectionStart, nextSectionStart).trimRight(); + sectionContent += '\n$newEntry'; + + content = + '${content.substring(0, sectionStart)}$sectionContent\n${content.substring(nextSectionStart).trimLeft()}'; + } + + file.writeAsStringSync(content); + print('Successfully added note to $section.'); +} diff --git a/pubspec.lock b/pubspec.lock index b0a61b8a684..e30fd8babfe 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -758,10 +758,10 @@ packages: dependency: transitive description: name: source_gen - sha256: "1d562a3c1f713904ebbed50d2760217fd8a51ca170ac4b05b0db490699dbac17" + sha256: adc962c96fffb2de1728ef396a995aaedcafbe635abdca13d2a987ce17e57751 url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.2.1" source_map_stack_trace: dependency: transitive description: