| = Adding a Changelog Entry to Apache Solr |
| :toc: |
| :toclevels: 2 |
| :icons: font |
| |
| The project no longer maintains a monolithic *CHANGES.txt* file directly. |
| Instead, we create small YAML fragments **per bug-fix or feature**, checked into |
| the `solr/changelog/unreleased/ folder`. At release time these fragments are |
| organized in versioned folders and collated into a human-readable *CHANGELOG.md* file. |
| |
| This document walks you through the workflow, explains the Gradle helpers |
| available, and finishes with a concrete example fragment. We use a tool called |
| [logchange](https://logchange.dev/tools/logchange/) as a gradle plugin to manage |
| the changelog. |
| |
| == 1. Workflow Overview |
| |
| . Make a feature branch with a descriptive name like 'SOLR-12345-fix-memory-leak'. |
| . Implement your change |
| . Run `./gradlew writeChangelog` |
| . Edit the generated YAML file in `changelog/unreleased/` to add a clear, user-focused description. |
| . Commit the YAML fragment along with the code change. |
| . Open your PR as usual. |
| |
| == 2. Directory Layout |
| |
| [source] |
| ---- |
| solr/ |
| └── changelog/ |
| ├── unreleased/ ← new fragments live here |
| | └── SOLR-12345-fix-memory-leak.yml |
| ├── v9.8.0/ ← changes in already released versions |
| ├── v9.8.0/ |
| └── v9.9.0/ |
| ---- |
| |
| == 3. The YAML format |
| |
| Below is an example of a changelog yaml fragment. The full yaml format is https://logchange.dev/tools/logchange/reference/#yaml-entry-format[documented here], but we normally only need `title`, `type`, `authors` and `links`. For a change without a JIRA, you can add the PR number in `issues`: |
| |
| [source, yaml] |
| ---- |
| title: Fix nasty bug in CoreContainer shutdown |
| # added, changed, fixed, deprecated, removed, dependency_update, security, other |
| type: fixed |
| authors: |
| - name: John Contributor |
| nick: johngithub |
| url: https://home.apache.org/phonebook.html?uid=johnasfid |
| links: |
| - name: SOLR-3333 |
| url: https://issues.apache.org/jira/browse/SOLR-3333 |
| ---- |
| |
| === 3.1 Tool to draft a YAML for your change |
| |
| We have a gradle task that bootstraps a YAML file in the `changelog/unreleased/` directory. The task will use your current branch name as a file name and also title, and will |
| try to parse JIRA id from the branch name if it exists to add the `links`. |
| |
| Invoke the task with: |
| |
| [source, bash] |
| ---- |
| ./gradlew writeChangelog |
| ---- |
| |
| The task will use your git `user.name` as display name by default, but if you |
| add your name, GitHub username, and optionally Apache ID to the |
| `gradle.properties` file at the root of the Solr git checkout, this task will |
| use that information. Example: |
| |
| [source, properties] |
| ---- |
| # Changelog generator settings (./gradlew writeChangelog) |
| user.name=John Doe |
| user.githubid=johngithub |
| user.asfid=johnapache |
| ---- |
| |
| The changelog has comments to help you fill it out. Remove them after filling out the form. |
| |
| TIP: Aliases for the `writeChangelog` task are `changelog` and `newChangelog`. |
| |
| == 4. Changelog Validation in Pull Requests |
| |
| The `validate-changelog` GitHub workflow automatically checks that: |
| |
| . **CHANGES.txt is not edited directly** - All changes must use the YAML fragment approach |
| . **A changelog entry is added** - Code changes must include a corresponding YAML file in `changelog/unreleased/` |
| |
| If your change does not require a changelog entry, it is still possible to merge the PR. |
| |
| == 5. For release managers |
| |
| === 5.1 Gradle tasks for logchange |
| |
| The logchange gradle plugin offers some tasks, here are the two most important: |
| |
| [cols="1,2", options="header"] |
| |=== |
| | Task | Purpose |
| |
| | `logchangeGenerate` |
| | Generates changelog file `/CHANGELOG.md` based on `.yml` entries and archives (does not moves any files) |
| |
| | `logchangeRelease` |
| | Creates a new changelog release by moving files from `changelog/unreleased/` directory to `changelog/vX.Y.Z` directory |
| |
| | `logchangeArchive` |
| | Archives the list of released versions up to (and including) the specified version by transferring their summaries to the `archive.md` file, merging all existing archives, and deleting the corresponding version directories. |
| |=== |
| |
| The `logchangeRelease` and `logchangeGenerate` tasks are used by ReleaseWizard. The `logchangeArchive` task can be ran once for every major release or when the number of versioned changelog folders grow too large. |
| |
| These are integrated in the Release Wizard. |
| |
| === 5.2 Migration tool |
| |
| There is a migration tool in `dev-tools/scripts/changes2logchange.py` for one-time use during the transition. |
| It will bulk convert the entire `solr/CHANGES.txt` file to files in the `changelog/` folder and versioned sub folders. |
| |
| The tool can also be used by a developer who needs to convert many entries from work-in-progress after the migration |
| cutover. You can paste one or more entries and get them converted in the Terminal as follows: |
| |
| [source,bash] |
| ---- |
| cat << EOF | python3 dev-tools/scripts/changes2logchange.py - |
| * SOLR-17960: Removed TikaLanguageIdentifierUpdateProcessor. |
| Use LangDetectLanguageIdentifierUpdateProcessor or |
| OpenNLPLangDetectUpdateProcessor instead. (janhoy) |
| EOF |
| ---- |
| |
| which will output to `stdout`: |
| |
| [source,yaml] |
| ---- |
| title: Removed TikaLanguageIdentifierUpdateProcessor. Use LangDetectLanguageIdentifierUpdateProcessor |
| or OpenNLPLangDetectUpdateProcessor instead. |
| type: other # added, changed, fixed, deprecated, removed, dependency_update, security, other |
| authors: |
| - name: janhoy |
| links: |
| - name: SOLR-17960 |
| url: https://issues.apache.org/jira/browse/SOLR-17960 |
| ---- |
| |
| === 5.3 Changelog validation tool |
| |
| There is a tool `dev-tools/scripts/validateChangelogs.py` that will do a |
| cross-branch validation of changelog folders. It takes no arguments and |
| discovers the branch structure automatically, and checks that each branch |
| (unstable, stable, release, previous-stable, previous-bugfix) are in sync |
| with remote and "clean". Then it checks that the changelog folders are the |
| same across branches and computes some statistics on how many unreleased |
| features are from each branch. |
| |
| The tool can also output a consolidated `CHANGELOG.md` file which calculates |
| what (unreleased) features are likely to be released in what version. This |
| resembles what we used to have in our `CHANGES.txt` on main branch before. |
| The tool is integrated in the releaseWizard. |
| |
| usage: validateChangelogs.py -h |
| |
| Example report output (Json or Markdown): |
| |
| [source,json,title=Example json report] |
| ---- |
| { |
| "success": false, |
| "errors": [ |
| "Folder v9.8.1 not found on branches: {'branch_9_9'}", |
| "Folder v9.9.0 not found on branches: {'branch_9_9'}" |
| ], |
| "warnings": [], |
| "branch_report": { |
| "branch_9_9": { |
| "version": "9.9.1", |
| "has_changelog_folder": false, |
| "id": "previous_major_bugfix" |
| }, |
| "branch_9x": { |
| "version": "9.10.0", |
| "unreleased_count": 31, |
| "id": "previous_major_stable", |
| "new_count": 31, |
| "new": [ |
| "SOLR-17541-deprecate -cloudhttp2solrclient-builder.yml", |
| "SOLR-17619 Use logchange for changelog management.yml" |
| ], |
| "not_in_newer_count": 1, |
| "not_in_newer": [ |
| "SOLR-17541-deprecate -cloudhttp2solrclient-builder.yml" |
| ] |
| }, |
| "branch_10_0": { |
| "version": "10.0.0", |
| "unreleased_count": 146, |
| "id": "release", |
| "new_count": 5, |
| "new": [ |
| "GITHUB#3666-removing redundant check if field exists in.yml", |
| "SOLR-12089-remove deprecated -breaksugestiontiebreaker-.yml", |
| "SOLR-14070-deprecate cloudsolrclient-s zookeeper hosts.yml" |
| ], |
| "not_in_newer_count": 2, |
| "not_in_newer": [ |
| "SOLR-16562-solr-16578- upgrade caffeine to 3-1-4 and.yml", |
| "SOLR-17012-update apache hadoop to 3-3-6 and apache curator.yml" |
| ] |
| }, |
| "branch_10x": { |
| "version": "10.1.0", |
| "unreleased_count": 147, |
| "id": "stable", |
| "new_count": 2, |
| "new": [ |
| "PR#3758-logs- removed webapp-solr and also removed from.yml", |
| "SOLR-17963-these solrcloud commands no longer aquire locks.yml" |
| ] |
| }, |
| "main": { |
| "version": "11.0.0", |
| "unreleased_count": 147, |
| "id": "main", |
| "new_count": 0, |
| "new": [] |
| } |
| } |
| } |
| ---- |
| |
| == 6. Further Reading |
| |
| * https://github.com/logchange/logchange[Logchange web page] |
| * https://keepachangelog.com/en/1.1.0/[keepachangelog.com website] |