Automatic generation of a project change log using GitLab

In this short article, we’ll talk about what a project change log is, why you need it, and how you can automate its generation using GitLab.

What is a changelog and what is it for?

A project changelog (changelog) is a document that usually contains an ordered list of project versions with their release dates, as well as a list of all changes for each of the versions.

Changelog will be primarily useful for the developers themselves, with its help you can quickly find in which version of the project the next feature breaking the production was added, or during the demonstration it will help to remember all the changes made during the iteration. It will also be useful both for managers following product development and for ordinary users who want to know what changes are in the current version and whether they need to update the application.

How to keep a log of changes?

At a minimum, a good changelog should adhere to the following principles:

  • There should be a separate section for each version.

  • Group changes by categories (Feature, Bug fix, Changed, etc.).

  • The newest versions should be at the beginning of the document.

  • Be able to navigate through the file.

The log file can be kept manually, but few developers will do it with enthusiasm, and if you support several versions of the product at the same time, it turns into a very tedious task. Another option would be to automate this process.

One of the ways to generate a change log (which we will use) will be to generate a log from a list of commits, but since they are often written haphazardly, first of all it is necessary for the development team to adhere to a certain style when writing commits. This style will depend on what you want to see in the change log, you can use something ready or write something of your own.

How to generate?

For generation, we will use the functionality GitLab API, with its help the file (CHANGELOG.md) with a change log based on the commit headers. Only those commits that include a specific tag (Git trailers) are added. GitLab uses these tags to group changes into categories.

To generate you need to make a POST request:

%gitlab-host%/api/v4/projects/%id%/repository/changelog

  • gitlab-host is the address where the GitLab server with your repository is located.

  • id – this is the project id of your repository, which can be viewed in the settings on the tab “General”

You also need to pass the access token for the api, which can be obtained in the settings on the tab “Access Tokens”. (or in your profile settings, on the tab “Access Tokens”.) And at least a required attribute “version” – the version for which the change log is generated. List of all attributes.

The result of executing the query will be a new section in the fileCHANGELOG.md in the selected repository. By default, the commit range starts from the last tag up to the version specified in the attribute “version” and ends with the default branch in the project, in the same branch the file with the change log will be updated.

In order for GitLab to automatically find the latest tag, both the version and the tag name need to be styled according to semantics of versioning

If we want to name something differently or use a different range of commits, then attributes come to the rescue:

  • from – the name of the branch, the last commit of which will be the beginning of the range. The commit itself will not be listed.

  • to – the name of the branch, the last commit of which will become the end of the range. The commit itself will be listed.

  • branch – the name of the branch in which the file will be updated / created CHANGELOG.md

For example, let’s execute several queries with the initial data:

  • Project id – 111

  • Gitlab-host https://gitlab.com/

  • API access token – token

  • Last tag name – 0.9.0

  • Default branch name – main

curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0" "https://gitlab.com/api/v4/projects/111/repository/changelog"

The result of the execution will be a new section in the branch main, subtitled 1.0.0 and the range of included commits 0.9.0..main

curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0&from=release_0.9.0&to=develop&branch=develop" "https://gitlab.com/api/v4/projects/111/repository/changelog" 

The result of the execution will be a new section in the branch develop, subtitled 1.0.0 and the range of included commits release_0.9.0..develop

How to customize?

For customization, a configuration file in YAML format is used. The file must be located in the root of the repository along the path: .gitlab/changelog_config.yml

For GitLab to start recognizing the configuration file, it must be located on the default branch.

The following variables are available for editing:

  • date_format – the date format that will be used in the title of the new section of the change log

  • template – the data format that will be used to display each category of the change log

  • categories – an alias to be used as the category name instead of the ones we use as git trailers

For example, the structure of our commits will look like this:

(task number): Title

– Detailed description (if required)

[git trailers]

Using the default settings, the generated file will look like this:

## 1.0.0 (2021-08-31)

### bug (2 changes)

