Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .agents/skills/adding-release-notes/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
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, use "TODO" for PR number if unknown)
- [ ] Step 2: Determine the section (Inspector, Memory, etc.)
- [ ] Step 3: Add the entry (use scripts/add_note.dart)
- [ ] Step 4: Add images (if applicable)
```

## Guidelines

### 1. Formulate the Entry
- **Tense**: Always use **past tense** (e.g., "Added", "Improved", "Fixed").
- **Punctuation**: Always end entries with a **period**.
- **Template**: `* <Description>. [#<PR_NUMBER>](https://github.com/flutter/devtools/pull/<PR_NUMBER>)`
- **Placeholder**: Use `TODO` if you do not have a PR number 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)`

### 2. 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)`

### 3. 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`

### 3. 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
```

### 4. 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.
68 changes: 68 additions & 0 deletions .agents/skills/adding-release-notes/scripts/add_note.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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<String> args) {
if (args.length < 3) {
print('Usage: dart add_note.dart <section> <note> <pr_number>');
exit(1);
}

final section = args[0].trim();
final note = args[1].trim();
final pr = args[2].trim();

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.');
}
20 changes: 10 additions & 10 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -530,10 +530,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.dev"
source: hosted
version: "0.12.18"
version: "0.12.19"
material_color_utilities:
dependency: transitive
description:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -854,26 +854,26 @@ packages:
dependency: transitive
description:
name: test
sha256: "54c516bbb7cee2754d327ad4fca637f78abfc3cbcc5ace83b3eda117e42cd71a"
sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
url: "https://pub.dev"
source: hosted
version: "1.29.0"
version: "1.30.0"
test_api:
dependency: transitive
description:
name: test_api
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
version: "0.7.9"
version: "0.7.10"
test_core:
dependency: transitive
description:
name: test_core
sha256: "394f07d21f0f2255ec9e3989f21e54d3c7dc0e6e9dbce160e5a9c1a6be0e2943"
sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
url: "https://pub.dev"
source: hosted
version: "0.6.15"
version: "0.6.16"
typed_data:
dependency: transitive
description:
Expand Down
Loading