blob: ee503457a9ed57f72943f571fe5255b599cbb539 [file] [log] [blame]
= 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]