Log4j Changelog

This project contains tools to maintain changelogs. It is designed for Apache Log4j, but can be used for any Java project.

Dependencies

You need to have the org.apache.logging.log4j:log4j-changelog dependency in your classpath:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-changelog</artifactId>
  <version>0.9.0</version>
</dependency>

Java module name and OSGi Bundle-SymbolicName are set to org.apache.logging.log4j.changelog.

What is a changelog?

A changelog is a log of all notable changes made to a project.

Why yet another changelog tool?

Existing changelog practices (e.g., Keep a changelog, maven-changes-plugin) store changelog entries in the same file. This creates merge conflicts between different branches. Imagine multiple people working on multiple branches each containing a change to CHANGELOG.md. Whoever succeeds in merging their branch to main first will cause a merge-conflict for the others, even though their work might be totally unrelated from each other.

This project embraces a model where changelog entries are kept in separate files and hence are not prone to merge conflicts. Similar to maven-changes-plugin, changelog sources and their exports (e.g., AsciiDoc-formatted) are split by design.

What does it look like?

All changelog sources and templates used to export them are stored in folders under the changelog directory (e.g., /src/changelog):

$ tree -a src/changelog
├── 2.18.0                              (1)
│   ├── LOG4J2-3424_Properties_defined_in_configuration_using_a_value_attribute.xml   (4)
│   ├── LOG4J2-3425_Syslog_appender_lacks_the_SocketOptions_setting.xml               (4)
│   ├── LOG4J2-3426_Log4j_1_2_bridge_should_not_wrap_components_unnecessarily.xml     (4)
│   ├── LOG4J2-3427_Improves_ServiceLoader_support_on_servlet_containers.xml          (4)
│   ├── .release-notes.adoc.ftl         (5)
│   └── .release.xml                    (3)
├── 2.19.0                              (1)
│   ├── LOG4J2-3588_Allow_PropertySources_to_be_added.xml                             (4)
│   ├── LOG4J2-3590_Remove_SLF4J_1_8_x_binding.xml                                    (4)
│   ├── LOG4J2-3614_Harden_InstantFormatter_against_delegate_failures.xml             (4)
│   ├── LOG4J2-3556_JsonTemplateLayout_stack_trace_truncation_fix.xml                 (4)
│   ├── .release-notes.adoc.ftl         (5)
│   └── .release.xml                    (3)
├── .2.x.x                              (2)
│   ├── LOG4J2-1284_redirect_old_javadoc_urls.xml                                     (4)
│   └── .release-notes.adoc.ftl         (5)
├── .changelog.adoc.ftl                 (5)
└── .index.adoc.ftl                     (5)
1 Changelog sources of released versions are stored in <changelogDirectory>/<releaseVersion> folders (e.g., src/changelog/2.19.0)
2 Changelog sources of upcoming releases are stored in <changelogDirectory>/.<releaseVersionMajor>.x.x folders (e.g., /src/changelog/.2.x.x)
3 .release.xml contains the information about the associated release. Note that upcoming release folders (e.g., src/changelog/.2.x.x) don’t contain a .release.xml, since these releases are by definition not done yet.
4 All XML files not prefixed with a . (e.g., src/changelog/.2.x.x/LOG4J2-3628_new_changelog_infra.xml) constitute changelog entries
5 FreeMarker templates are used to export this information to various forms; AsciiDoc-formatted pages for the website, Markdown-formatted files for GitHub Releases, etc.

Release entry file

A release entry file, .release.xml, consists of meta information regarding a particular release. A sample release entry file is shared below.

src/changelog/2.19.0/release.xml file contents
<?xml version="1.0" encoding="UTF-8"?>
<release xmlns="https://logging.apache.org/xml/ns"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="
             https://logging.apache.org/xml/ns
             https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
         date="2022-09-09"
         version="2.19.0"/>

Note that upcoming release folders (e.g., src/changelog/.2.x.x) don’t contain a .release.xml, since these releases are by definition not done yet.

Changelog entry file

A changelog entry file consists of short meta information regarding a particular change. They are named following the [<issueId>_]<shortSummary>.xml pattern. Consider the following examples:

  • LOG4J2-3556_JsonTemplateLayout_stack_trace_truncation_fix.xml

  • LOG4J2-3578_Generate_new_SSL_certs_for_testing.xml

  • Update_jackson_2_11_0_2_11_2.xml

A sample changelog entry file is shared below.

src/changelog/2.19.0/LOG4J2-3556_JsonTemplateLayout_stack_trace_truncation_fix.xml file contents
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="https://logging.apache.org/xml/ns"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           https://logging.apache.org/xml/ns
           https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
       type="fixed">
  <issue id="2443" link="https://github.com/apache/logging-log4j2/pull/2443"/>
  <description format="asciidoc">
    Make `JsonTemplateLayout` stack trace truncation operate for each label block
  </description>
