|
| 1 | +--- |
| 2 | +name: draft-release-notes |
| 3 | +description: Draft the Unreleased section of CHANGELOG.md by running .github/scripts/draft-change-log-entries.sh, classifying each PR from its real diff, and producing clean user-facing entries. Use when asked to prepare, update, or clean up the Unreleased section of CHANGELOG.md. |
| 4 | +--- |
| 5 | + |
| 6 | +# Draft Release Notes Skill |
| 7 | + |
| 8 | +This skill turns the raw output of `.github/scripts/draft-change-log-entries.sh` |
| 9 | +into a curated `## Unreleased` section in `CHANGELOG.md`. |
| 10 | + |
| 11 | +The rules below are baked in from previous drafting passes on this repo. Follow |
| 12 | +them directly rather than re-deriving them. |
| 13 | + |
| 14 | +## When to Use |
| 15 | + |
| 16 | +- Asked to draft, refresh, or clean up the `## Unreleased` section of |
| 17 | + `CHANGELOG.md`. |
| 18 | +- Asked to categorize a batch of recent PRs into release-note sections. |
| 19 | +- Asked to decide whether a specific PR is a breaking change, deprecation, |
| 20 | + enhancement, or bug fix. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +- `gh` CLI authenticated (needed for label-based extraction inside the script |
| 25 | + and for inspecting individual PR diffs). |
| 26 | +- `git` available with local branches up to date. |
| 27 | +- You are operating on the repository root. |
| 28 | + |
| 29 | +## Section Order |
| 30 | + |
| 31 | +Use exactly this order. Omit any section that ends up empty. |
| 32 | + |
| 33 | +1. `### ⚠️ Breaking changes to non-stable APIs` |
| 34 | +2. `### 🚫 Deprecations` |
| 35 | +3. `### 🌟 New javaagent instrumentation` |
| 36 | +4. `### 🌟 New library instrumentation` |
| 37 | +5. `### 📈 Enhancements` |
| 38 | +6. `### 🛠️ Bug fixes` |
| 39 | +7. `### 🧰 Tooling` (only if it carries user-facing tooling changes) |
| 40 | + |
| 41 | +## Workflow |
| 42 | + |
| 43 | +### 1. Generate the raw draft |
| 44 | + |
| 45 | +```bash |
| 46 | +.github/scripts/draft-change-log-entries.sh | tee out |
| 47 | +``` |
| 48 | + |
| 49 | +The script: |
| 50 | + |
| 51 | +- Computes the commit range since the last release tag. |
| 52 | +- Pulls PRs labeled `breaking change` and `deprecation` via `gh`. |
| 53 | +- Flags commits whose diff adds or removes `@Deprecated` on `src/main` files. |
| 54 | +- Groups remaining commits by whether they touch `src/main/`. |
| 55 | + |
| 56 | +Keep the `out` file around for the whole pass; you will re-read it per PR. |
| 57 | +Delete it at the end. |
| 58 | + |
| 59 | +If the script fails (usually `gh` not authenticated), fix that before |
| 60 | +continuing. Do not hand-roll the list. |
| 61 | + |
| 62 | +### 2. Read the current CHANGELOG |
| 63 | + |
| 64 | +Read the top of `CHANGELOG.md` and identify the `## Unreleased` block. Only |
| 65 | +this block may be modified. Never touch prior versioned releases. |
| 66 | + |
| 67 | +If the block is completely empty, start from an empty set of entries. If it |
| 68 | +already has content, treat each existing bullet as a provisional classification |
| 69 | +to re-verify against the draft output. |
| 70 | + |
| 71 | +### 3. Classify each PR from its real diff |
| 72 | + |
| 73 | +For every PR number in the draft output, decide its section from the diff, |
| 74 | +not from the PR title. Use these signals: |
| 75 | + |
| 76 | +- `gh pr view <NNNN> --json title,files --jq '{title, files: [.files[].path]}'` |
| 77 | +- `gh pr diff <NNNN> --patch` (use this when the local squash commit is empty |
| 78 | + or when you need to read actual code changes) |
| 79 | +- `git log --grep '#NNNN'` and `git show <sha>` for local history |
| 80 | + |
| 81 | +Then apply the rules in the next section. |
| 82 | + |
| 83 | +### 4. Apply the classification rules |
| 84 | + |
| 85 | +#### Breaking changes to non-stable APIs |
| 86 | + |
| 87 | +Put under this section when the PR removes or changes a public method, |
| 88 | +interface, class, or signature in a non-stable (`-alpha`) module or in an |
| 89 | +`internal` / experimental extension API. |
| 90 | + |
| 91 | +- The `#### Possible breaking changes (diff removes @Deprecated)` block in the |
| 92 | + draft output is the strongest signal. |
| 93 | +- Also inspect PRs that touch `javaagent-extension-api` and any |
| 94 | + `*/internal/**` package — removing a `default` method from an internal |
| 95 | + experimental interface is a breaking change to a non-stable API even if the |
| 96 | + class is marked `internal`. |
| 97 | +- Example from a prior pass: PR #17812 removed |
| 98 | + `ExperimentalInstrumentationModule.isIndyReady()` from the internal |
| 99 | + experimental extension API. That belonged in Breaking changes even though |
| 100 | + its per-module overrides looked like cleanup. |
| 101 | + |
| 102 | +Entries here describe what was removed/changed and where, not the motivation. |
| 103 | + |
| 104 | +#### Deprecations |
| 105 | + |
| 106 | +Put under this section when the PR deprecates user-facing API or config |
| 107 | +without removing it. |
| 108 | + |
| 109 | +- The `#### Possible deprecations (diff adds @Deprecated)` block in the draft |
| 110 | + output is the strongest signal for Java API deprecations. |
| 111 | +- Configuration property renames always belong here, not in Enhancements. |
| 112 | + Name the **old** and **new** user-facing property and/or declarative YAML |
| 113 | + key. Use the flat system property name in the user-facing text, because that |
| 114 | + is what most users configure. |
| 115 | +- When the same PR renames both a builder method and a property, describe |
| 116 | + both in one bullet. |
| 117 | + |
| 118 | +See `.github/agents/knowledge/api-deprecation-policy.md` and |
| 119 | +`.github/agents/knowledge/config-property-stability.md` for the authoritative |
| 120 | +policy. The one-line summary: |
| 121 | + |
| 122 | +- Stable property/API: may be deprecated in any minor; may only be removed in |
| 123 | + a major. |
| 124 | +- Experimental property (name contains `experimental` or YAML key ends with |
| 125 | + `/development`): may be deprecated and removed in a later release. |
| 126 | + |
| 127 | +#### New javaagent instrumentation / New library instrumentation |
| 128 | + |
| 129 | +Only use when the PR adds a brand-new instrumentation module under |
| 130 | +`instrumentation/<name>/javaagent/**` or `instrumentation/<name>/library/**`. |
| 131 | +Renaming or extracting an existing module does not count. |
| 132 | + |
| 133 | +Confirm via the PR's file list: |
| 134 | + |
| 135 | +- New module: a new `instrumentation/<name>/javaagent/build.gradle.kts` (or |
| 136 | + `library/build.gradle.kts`) together with new source files and a |
| 137 | + `settings.gradle.kts` entry. |
| 138 | +- Rename: a module path change with no brand-new coverage of a library. |
| 139 | + |
| 140 | +If no PRs fit, delete both empty section headers from the Unreleased block |
| 141 | +before finalizing. |
| 142 | + |
| 143 | +#### Enhancements |
| 144 | + |
| 145 | +User-visible feature additions, new attributes, new config flags, new |
| 146 | +stable-semconv support, or observable behavior changes gated on a new or |
| 147 | +existing flag. |
| 148 | + |
| 149 | +Examples that belong here: adding a new attribute on a span, adding a stable |
| 150 | +`db.system.name` emission, adding a new config toggle under `v3_preview`, |
| 151 | +adding schema URL on an instrumenter, optimizing an observable hot path. |
| 152 | + |
| 153 | +#### Bug fixes |
| 154 | + |
| 155 | +Observable bug fixes: wrong attribute values, missing spans, NPEs, memory |
| 156 | +leaks, crashes, latest-dep compatibility fixes that users would notice. |
| 157 | + |
| 158 | +Prefer describing the user-visible symptom or the concrete remediation (for |
| 159 | +example "Prevent duplicate OpenTelemetry Logback appenders in Spring starter" |
| 160 | +rather than "fix duplicate appender registration"). |
| 161 | + |
| 162 | +#### Omit entirely |
| 163 | + |
| 164 | +Do **not** create entries for: |
| 165 | + |
| 166 | +- Pure refactoring or code cleanup. |
| 167 | +- Style-only changes (naming conventions, `final` changes, null comparisons). |
| 168 | +- Test-only changes, cross-testing, moving tests out of default packages. |
| 169 | +- Muzzle-only CI fixes with no runtime behavior change. |
| 170 | +- Renames of internal fields, internal packages, or internal helpers. |
| 171 | +- Gradle / build-script internal tweaks that do not change published artifacts |
| 172 | + or published behavior. |
| 173 | +- `renovate[bot]` dependency bumps (the script already filters them; keep |
| 174 | + them filtered). |
| 175 | + |
| 176 | +If in doubt, re-read the PR diff. Entries in Unreleased must describe an |
| 177 | +observable change that a user could notice. |
| 178 | + |
| 179 | +### 5. Wording rules |
| 180 | + |
| 181 | +- One sentence per bullet. Imperative or descriptive, consistent with prior |
| 182 | + releases. |
| 183 | +- Name concrete user-facing surfaces: flag names, property names, class names, |
| 184 | + attribute names. Prefer flag values over internal mechanisms. For semconv |
| 185 | + opt-ins, cite the actual flag like |
| 186 | + `otel.semconv-stability.opt-in=messaging`, not "via SemconvStability". |
| 187 | +- Use backticks for config keys, property names, attributes, and class/method |
| 188 | + names. |
| 189 | +- Do not describe implementation details ("refactored", "moved", "simplified") |
| 190 | + unless that is the user-visible change itself. |
| 191 | +- Do not credit authors. |
| 192 | + |
| 193 | +### 6. Link format |
| 194 | + |
| 195 | +Each entry ends with the PR link on its own line, two-space indented: |
| 196 | + |
| 197 | +```markdown |
| 198 | +- Short user-facing description |
| 199 | + ([#NNNN](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/NNNN)) |
| 200 | +``` |
| 201 | + |
| 202 | +If multiple PRs share one logical change, group them on one trailing line: |
| 203 | + |
| 204 | +```markdown |
| 205 | +- Short user-facing description |
| 206 | + ([#AAAA](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/AAAA), |
| 207 | + [#BBBB](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/BBBB)) |
| 208 | +``` |
| 209 | + |
| 210 | +Some Deprecations bullets intentionally have no PR link (they summarize |
| 211 | +multiple earlier renames). Leave those as-is if they already exist. |
| 212 | + |
| 213 | +### 7. Sort order inside each section |
| 214 | + |
| 215 | +Within each populated section, sort PR-linked entries by ascending PR number. |
| 216 | +Unlinked bullets (if any) stay at the top of their section in their current |
| 217 | +order. |
| 218 | + |
| 219 | +After reordering, do a readback of the whole `## Unreleased` block and |
| 220 | +visually confirm monotonic PR numbers in each section. |
| 221 | + |
| 222 | +### 8. Handling tricky cases |
| 223 | + |
| 224 | +- **Empty local squash commit**: if `git show` for a PR is empty, use |
| 225 | + `gh pr diff <NNNN> --patch` to get the real diff. |
| 226 | +- **PR that touches both user-facing behavior and internal cleanup**: |
| 227 | + classify on the user-facing part. Ignore the cleanup aspect. |
| 228 | +- **PR that renames a config property**: always Deprecations, never |
| 229 | + Enhancements. Name both old and new property. Remove any stray Enhancements |
| 230 | + bullet that duplicates it. |
| 231 | +- **PR that looks like an Enhancement but only changes internal wiring**: |
| 232 | + omit. |
| 233 | +- **Property rename bullets with no PR link**: keep in Deprecations at the top |
| 234 | + of that subsection if already present; do not invent PR links for them. |
| 235 | + |
| 236 | +### 9. Finalize |
| 237 | + |
| 238 | +1. Delete any Unreleased sub-section that ended up empty. |
| 239 | +2. Re-read the full `## Unreleased` block end-to-end and sanity-check: |
| 240 | + - Section order matches the canonical order above. |
| 241 | + - Each populated section is PR-number-sorted. |
| 242 | + - No cleanup/refactor-only bullets slipped in. |
| 243 | + - Config renames appear exactly once, under Deprecations. |
| 244 | + - Every bullet names a concrete user-facing surface. |
| 245 | +3. Run `git diff CHANGELOG.md` to confirm only `## Unreleased` changed. |
| 246 | +4. Delete the temporary `out` file. |
| 247 | +5. Summarize counts per section for the user (for example "Breaking: 1, |
| 248 | + Deprecations: 9, Enhancements: 18, Bug fixes: 31"). |
| 249 | + |
| 250 | +## Reference Knowledge |
| 251 | + |
| 252 | +- `.github/agents/knowledge/api-deprecation-policy.md` — deprecate-then-remove |
| 253 | + timing, stable vs alpha rules, required Javadoc/CHANGELOG coverage. |
| 254 | +- `.github/agents/knowledge/config-property-stability.md` — stable vs |
| 255 | + experimental property policy, deprecation communication, naming |
| 256 | + conventions. |
| 257 | +- `.github/scripts/draft-change-log-entries.sh` — the source of the raw |
| 258 | + draft. Read it if you need to understand exactly what the sub-sections |
| 259 | + mean. |
0 commit comments