Automated Changelog Generation at Fueled

Stéphane Copin
Fueled Engineering
Published in
5 min readAug 27, 2018

This article is the first one in a series of blog posts regarding build automation at Fueled. More to come soon!

At Fueled, proper changelogs are important to all teams working on a project:

  • The QA team so they know what can be tested
  • The Client and Project Managers so they know what was done
  • The Developers so they can quickly reference what was worked on

We took a fairly agile approach to improving the changelog throughout the year to get where we are today. My hope is to share with you some of our key takeaways from the process so far and also make a few suggestions about where we might continue to improve.

Our initial approach was to simply write changelogs only for client builds, and internally relie on proper Jira story updates to keep track of a project’s status. While this worked well, it had the overhead of having somebody write changelogs and manually updating the Jira stories, and possibly forget a feature here or a bug fix there.

So we thought:

“Is there a way to automate it?”

That’s around the time where we learned about Semantic Commit Messages. Semantic Commit Messages allows to succinctly describe a commit’s content, optionally allowing for a more expanded message to be added in the body of the commit.

At Fueled, we’re using the following format of commit message:

<type>(<scope>): <message>

Where type is one of the following:

  • feat: a new feature
  • fix: a bug fix
  • perf: performance enhancement
  • docs: documentation update
  • refactor: code refactoring
  • test: add/change/remove unit tests
  • style: style change (update indentation, change spaces to tabs, …)
  • chore: configuration update, code signing change, …
  • scope is the part of the app that's being changed in the commit. i.e. If you have a login flow, and you've updated the UI there - you could have feat(login): <message>. It is always in lowercase with dashes separating words, i.e. video-player, code-signing, etc…
  • message is just a short imperative message (optimally less than 80 characters) describing what was done in the commit (as if you were telling to the project what it does)

Here are some examples taken from our projects:

  • feat(settings): add button allowing user to log out
  • fix(offline-mode): fix issue where success popup would not display properly on iphone 6+
  • perf(video-player): improve video playback performance by leveraging GPU
  • docs(readme): add architecture information
  • refactor(settings): de-dupe duplicated code
  • test(api): add tests related to API model parsing
  • style(*): convert spaces to tabs
  • chore(code-signing): fix code-signing issues

There are a few advantages to using Semantic Commit Messages:

  • It forces you to separate features and bug fixes from commits
  • Thus keeping the commits small and focused
  • Thus making debugging through bisect more focused
  • It allows you to extract this information into a changelog
  • It allows for consistency among teams and projects

Obviously, this only works if people adopt and use this message format for every single commit. At Fueled, over the next few weeks we introduced this format every developers at Fueled were using it — be they be on our iOS, Android, Web or API teams.

The Semantic Commit Messages syntax is heavily inspired by Karma’s Git Commit Msg, as well as other sources.

Once everybody was using this commit message syntax, it was just a matter of normalizing scopes for a given project, so that changelogs could be generated properly and consistently. Since we’re using Jira for project management, and each project has a least one Jira board, we decided to associate scopes with Jira epics — a scope could only reference a Jira epic (normalized in lowercase with dashes). We went on to detail the specification further and allow people to define more granular scopes or directly Jira story if necessary, by using a slash /.

So the final specification became:

  • Scope must be an epic
  • Nested scope might be specified after a slash /
  • Jira story may be specified as an epic (if associated with one), or as a nested scope
  • Allow multiple nested scopes to be specified separated with a comma ,

This simple set of rules allows commit to be as small as possible for a given feature, while giving us the possibility to generate changelogs that truly match what was done in the app. For example, here are some sample commits:

  • fix(XXX-1129): change copy for push notification
  • fix(analytics/XXX-421): round geocoordinates to 4th decimal
  • fix(global/XXX-742,XXX-747): fix a layout issue on iOS10 devices

But could we go any further?

Of course: we thought of validating the commit messages as they are committed. Git allows this by creating a specific file called commit-msg in .git/hooks (read more about git hooks here). This file is simply a script ran by git, with a single parameter being the message the user is trying to commit. If the script returns an error code different from 0, the commit is rejected.

We proceeded to write a linter for commit messages that could be integrated easily by developers (Wikipedia link). The tool is currently internal to Fueled but we’re looking to open-source it — keep an eye out for it 👀

The last step was to create the script to generate changelogs: the final script uses a combination of git commands (to get the commits) and the GitHub API to get the authors. It generates changelogs that can be displayed on HockeyApp/Fabric, GitHub and Slack. We decided that client-facing changelogs should only include feat, fix and perf changes, as the other types seldom refer to a relevant user story.
For example, given an input of:

  • fix(XXX-1129): change copy for push notification
  • fix(analytics/XXX-421): round geocoordinates to 4th decimal
  • fix(global/XXX-742,XXX-747): fix a layout issue on iOS10 devices
  • fix(global/XXX-426): fix login CTA

The following GitHub changelog is being generated:

GitHub Changelog

(Usernames are displayed here as it’s an internal changelog)

On HockeyApp:

HockeyApp Changelog

(Usernames aren’t displayed here as it’s client-facing, and this information is available in the Jira tickets if required)

All in all, there are many advantages to allowing for automated changelog generation, most notably Semantic Commit Messages.

I hope you found this post interesting, and stay tuned for more! We’ll soon explore how we’re using this linting to display the message as comments directly on PRs, along with the other checks we’re doing to make sure that we’re always delivering quality code.

--

--