As a developer it is not your favorite duty to write changelogs according to the tagging which was done in a code repository. So the best idea is to automate the process of updating changelogs based on the commit messages which ( should ) already describe what changes came into the repo since the last merge into master or tagging a version.
For this you can use semantic releases.
semantic-release automates the whole package release workflow including: determining the next version number, generating the release notes and publishing the package.
This removes the immediate connection between human emotions and version numbers, strictly following the Semantic Versioning specification.
This process can now be used for terraform modules, chef cookbooks or any other software releasing process.
semantic-release uses the commit messages to determine the type of changes in the codebase. Following formalized conventions for commit messages, semantic-release automatically determines the next semantic version number, generates a changelog and publishes the release.
By default semantic-release uses Angular Commit Message Conventions. The commit message format can be changed with the preset or config options Tools such as commitizen or commitlint can be used to help contributors and enforce valid commit messages. Here is an example of the release type that will be done based on a commit messages:
|Commit message||Release type|
|feat(next-version): add configuration options for accounting||Feature Release|
|fix(accounting): accounting configuration options bug
|refactor(accounting): removing accounting configuration
BREAKING CHANGE: Configuration options removed for accounting
In some implementation of semantic releases it is also possible to customize those flags. In our current example we chose go-semrel-gitlab which supports this adaptions, but it is not used in any of our setups right now.
Within our upcoming pipeline we gonne use 3 stages: version, build and release. The release stage should only run when running in master.
In our initial step a version estimation is done and stored into an artifact .next-version. This file is restored on the next runs to reuse its content for stamping your binary with this build information. In our example we just generate another artifact build_info which holds some sample data to inspire you what can be done and used for your application workflow.
git fetch --tags is only mandatory on gitlab because of this issue within gitlab runner which does not fetch this information on creation.
version: stage: version image: registry.gitlab.com/mbuchleitner/go-semrel-gitlab:v0.21.1 script: - git fetch --tags - release next-version --bump-patch > .next-version artifacts: paths: - .next-version except: - tags
At the building step you can now use the information to stamp your application with the correct version number, commit sha and build job information.
compile: stage: build script: - echo "some artifact using version " > artifact - cat .next-version >> artifact - echo "RELEASE_URL=https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/jobs/$CI_JOB_ID/artifacts/release" > build_info - echo "RELEASE_DESC=\"$(uname -mo) binary\"" >> build_info - echo "RELEASE_SHA=$CI_COMMIT_SHA" >> build_info - echo "RELEASE_VERSION=$(<.next-version)" >> build_info artifacts: paths: - build_info - artifact except: - tags
Now we are within the most relevant part of this blog post - generating version tags and update the changelog with some auto-magic. If we are using this workflow on code which does not produce a binary output which can/must be stamped we could also skip the previous build steps from this post and only add this last one.
In this sample we rename the build information artifact as release information, then generate an updated changelog about the latest changes and afterwards commit our changed and tag those with the automaically generated version. As a bonus step also a download link for the current release is generated within gitlab.
For some use cases you might also want to update some meta information files ( e.g. metadata.rb on chef cookbooks ) and commit those changes with the changelog.
release: stage: release image: registry.gitlab.com/mbuchleitner/go-semrel-gitlab:v0.21.1 script: - git fetch --tags - rm -f release_info - mv build_info release_info - . release_info - echo -n "update version information v$RELEASE_VERSION ..." - release changelog - release commit-and-tag CHANGELOG.md release_info - release --ci-commit-tag v$RELEASE_VERSION add-download-link --name release --url $RELEASE_URL --description "$RELEASE_DESC" only: - master
When you start a fresh project or at least start with fresh changelog you are perfect fine now. But if you already got a changelog within your code repository you need to adapt it and add a line into the markdown:
<!--- next entry here -->
With this marker the automation is able to find the insertion of the changes. You must review the used implementation how this marker is named.