Semantic Version Your Web Extension

Emmanuel Ogbizi-Ugbe
Top Hat Engineering Blog
5 min readOct 18, 2020
Semantic Versioned Web Extension

Preamble

If you’ve written any application that relies on auto release versioning, then you’ve probably had to decide on an objective method for deciding the version numbers associated with a new release.

There are a number of versioning schemes and for this project we will be using semantic versioning. If you do not yet know about semantic versioning you should take some time to read up on it, useful link here Semantic Versioning.

Overall, semantic versioning appeals to me because of the strict but easy to understand, for both authors and consumers, guidelines. When releasing a new version of my application, or in this case web extension a simple number tells the user updating what to expect and in this guide we will also touch on automatically creating versions and changelogs using semantic commits.

Without Further Ado!

The scope of this tutorial will be

  1. Adding node to your project
  2. Setting up GitHub actions CI
  3. Adding build and release steps
  4. Profit?

Prerequisites

We will be using the following tools, feel free to skip if you already have them or some alternative installed in your environment.

Git | Github | NodeJS | Yarn

Ready, Set, Go!

Clone the starter repository, this includes a sample web extension for the purpose of this tutorial https://github.com/tophat/webext-training.

$ git clone git@github.com:tophat/webext-training.git
$ cd webext-training

Step 1: Create package.json

$ npm init
...
Is this OK? (yes) yes

This will give you a bunch of options you can fill in or ignore for now and at the end of the prompt you should have something like this

{
"name": "webext-training",
"version": "0.0.1",
"description": "Semantic versioning your web extension",
"main": "content.js",
"scripts": {
"test": "echo 'Good tests and continuous deployments make the world go round'"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tophat/webext-training.git"
},
"author": "iamogbz",
"license": "MIT",
"bugs": {
"url": "https://github.com/tophat/webext-training/issues"
},
"homepage": "https://github.com/tophat/webext-training#readme"
}

Note: The test script is a stub for now but can be easily configured to use any javascript testing framework.

Step 2: Add Dependencies

$ yarn add -D semantic-release @semantic-release/changelog semantic-release-chrome semantic-release-firefox-add-on

These are responsible for running the semantic release pipeline, with the second responsible for updating the repo changelog following the keepachangelog.com convention and the last 2, being plugins for Chrome and Firefox respectively.

Diff showing dependency changes to package.json

Note: Remember to commit your changes after each step.

Step 3: Release Configuration

You will need to either configure semantic-release by adding a release section to your package.json or creating a .releaserc file, see options.

$ vim .releaserc.json

We will be specifying a few things

  • Chrome extension ID
  • Mozilla extension ID
  • Location of packaged extension for each browser respectively
  • Source and artifacts directory for semantic-release-add-on, semantic-release-chrome defaults to the working directory which is suitable for now
{
"dryRun": true,
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"semantic-release-chrome",
{
"extensionId": "ffifqrxowctbwefuzphbhgsreeltlrhw",
"asset": "webext-training.zip"
}
],
[
"semantic-release-firefox-add-on",
{
"artifactsDir": ".",
"extensionId": "biciwyjkdhcmbrkuugxdpxmsccxdiyib",
"sourceDir": ".",
"targetXpi": "webext-training.xpi"
}
],
[
"@semantic-release/github",
{
"assets": [
{
"path": "webext-training.zip"
},
{
"path": "webext-training.xpi"
}
]
}
]
]
}

Note: The dryRun flag is useful to catch errors in your configuration before semantic-release will attempt to publish the release.

Step 4: Enable Github Actions

Configure GitHub CI workflow to run tests and release on the master branch.

$ mkdir .github/workflow
$ vim .github/workflow/nodejs.yml

We will be specifying a few things

  • The name of our workflow i.e. Build
  • When we want this workflow to be to run i.e. on push
  • The os environment using a docker image i.e ubuntu-latest
  • Checking out the repo branch commit code
  • Setting up a version of node in the environment i.e. 12.x
  • Installing the project dependencies i.e. yarn install
  • Running tests and coverage to confirm changes are good i.e.yarn test
  • When to run the deploy using semantic-release, in this case on master i.e. github.ref == 'ref/heads/master'
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Setup
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: Install
run: |
yarn install
- name: Test
env:
CI: true
run: |
yarn test --ci --coverage
- name: Release
if: github.ref == 'refs/heads/master'
run: |
yarn semantic-release

See here for an introduction to github actions.

Note: After committing and pushing to GitHub, you should see the action run and publish a status. It will likely fail, but that’s where the next step comes in.

Step 5: Add CI Environment Variables

Some of the semantic-release plugins need environment variables to be present before they can be successfully run. These can be added to your repository secrets and made available to the build GitHub action pipeline by visiting https://github.com/USER/REPO/webext-training/settings/secrets.

After adding these to your GitHub repo settings secrets, they can now be included in your GitHub action workflow pipeline.

Diff showing changes to GitHub actions workflow nodejs.yml

Once you commit and push your CI should build successfully and the dry run release should complete with no hiccups. 🥳🎉

Once you feel comfortable with your current setup, remove the dryRun flag from the release config and watch the magic happen.

Extras

Maybe you’re wondering how you can ensure your commits are semantic? Then look no further, you can easily extend your existing setup to lint commits and help with writing semantic commits.

Lint commits to ensure semantic correctness before they are written.

$ yarn add -D @commitlint/cli @commitlint/config-conventional husky

The first two handle linting the commit messages while the last is a useful package for running commands on git hooks.

Diff showing changes for commit linting using git hooks

Now all commit messages are checked to ensure maximum semanticity.

Construct semantically correct commits using semantic conventions.

yarn add -D commitizen cz-conventional-changelog

The first is the tool for writing commits while the second defines the prompts.

Diff showing changes for git semantic commit prompt

Now you can write semantic commits using yarn commit.

Hope this was a good first or return expedition into the land of semantic versioning.

--

--