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-pluginfor automating the release process
I’m using the following flow for development/releasing:
- Development happens in
devbranch - Release is triggered manually from the Jenkins UI by running the release pipeline on the
devbranch - 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 verifywith build profile to check whether everything actually builds successfully. - Locally merge the release branch into
master, then runmvn deployto deploy artifacts to Maven Central. - Increment the version in the release branch to new
-SNAPSHOTand merge this branch intodev - If everything went successful until here, delete the local release branch and push the
masteranddevbranch 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.