Semantically release your Angular library

profile
Tim Deschryver
timdeschryver.dev

Are you, like me, getting tired of releasing your Angular library manually? And how about keeping that CHANGELOG up to date? In this post I’m taking you along in my journey towards a fully automated process for my ngx-testing-library library!

The Angular DevOps Series link

This post is the first post of the Angular DevOps Series. The series also includes a post by fellow Angular in Depth writer, Todd Palmer, who walks you through the details of deploying an Angular application with Travis CI to GitHub pages. And, Andrew Evans shows you how to deploy to Firebase with CircleCI.

Introduction link

As a bit of background, ngx-testing-library is created with the ng generate library command and has tests written in the library as well as tests in the example application using it. To build and test my changes, I’m already using CircleCI as my Continuous Integration (CI) server.

Before we start let’s make a list of what we’re trying to accomplish after we push a commit:

🔲 Only release when the build passes

🔲 Only release when the push has been made to the master branch

🔲 Release the new version to npm

🔲 Release the new version to GitHub

🔲 Keep the CHANGELOG up to date️

CI/CD Server link

The first step towards automation is having a CI server. It will run the tests, create a build, and release the build. Because I’m already happily using CircleCI for my CI, I decided to stick with it. There are some other possibilities, the most popular being Travis CI or Jenkins. Note that the CI snippets in this post are written for a CircleCI project, other CI servers are also supporting the same functionality but with a different syntax.

📦🚀 semantic-release link

format_quote

Fully automated version management and package publishing

In my quest for automation I quickly stumbled upon semantic-release. I had already encountered this library in some OSS projects and heard good stuff about it. After giving it a quick glance it seemed like it had everything I needed and more, so I decided to go with it.

Like the name semantic-release implies, this tool will release your library using the semantic versioning specification (SemVer). In short SemVer is giving a meaning to the version number, it translates the version number to MAJOR.MINOR.PATCH, also known as BREAKING.FEATURE.PATCH.

  1. MAJOR version when you make an incompatible API change
  2. MINOR version when you add functionality in a backwards-compatible manner
  3. PATCH version when you make backwards-compatible bug fixes

Based on the commit messages, semantic-release increments one or none of these versions. These commit messages must follow the Angular commit message convention. An example is as follows, where the header is required and the body and footer are optional:

The following types can be used:

Some examples link

To help you out, you can either use commitizen or commitlint to follow this convention.

Oof, it seems like we have been derailed a bit here, back to semantic-release. To setup semantic-release inside your project we first have to install the cli globally or use the npx command. After this we can start setting up semantic-release with semantic-release init. You will have to answer a couple of questions but after this you’re good to go.

If you’re using CircleCI you can generate a token at https://circleci.com/account/api

The semantic-release init command changes the following items in the package.json file:

Because we’re releasing a library which is located in the projects folder, e.g. ./projects/ngx-testing-library, we’ll also have to make these changes manually inside the project’s package.json, eg ./projects/ngx-testing-library/package.json. This is because the project’s package.json will be used when we release a new version of the library.

Configuring the build steps link

Note that I already had a CircleCI config file. Because of this the semantic-release init command didn’t create one. If you’re running the cli in a clean repository it will create the following config.yml for you.

If I add the release script to my existing config, it looks like this:

Without going into too much detail, the above configuration will do the following:

This build process can be seen (live), if you go to the workflows tab.

If one of the steps fails, it aborts the following build steps.

This will release our whole directory, but we only want to release our library which is located in the **dist** folder, more specifically dist/ngx-testing-library. Therefore we have to set the pkgRoot inside the semantic-release configuration, we can do this by adding a release entry inside the package.json.

Configuring CircleCI link

To enable CircleCI you can login using your GitHub account. Once you’re logged in you can enable CircleCI on a per-project basis. This can be done by going to the Add project tab. Go to your project and click on Set up project and follow the instructions on the page.

projects tab
add project

Once your project is configured, you’ll have to add a GitHub and npm token in order to release a new version as a CI step. This can be done via the environment variables tab of your project.

If you don’t have a GitHub token you can generate one via the settings of your GitHub repository.

manage deploy keys in github

The same applies for an npm token, if you don’t have one you can generate one via your profile settings.

npm tokens

Once both of the tokens are generated you can set them as environment variables in CircleCI by using GH_TOKEN for your GitHub token and NPM_TOKEN for your NPM token.

environment variables tab

If you push a commit to your GitHub repository by using the commit message convention, it will now publish your library/application.

Finally, we can start checking a couple of items off our list! So far we have:

✅ Only release when the build passes

🔲 Only release when the push has been made to the master branch

✅ Release the new version to npm

✅ Release the new version to GitHub

🔲 Keep the CHANGELOG up to date️

This means there would also be a new release if you push to another branch which is not the master branch. This is something we, and definitely our users, wouldn’t want.

Configuring the release step link

To only release a new version when the master branch receives a push we’ll have to add a filter on the release job.

This means we can check off another item from our list!

✅ Only release when the build passes

✅ Only release when the push has been made to the master branch

✅ Release the new version to npm

✅ Release the new version to GitHub

🔲 Keep the CHANGELOG up to date️

The last item to tick off is updating the CHANGELOG automatically.

CHANGELOG link

When semantic-release releases a new version to GitHub, it also adds the commit message(s) related to the release in the release notes. Because of this I don’t see the need to maintain a CHANGELOG since it’s already documented with each release. For example, these are the release notes of the ngx-testing-library:

commit messages are shown with each release — these also include the commit hastag and the pull request id

These release notes can be seen via the release page in a GitHub repository, for example https://github.com/timdeschryver/ngx-testing-library/releases. The only step left is to refer to the release page inside the CHANGELOG.

If you would want to generate a CHANGELOG, I would suggest taking a look at the standard-version library. For an example you can always take a look at the angular-ngrx-material-starter project.

changelog referenecs to the release page

With this last step we can check off every item on the list!

✅ Only release when the build passes

✅ Only release when the push has been made to the master branch

✅ Release the new version to NPM

✅ Release the new version to GitHub

✅ Keep the CHANGELOG up to date️

Result and conclusion link

By simply installing semantic-release and holding ourselves (and contributors/your team) to a commit message convention, which is not a bad thing, we can automate our whole release flow.

With each commit against the master branch we test and build our library, and make sure we didn’t break anything by testing the example app. If everything turns green we release a new version to GitHub and npm.

As a last note I would say go check out ngx-testing-library and while you’re there you might as well give it a ⭐️.

TLDR link

✅ Only release when the build passes

✅ Only release when the push has been made to the master branch

everything turns green and we make a new release

✅ Release the new version to NPM

npm versions

✅ Release the new version to GitHub

✅ Keep the CHANGELOG up to date️

GitHub release page

Not to miss: GitHub Actions link

With GitHub Actions we can do the same directly via GitHub, which does the same job but without the need to glue different services together.

For more information about GitHub Actions, I’m going to refer you to Sarah Drasner’s post Introducing GitHub Actions

Feel free to update this blog post on GitHub, thanks in advance!

Join My Newsletter (WIP)

Join my weekly newsletter to receive my latest blog posts and bits, directly in your inbox.

Support me

I appreciate it if you would support me if have you enjoyed this post and found it useful, thank you in advance.

Buy Me a Coffee at ko-fi.com PayPal logo

Share this post