- [bug(#12445): Исправлено зависание приложения, при нажатии кнопки "Выход"](Nethius/example@commit-sha1)([merge request](Nethius/example!4))
- [bug(#12347): Исправлено отображение кнопок "Добавить", "Удалить"](Nethius/example@commit-sha1)

### performance (2 changes)

- [refactoring(#12349): Повышена скорость сборки приложения](Nethius/example@commit-sha1)
- [refactoring(#12348): Повышена скорость загрузки приложения](Nethius/example@commit-sha1)

### feature (2 changes)

- [feature(#12346): Добавлена поддержка файлов формата .md .yml](Nethius/example@commit-sha1)
- [feature(#12345): Реализована форма авторизации](Nethius/example@commit-sha1)

Now let’s try to change the category titles and add a commit author for each entry.

In the example above, we are using the standard git trailer – Changelog and the values ​​used for it: feature, bug, performance, which became the names of the categories.

To change the names of categories, you need to add to the configuration file changelog_config.yml the following lines:

categories:
  feature: Features
  bug: Bug fixes
  performance: Performance improvements

Templates are used to generate data in categories. For the example above, the template looks like this:

template: |
  {% if categories %}
  {% each categories %}
  ### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})

  {% each entries %}
  - [{{ title }}]({{ commit.reference }})
  {% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}

  {% end %}

  {% end %}
  {% else %}
  No changes.
  {% end %}

Here, in the main loop, we go through all the categories, displaying the name and number of posts in the category. In the nested loop, we go through all the records and write out the commit header and the link to it, if there is a link to the MP, then add it.

  • {% …%} – used for conditions (if / else) and loops (each). Each expression must be closed with {% end%}

  • {{…}} – used to display data available in the template

To display the author of the commit, we will change the template text by adding the line to the nested loop by {{ author.reference }} after displaying the link to the commit.

After all the changes, the file changelog_config.yml will look like this:

---
categories:
  feature: Features
  bug: Bug fixes
  performance: Performance improvements
template: |
  {% if categories %}
  {% each categories %}
  ### {{ title }} ({% if single_change %}1 change{% else %}{{ count }} changes{% end %})

  {% each entries %}
  - [{{ title }}]({{ commit.reference }}) by {{ author.reference }}
  {% if merge_request %} ([merge request]({{ merge_request.reference }})){% end %}

  {% end %}

  {% end %}
  {% else %}
  No changes.
  {% end %}

And the generated file CHANGELOG.md So:

## 1.0.0 (2021-08-31)

### Bug fixes (2 changes)

- [bug(#12445): Исправлено зависание приложения, при нажатии кнопки "Выход"](Nethius/example@commit-sha1) by @Nethius ([merge request](Nethius/example!4))
- [bug(#12347): Исправлено отображение кнопок "Добавить", "Удалить"](Nethius/example@commit-sha1) by @Nethius

### Performance improvements (2 changes)

- [refactoring(#12349): Повышена скорость сборки приложения](Nethius/example@commit-sha1) by @Nethius
- [refactoring(#12348): Повышена скорость загрузки приложения](Nethius/example@commit-sha1) by @Nethius

### Features (2 changes)

- [feature(#12346): Добавлена поддержка файлов формата .md .yml](Nethius/example@commit-sha1) by @Nethius
- [feature(#12345): Реализована форма авторизации](Nethius/example@commit-sha1) by @Nethius

How to automate?

First, set up GitLab CI / CD… After this stage is passed, add to the file .gitlab-ci.yml a new stage (or change an existing one) to update the changelog. In it we have to get the names of the branches for the attributes. from and to and after that execute a POST request to generate the file CHANGELOG.md

For example, let’s say our fetch of commits starts at the last tag and ends with the current release version. The version of the change log, for example, will be taken from the project files, stage will be launched only for the release branch.

update-changelog:
  stage: update_changelog
  script: 
    - latestVersion=$(git describe --tags --abbrev=0)
    - currentVersion=$(grep -oP '(?<=VERSION ")([^"]*)' version.h)
    - |
      curl --header "PRIVATE-TOKEN: token" --data "version=$currentVersion&from=$latestVersion&to=release&branch=release" "https://gitlab.com/api/v4/projects/111/repository/changelog"
  only: 
    - release

Now, every time you build a release, a new section with the currentVersion version will be added to the file CHANGELOG.md

It is important that if the section with the current version already exists, then it will not be supplemented with new commits.

Outcome

In a couple of hours, we set up a simple automatic generation of a file with a change log, which, even in this form, will be useful on small projects, reduce the routine of maintainers, or, for example, help to receive fewer calls from technical support with questions in which version the feature was added.

Thank you for reading!

Tags: GitLab CI, GitLab, Changelog, DevOps

Hubs: Git

Similar Posts

Leave a Reply