Befriend Your Changelog

If you are tired of maintaining your changelog files manually, following solution may help you as it helped me.

At my current company we have quite a lot of services to maintain. Some time ago we introduced proper versioning and releasing. That was a great step forward, but we were still missing an important piece. We wanted to have an easy way to know what was introduced (features & bug fixes) in each version. Appending information to a changelog file manually quickly became tedious job, as our release cycles can be very short.

To overcome this, I came up with a solution of having the changelog file generated automatically out of git commit messages. It consists of two parts. First is about adding a generated html file to a released Maven artifact, so it can be easily accessible in Maven artifacts repository (such as Nexus). Second part is about keeping up-to-date file in the project root folder.

This fit our git-flow releasing cycle flawlessly (whole process occurs in a release branch). I already described our cycle here. However, it shouldn’t be much of a hassle to adapt the solution to your preffered flow.

Core part of the solution is the maven-gitlog-plugin created by Daniel Flower. It’s a simple tool, that gets most of the job done. It generates changelog out of the git commits. It can output to a text, markdown, HTML or even JSON file. It supports GitHub and JIRA issue trackers and its configuration is really easy.

All of the below xml snippets are a part of our ‘release’ Maven profile.

Baseline is to have the gitlog plugin set up and configured in pom.xml:

 1    <plugin>
 2        <groupId>com.github.danielflower.mavenplugins</groupId>
 3        <artifactId>gitlog-maven-plugin</artifactId>
 4        <configuration>
 5            <fullGitMessage>true</fullGitMessage>
 6            <excludeCommiters>
 7                <commiter>jenkins</commiter>
 8            </excludeCommiters>
 9            <dateFormat>yyyy-MM-dd</dateFormat>
10            <markdownChangeLogFilename></markdownChangeLogFilename>
11            <generateMarkdownChangeLog>true</generateMarkdownChangeLog>
12            <generateJSONChangeLog>false</generateJSONChangeLog>
13            <generatePlainTextChangeLog>false</generatePlainTextChangeLog>
14            <outputDirectory>${project.basedir}</outputDirectory>
15        </configuration>
16        <executions>
17            <execution>
18                <goals>
19                    <goal>generate</goal>
20                </goals>
21            </execution>
22        </executions>
23    </plugin>

Important difference (in contrast to defaults) is outputDirectory value. Instead of having changelog generated in the target folder, we want it to appear in project root folder - to commit the files later on. Everything else is rather self-explanatory.

To attach changelog.html to a released Maven artifact we need to use builder-helper-maven-plugin:

 1    <plugin>
 2        <groupId>org.codehaus.mojo</groupId>
 3        <artifactId>build-helper-maven-plugin</artifactId>
 4        <executions>
 5            <execution>
 6                <id>attach-artifacts</id>
 7                <phase>package</phase>
 8                <goals>
 9                    <goal>attach-artifact</goal>
10                </goals>
11                <configuration>
12                    <artifacts>
13                        <artifact>
14                            <file>changelog.html</file>
15                            <type>html</type>
16                            <classifier>changelog</classifier>
17                        </artifact>
18                    </artifacts>
19                </configuration>
20            </execution>
21        </executions>
22    </plugin>

Then in Nexus we can easily navigate to the changelog:

Sample html output is available here.

Keeping up-to-date changelog in your project folder requires additional step of commiting and pushing newly generated files:

 1    <plugin>
 2        <groupId>org.apache.maven.plugins</groupId>
 3        <artifactId>maven-scm-plugin</artifactId>
 4        <executions>
 5            <execution>
 6                <id>add-changelog-to-git</id>
 7                <phase>package</phase>
 8                <goals>
 9                    <goal>add</goal>
10                    <goal>checkin</goal>
11                </goals>
12                <configuration>
13                    <basedir>./</basedir>
14                    <includes>, changelog.html</includes>
15                    <message>Add changelog</message>
16                    <pushChanges>true</pushChanges>
17                </configuration>
18            </execution>
19        </executions>
20    </plugin>

Maven scm plugin needs scm element specified. I had problems with defining Git addresses properly, but this Stack Overflow response did the trick:

1    <scm>
2        <url></url>
3        <connection>scm:git:ssh://</connection>
4        <developerConnection>scm:git:ssh://</developerConnection>
5    </scm>

That’s it. Your changelog always stay fresh. However, there is one catch from now on. You should pay attention to quality of your commit messages (nice writing on that by Chris Beams here). But… you was already doing that, right?