Automatically update README during release
- 3 minsIntroduction
For my open source projects I like to include a quick start snippet in their README
files, so users can quickly get
started using it. All my READMEs
thus contain a copyable snippet with the project’s maven coordinates. But there
is one obvious problem: these coordinates change with every release because the version is incremented. Before
starting a release I always need to remember to manually update the README
and insert the upcoming release’s version.
After years of doing this manually, I just now decided to automate this process and it works like a charm.
My implementation uses the following technologies:
- GitHub as SCM
- Privately hosted Jenkins for building
- Maven as build tool
gitflow-maven-plugin
for automating the release process
I’m using the following flow for development/releasing:
- Development happens in
dev
branch - Release is triggered manually from the Jenkins UI by running the release pipeline on the
dev
branch - A release does the following:
- Create a new local release branch and update the project’s version to the release version (remove
-SNAPSHOT
). - Run
mvn verify
with build profile to check whether everything actually builds successfully. - Locally merge the release branch into
master
, then runmvn deploy
to deploy artifacts to Maven Central. - Increment the version in the release branch to new
-SNAPSHOT
and merge this branch intodev
- If everything went successful until here, delete the local release branch and push the
master
anddev
branch to the origin
- Create a new local release branch and update the project’s version to the release version (remove
Step 1 is automated using gitflow:release-start
and the remaining steps are automated using gitflow:release-finish
.
This flow now only needs minimum adjustments to automatically update the README
:
Automatically update the README
First, we copy the README.md
from the project’s base directory into a sub directory, i.e. reamde/README.md
.
Next, we will use the maven-resources-plugin
to replace placeholders in the README
and copy the result into
the project’s base directory:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>validate</phase>
<configuration>
<outputDirectory>${basedir}</outputDirectory>
<resources>
<resource>
<directory>readme/</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
The flag filtering=true
enables the resource filtering mechanism that is responsible for resolving placeholders
within the resources, just like you know it from the pom.xml
itself. You are now able to use placeholders
like ${project.version} in your readme/README.md
.
Last thing we need to do is committing the automatically created README
as part of the release process. If you
take a look back at the release flow outlined at the beginning, you’ll notice the mvn verify
call that is
already executed during release. As we have bound the maven-resources-plugin
execution to the validate
phase (a pretty early phase, actually) the README
already has been processed after this call. All that is left
to do now is, to commit the file:
git add README.md
git commit -m "Update README during release"
You can find a real world example including a Jenkinsfile
at GitHub.
Further notes
I believe this can be easily taken even further: For example I’m planning to automatically include unit tested example code snippets into the project’s documentation.
There is also one thing that is still bugging me: Merging the release branch with the updated SNAPSHOT
version into
dev
always restores the README.md
as tracked file in git. The restored file now contains the last release version
and you always end up with a dirty workspace when building locally because the build overrides the file. Ideally the
generated file should not be added to the repository at all except for master branch.