Releasing frontend modules
Releasing (opens in a new tab) frontend modules is a critical part of the development process. After meeting a reasonable threshold of commits, or after a set amount of time, you will likely want to publish your software to the NPM registry so that consumers can install it. This guide will walk you through the process of releasing frontend modules in the O3 ecosystem.
O3 currently follows a release cadence of two weeks. This means we aim to publish new versions of our frontend to our QA environment (opens in a new tab) every fortnight. QA review and feedback typically takes a week, after which we promote the release to our demo Production environment (opens in a new tab). This cadence is subject to change as we get more experience with the process.
Cutting a release
Please read through the Important notes section at the end of this page for guidance on some oft-overlooked steps in the release process.
Cutting an O3 release involves two steps:
- Bumping your local package versions and pushing those changes to GitHub. This step will trigger the CI's
pre-release
job. - Cutting a release using the Github releases UI. This step triggers the
release
CI job, which publishes the package(s) to the NPM registry.
If you want to publish a release version of your module, you need to think about a few things first, including:
-
The release
type
- the semantic versioning release type (opens in a new tab) your changes conform to. Our release versions use the SemVer spec, meaning we have three release types:patch
- when you make backwards-compatible bug fixes.minor
- when you add functionality in a backwards-compatible manner.major
- when you make incompatible API changes.
For example, if the most recently released version number for a frontend module is
v1.0.0
:- A
patch
version would increment the version number to1.0.1
. - A
minor
version would increment the version number to1.1.0
. - A
major
version would increment the version number to2.0.0
.
Drafting a changelog
With that knowledge, you can draft a changelog. To do so:
- Go to the
releases
page of your monorepo, and clickDraft a new release
. - Click the
Choose a tag
button in the releases page UI. Choose any tag, sayv1.0.1
for apatch
release if the most recent version isv1.0.0
. We will likely change this shortly after reviewing the changelog. Set that value as the release title as well. Next, click theGenerate release notes
button.
We have established a convention within O3 where PR titles contain a conventional commit type
value that describes the kind of change the PR makes. These include:
(feat)
for new features(fix)
for bug fixes(refactor)
for refactors(test)
for tests(docs)
for documentation(chore)
for housekeeping tasks, like managing dependencies, configuring things or updating CI workflows(BREAKING)
for backwards-incompatible API changes.
Reviewing the generated changelog with these commit types in mind should give you a good idea of the semantic version bump your release should create.
Bumping versions
At this point, you can switch to your IDE to initiate the release process. Typically, we use yarn
to version frontend modules.
Monorepos
For monorepos, we use the workspaces
command to bump versions across all packages in the monorepo. You'll typically find a release
script in the root-level package.json
file of the monorepo that looks like this:
"release": "yarn workspaces foreach --all --topological version"
This script runs the version
command against all the packages in the workspace. You'll need to append the release type to this command to trigger a version bump. So, for a major
release, you would run:
yarn release major
This command:
- Runs the
version
command against all the packages in the workspace and bumps them to a major version. For example, if the current version is1.0.0
, it would get bumped to2.0.0
.first-letter. - Tells yarn to sort the packages before running the commands so that they run on the packages in topological order (i.e., packages that depend on other packages get run later).
- Tells yarn to exclude versioning for the selected monorepo so that the package.json in the root directory is unaffected. The root
package.json
does not require a version for publishing purposes because it is never published.
Non-monorepos
For non-monorepos, you can use the version
command directly. For example, if you want to bump the version of a package named @openmrs/esm-patient-management
to a major
release, you would run:
yarn version major --workspaces --scope @openmrs/esm-patient-management
Libraries using legacy versions of yarn
Some of our projects use legacy versions of yarn (yarn v1). The Angular form engine (opens in a new tab) is an example of such a project. To release the Angular form engine, you would run the following command:
yarn version --new-version <major|minor|patch> --no-git-tag-version
Be sure to follow the instructions listed in the Cutting a release docs (opens in a new tab) to avoid getting caught out.
Post-bump steps
Once you're done versioning, you should see a diff in your editor that includes a version bump for all the packages in your repository. Run yarn
or yarn install
to update your yarn.lock
file.
Create a new branch named chore/release-vX.X.X
where X.X.X
is the version number you are releasing. Commit these changes with the title (chore) Release vX.X.X
. See an example of this commit (opens in a new tab) that bumps Patient Chart
to v5.0.0
.
Once your release commit is merged, the CI workflow's pre-release
job gets triggered and initiates a version bump for the corresponding version tagged latest
on NPM. This version is what consumers get when they install your frontend module.
Releasing on GitHub
You can then switch to your browser and head back to the releases page of the repo you are working with. Review the release notes generated by GitHub and then update the version number and tags appropriately.
Release notes should match the format of the O3 changelog. This format includes a title, a
description, and a list of changes. The main categories of changes are Features
, Bug Fixes
, Breaking Changes
,
Refactors
, Docs
and Tests
. Each category should have a list of changes under it. You might need to do a bit more
work to get the changelog to match this format. It's worth the effort, as it makes it easier for the Release Manager
to review the changes and prepare release notes for the community.
Once you are satisfied that everything looks ok, click the Publish release
button. This step should trigger the CI workflow and, notably, the release
job.
Under the hood, that job runs the following script:
"ci:prepublish": "yarn workspaces foreach --all --topological npm publish --access public --tag next",
This command publishes a new package tagged next
. This is the version that consumers will get when they install your frontend module with the next
tag. This is useful for testing new features before they get released to the latest
tag.
Broadly speaking, when a PR is merged, a pre-release
job in our primary GitHub actions CI workflow gets triggered. This job publishes a version of the frontend module to its corresponding npm registry tagged latest
. This is the version that consumers will get when they install your frontend module.
To see what version the latest
tag corresponds to for a frontend module, go to its NPM registry page and click on the version
tag. Look out for the most recent version tagged latest
.
Important notes
- When versioning the Angular form engine (opens in a new tab), ensure you bump both the version in the root-level
package.json
file and the version in thepackage.json
file in theprojects/openmrs-esm-formentry
directory. The actual library is published from that directory, so it's important to bump the version there as well. More information can be found in this section (opens in a new tab) of the README. - When versioning the Patient Chart (opens in a new tab), ensure you bump the Common Lib peer dependency in each of the packages that depend on it. Here's an example of a release commit that bumps both the package version and the peer dependency version: chore: Release v7.0.0 (opens in a new tab).