</entry>

Some remarks about the structure of changelog entry files:

  • The root element must be named entry

  • entry.type attribute is required and must be one of the change types:

    • added – for new features

    • changed – for changes in existing functionality

    • deprecated – for soon-to-be removed features

    • fixed – for any bug fixes

    • removed – for now removed features

    • updated – for dependency updates

  • issue element is optional, can occur multiple times, and, if present, must contain id and link attributes

  • There must be a single description element with non-blank content and format attribute

Exporting changelogs

Exporting changelogs is the act of feeding provided changelog and release information into FreeMarker templates to generate certain files; e.g., release notes for the website. There are two types template files supported:

Changelog templates

These templates are rendered with the release and changelog information of a particular release. These are generally used to generate release notes for a particular release.

Index templates

These templates are rendered with the release information of all releases. These are generally used to generate the index page referencing to release notes of each release.

ChangelogExporter is responsible for performing the export operation.

Changelog templates

Changelog template files (e.g., src/changelog/2.19.0/.release-notes.adoc.ftl ) are rendered with the release and changelog information of a particular release using the following input data hash:

  • releaseChangelogRelease

  • entriesByTypeMap<ChangelogEntry.Type, List<ChangelogEntry>>

See ChangelogRelease and ChangelogEntry for details.

These templates are generally used to generate release notes for a particular release. A sample changelog template file is shared below.

src/changelog/2.19.0/.release-notes.adoc.ftl file contents
= ${release.version}<#if release.date?has_content> (${release.date})</#if>

This release primarily contains bug fixes and minor enhancements.

<#if entriesByType?size gt 0>== Changes
<#list entriesByType as entryType, entries>

=== ${entryType?capitalize}

<#list entries as entry>
* ${entry.description.text?replace("\\s+", " ", "r")}
(<#list entry.issues as issue>${issue.link}[${issue.id}]<#if issue?has_next>, </#if></#list>)
</#list>
</#list>
</#if>

Index templates

Index template files (e.g., src/changelog/.index.adoc.ftl) are rendered with the release information of all releases using the following input data hash:

  • releases → list of hashes containing following keys:

    • version

    • date

These template files are generally used to generate the index page referencing to release notes of each release. A sample index template file is shared below.

src/changelog/.index.adoc.ftl file contents
= Release changelogs

<#list releases as release>
* xref:${release.version}.adoc[${release.version}]<#if release.date?has_content> (${release.date})</#if>
</#list>

Q&A

How can I add an entry for a change I am about to commit?

You have just committed, or better, about to commit a great feature you have been working on. Simply create a Changelog entry file and commit it along with your change!

How can I export changelogs to AsciiDoc, Markdown, etc. files?

I am about to deploy a new release. What shall I do?

Just before a release, three things need to happen in the changelog sources:

  1. Changelog entry files needs to be moved from the upcoming release changelog directory <changelogDirectory>/.<releaseVersionMajor>.x.x to the new release changelog directory <changelogDirectory>/<releaseVersion>

  2. Templates need to be copied from the upcoming release changelog directory to the new release changelog directory, unless it already exists in the target

  3. .release.xml needs to be created in the new release changelog directory

Due to the nature of release candidates, above steps might need to be repeated multiple times.

Log4j releases and release candidates all get deployed to the same staging repository. Their pom.xml files all contain the same release version, e.g., 2.19.0. There are no -rc1, -rc2, etc. suffixes in the version of a release candidate. Once a release candidate voting reaches to a consensus for release, associated artifacts simply get promoted from the staging to the public repository. Hence, there are no differences between releases and release candidates from the point of view of changelogs.

How to carry out aforementioned changes are explained below in steps:

  1. Populate the <changelogDirectory>/<releaseVersion> directory (e.g., /src/changelog/2.19.0) from the upcoming release changelog directory (e.g., <changelogDirectory>/.2.x.x) using the release Maven goal:

    ./mvnw log4j-changelog:release \
        -Dlog4j.changelog.directory=/path/to/changelog/directory \
        -Dlog4j.changelog.releaseVersion=X.Y.Z
  2. Verify that all changelog entry files are moved from <changelogDirectory>/.<releaseVersionMajor>.x.x directory (e.g., /src/changelog/.2.x.x)

  3. Verify that <changelogDirectory>/<releaseVersion> directory (e.g., /src/changelog/2.19.0) is created, and it contains templates, changelog entry files, and a .release.xml

    If <changelogDirectory>/<releaseVersion> directory (e.g., /src/changelog/2.19.0) already exists with certain content, ChangelogReleaser will only move new changelog entry files and override .release.xml; templates will not be overridden. This allows one to run ChangelogReleaser multiple times, e.g., to incorporate changes added to a release candidate.

  4. Edit the populated templates (e.g., update the release notes with a short summary paragraph)

  5. git add the changes in the changelog directory (e.g., /src/changelog) and commit them