Releases and Deployment

UKRDC-Compose

https://github.com/renalreg/ukrdc-compose

We use Docker Compose to handle deployments of the UKRDC Dashboard. This allows us to bind together the API, frontend, and any dependencies such as Redis instances in a reproducible way. It also allows us to deploy different versions to different people (discussed further down).

On both live and staging, the application stack is deployed to /srv/ukrdc-compose. All deployment actions should happen from within that directory.

Updating Deployments

Once you've published your updated container images (see below), run ./update_and_restart.sh from within the deployment directory on the server.

This will pull the updated images, stop, and restart the containers with the new images.

Generally, we suggest also running docker system prune afterwards to clean out old images from the system.

A second convenience script, update_prune_and_log.sh, does the update and restart, prunes unused images, and then starts showing live logs from the containers. This can be particularly useful for checking deployments are working as expected.

Image Tags

Container images for https://github.com/renalreg/ukrdc-fastapi and https://github.com/renalreg/ukrdc-nuxt-3 are published on either a GitHub Release, or a manual workflow dispatch.

All published images are tagged with edge. The edge tag will always point to the most recently published image regardless of version number or publish method (i.e. release or manual).

Manual workflow dispatch will also tag the image with the branch name. For example, manually running a workflow on the main branch will tag the published image with both edge and main.

Pre-release GitHub releases (those with semantic version names with a pre-release suffix, e.g. v1.0.1-beta.1) publish a container image tagged with the version number, and edge. For example, creating a GitHub release with the name v1.0.1-beta.1 will tag the published image with both edge and v1.0.1-beta.1.

Stable GitHub releases (those with semantic version names but no pre-release suffix) publish a container image tagged with the version number, edge, and latest. For example, creating a GitHub release with the name v1.0.1 will tag the published image with edge, latest, and v1.0.1.

In summary:

Workflow Trigger

Tag Name

Image Tags

Workflow Trigger

Tag Name

Image Tags

workflow_dispatch
(manual trigger)

N/A

edge
Branch name (e.g. main)

GitHub Release

Stable semantic version
(e.g. v1.0.0)

edge
latest
Version number (e.g. v1.0.0)

GitHub Release

Pre-release semantic version
(e.g. v1.0.0-beta.1)

edge
Version number (e.g. v1.0.0-beta.1)

GitHub Release

Any non-semantic release
(e.g. some-random-tag)

edge

Why do this?

While we make use of a staging environment, the database has a tendency to fall way out of sync with production/live. Generally then it's used as a first test, to ensure new releases deploy without errors.

Occasionally though, we implement changes significant enough that we want to internally test them within the production/live environment. To do this, we make use of the edge tag on our docker images.

The nginx config in is set so that internal staff will be served the most recent edge image, but external users will be served the most recent latest (stable) image.

If the most recently published image was a stable release, edge and latest will point to the same image, and all users will be served the same version. This should be the state the application is in most of the time.

Setting Versions

Both and have a setversion.sh script in their repositories to simplify setting application versions.

Use ./setversion.sh {version_number} to set the application version. E.g. ./setversion.sh 4.0.0-beta.1.

You can also use ./setversion.sh major, ./setversion.sh minor, and ./setversion.sh patch to automatically bump the version number by the appropriate amount for that type of release.

Versioning

The application version as defined in pyproject.toml will be used as the API version in all documentation and clients libraries. Therefore, the application version should follow semantic versioning for the API functionality, that is:

  • Major version changes should be accompanied by a breaking change in the API.

    • E.g. removing or changing the schema of returned data in existing API routes.

  • Minor version changes should be accompanied by a non-breaking change in the API.

    • E.g. adding new, additional data to existing routes, or adding new routes entirely.

  • Patch version changes should be accompanied by fixes or updates introducing no API changes.

    • E.g. bug fixes.

Versioning

The application version will generally follow the version of the API it is compatible with. Therefore, the application should follow semantic versioning for the API functionality, that is:

  • Major version changes should be accompanied by a breaking change in the API.

  • Minor version changes should be accompanied by a non-breaking change in the API.

  • Patch version changes should be accompanied by fixes or updates introducing no new API functionality.

Under this system, the major and minor application versions should be the same as the API client version, and the patch version should iterate on it's own with any changes not dependent on API functionality.

GitHub Release Names

Github releases should use tags that follow the application version. E.g. application version 1.0.1 will be tagged with v1.0.1.

Suggested Release Flow

  • Make all changes to bundle into a release

  • Iterate version number of the application to a pre-release (e.g. v1.0.0-beta.1) with setversion.sh (see above section), and push.

  • Create a matching pre-release using GitHub releases.

    • This will publish a docker image with a version-numbered tag, as well as the edge tag

  • Update and restart containers on staging first, and then live (once confirmed working on staging).

    • This will pull the edge build and route internal UKKA traffic to that edge build. External users will remain on the latest stable release (tagged latest).

Once internal testing is complete

  • Iterate version number of the application to a stable release (e.g. v1.0.0) with setversion.sh (see above section), and push.

  • Create a matching pre-release using GitHub releases.

    • This will publish a docker image with a version-numbered tag, as well as the edge tag and the latest tag.

  • Update and restart containers on staging and live environments.

    • This will pull the latest build and route external traffic to that stable build.