Skip to content

ci: enforce conventional commit format

Tomas Vik requested to merge 198-conventional-commits into master

This issue of generating automated changelog can be separated into two parts:

  1. Making sure each MR contains information that can be used for generating a changelog
  2. Collecting the aforementioned information and creating changelog at the time of release

This MR handles the first part.

TL;DR: jump straight to Implementing Conventional Commits

The problem

Each MR needs to describe its change in a format that is useful for automatically generating changelog.

The options for the description format

At GitLab we are using two standardised approaches for describing changes introduced by an MR:

Changelog yml entry

This is the approach used by the main GitLab project. Each MR that introduces user-facing change contains a changelog entry similar to:

---
title: "Change[log]s"
merge_request: 1972
author: Black Sabbath @bsabbath
type: added

More details in the official documentation.

Pros:

  • Great control over what information we require from the contributor.
  • Adds MR information to the changelog

Cons:

  • Custom to GitLab
  • All tooling is in ruby
  • Enforced by Danger, which can't run on forks

Conventional commits

This is a more recent approach taken by pajamas and gitlab-ui. The commit message is used to generate a changelog entry. Each commit message needs to conform to the conventional commit standard.

Pros:

  • widely used standard
  • can be used for semantic versioning
  • open-source tooling

Cons:

  • MR reference is not in the changelog out of the box

Example of CHANGELOG entries generated from conventional commits.

Choosing Conventional Commits

Conventional commits were a better fit for the VS Code Extension for the following reasons:

  • Majority of the contributions are from the wider community. It's better not to require GitLab-specific guidelines unless it's necessary
  • Conventional commits have well-maintained and widely used JavaScript tooling available.
  • We've got a precedent in at least two existing GitLab projects (pajamas and gitlab-ui)

Implementing Conventional Commits

The original idea was to reuse the gitlab-ui Danger configuration to enforce conventional commits and I even implemented it in this deprecated MR: !83 (closed).

This solution had two shortcomings:

  • The Danger job is not running on forks - Since the Danger job needs GitLab access token (we use gitlab-bot), contributors who are not GitLab team members are not going to be warned that their commit message is not correctly structured. This was the main problem. Majority of the contributions are from the wider community.
  • The gitlab-ui Danger job wasn't strict enough - this was a much smaller issue, but the Danger bot is returning warnings when the squashed MR is valid and it allows commits without the correct structure to be merged.

Using commitlint

This MR implements a short (80 lines script) that can run on every MR (including forks) and fails if and only if the MR can't be merged because it would result in an incorrectly formatted commit message. This linting script is run as a normal CI job. This script is a replacement of the larger ruby Dangerfile used by other projects.

The only disadvantage of this approach is inconsistency. We are introducing a way of linting commits that's different from pajamas and gitlab-ui.

CI errors/warnings examples

INFO: MR is set to squash, GitLab is going to used the first multiline MR as commit message.

⧗   input: ci: enforce conventional commit format
⚠   body must not be longer than 72 characters [body-max-length]

⚠   found 0 problems, 1 warnings
ⓘ   Get help: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/docs/commits.md
INFO: MR is set to squash, there is no multiline commit and so GitLab is going to use the MR title.
INFO: If the MR title isn't correct, you can fix it and rerun this CI Job.

⧗   input: Test MR Title
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖   found 2 problems, 0 warnings
ⓘ   Get help: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/docs/commits.md
INFO: MR is not set to squash, every commit message needs to conform to conventional commit standard.

⧗   input: invalid: testing invalid type and too long message at the same time in one commit
✖   header must not be longer than 72 characters, current length is 81 [header-max-length]
✖   type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]

✖   found 2 problems, 0 warnings
ⓘ   Get help: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/docs/commits.md

⧗   input: ci: enforce conventional commit format
⚠   body must not be longer than 72 characters [body-max-length]

⚠   found 0 problems, 1 warnings
ⓘ   Get help: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/master/docs/commits.md

Part of #198 (closed)

Edited by Tomas Vik

Merge request reports