Skip to content

Commit

Permalink
Added a versioning policy to the documentation.
Browse files Browse the repository at this point in the history
Closes #8748.
  • Loading branch information
fniessink committed Jun 8, 2024
1 parent 1d4ff49 commit 512a8e4
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 18 deletions.
3 changes: 2 additions & 1 deletion docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

### Deployment notes

If your currently installed *Quality-time* version is v4.10.0 or older, please read the v5.0.0 deployment notes first.
If your currently installed *Quality-time* version is not v5.13.0, please read the [versioning policy](versioning.md) first.

### Fixed

Expand All @@ -22,6 +22,7 @@ If your currently installed *Quality-time* version is v4.10.0 or older, please r

- Group digits in numbers. Closes [#8076](https://github.com/ICTU/quality-time/issues/8076).
- In the measurement entity status menu, the description of the menu items would say "undefined days" if the desired response time for the status had not been changed from its default value. Fixes [#8284](https://github.com/ICTU/quality-time/issues/8284).
- Added a [versioning policy](versioning.md) to the documentation. Closes [#8748](https://github.com/ICTU/quality-time/issues/8748).
- Allow for specifying supported source versions in the data model. Show the supported source version in the UI and the reference documentation. Closes [#8786](https://github.com/ICTU/quality-time/issues/8786).

### Changed
Expand Down
12 changes: 10 additions & 2 deletions docs/src/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ This document describes how to deploy, and if needed move, the *Quality-time* ap

*Quality-time* furthermore assumes an LDAP service is available to authenticate users or that forwarded authentication is used.

```{warning}
Before skipping versions or downgrading, see the [version policy](versioning.md).
```

## Docker-composition

This document assumes docker-compose is used to deploy the containers. The [docker folder](https://github.com/ICTU/quality-time/tree/master/docker) of the *Quality-time* repository contains different compose files for running *Quality-time* in development and continuous integration mode. You can use these compose files as basis for your own deployment configuration.

```{note}
Per the [version policy](versioning.md), if the docker-composition needs changes, this will be indicated by a new major release of *Quality-time*.
```

To deploy *Quality-time* locally, follow these steps:

1. Make a directory, e.g. `quality_time` and change directory to it.
Expand Down Expand Up @@ -126,7 +134,7 @@ By default, the notifier wakes up every minute to check for changed metric statu

## Configuring MongoDB credentials (optional)

The default MongoDB credentials can be changed as follows:
The default {index}`MongoDB` credentials can be changed as follows:

```yaml
database:
Expand All @@ -139,7 +147,7 @@ See the [documentation on the MongoDB image](https://hub.docker.com/_/mongo) for

## Configuring renderer localisation (optional)

The date/time format and timezone of the reports that user sees are determined by the user's browser. To configure the date/time format and timezone of exported PDFs, the renderer can be configured as follows:
The date/time format and timezone of the reports that a user sees are determined by the user's browser. To configure the date/time format and timezone of exported PDFs, the renderer can be configured as follows:

```yaml
renderer:
Expand Down
12 changes: 7 additions & 5 deletions docs/src/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,16 @@ python release.py --help

### Decide the release type

*Quality-time* adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), so first you need to decide on the type of release you want to create:
*Quality-time* adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), so first you need to decide on the type of release you want to create, conform the [release policy](versioning.md#major-minor-and-patch-releases).

- Create a **major** release if the next release contains backwards incompatible changes, and optionally other changes and bug fixes.
- Create a **minor** release if the next release contains non-breaking changes, and optionally bug fixes.
- Create a **patch** release if the next release contains bug fixes only.
- Create a **major** release if the docker-composition needs to be changed to deploy the next release
- Create a **minor** release if the next release contains new or changed functionality.
- Create a **patch** release if the next release contains only bug fixes.

If you want to test the release (for example, deploy it to a test environment, or roll out a release to early adopters), it's possible to create a **release candidate** for a major, minor, or patch release.

If the release type is major, minor, or patch, update the [version overview](versioning.md#version-overview).

```{important}
To determine whether a release is major, minor, or patch, compare the changes to the [previous most recent release](changelog.md), excluding release candidates.
```
Expand Down Expand Up @@ -534,7 +536,7 @@ Base images used in the Docker containers, and additionally installed software,
- [Collector](https://github.com/ICTU/quality-time/blob/master/components/collector/Dockerfile): the Python base image.
- [Notifier](https://github.com/ICTU/quality-time/blob/master/components/notifier/Dockerfile): the Python base image.
- [Frontend](https://github.com/ICTU/quality-time/blob/master/components/frontend/Dockerfile): the Node base image, the curl version, the npm version, and the serve version.
- [Database](https://github.com/ICTU/quality-time/blob/master/components/database/Dockerfile): the MongoDB base image.
- [Database](https://github.com/ICTU/quality-time/blob/master/components/database/Dockerfile): the {index}`MongoDB` base image.
- [Proxy](https://github.com/ICTU/quality-time/blob/master/components/proxy/Dockerfile): the Nginx base image.
- [Renderer](https://github.com/ICTU/quality-time/blob/master/components/renderer/Dockerfile): the Node base image, the curl version, the Chromium version, and the npm version.
- [Test data](https://github.com/ICTU/quality-time/blob/master/components/testdata/Dockerfile): the Python base image.
Expand Down
1 change: 1 addition & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ reference.md
```{toctree}
:maxdepth: 1
:caption: Technical documentation 🛠
versioning.md
deployment.md
development.md
software.md
Expand Down
6 changes: 2 additions & 4 deletions docs/src/software.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,12 @@ The proxy uses the following environment variables:

## Database

The database component consists of a [Mongo](https://www.mongodb.com) database to store reports and measurements.
The database component consists of a [MongoDB](https://www.mongodb.com) database to store reports and measurements.

The proxy [Dockerfile](https://github.com/ICTU/quality-time/blob/master/components/database/Dockerfile) wraps the MongoDB image in a *Quality-time* image so the MongoDB version number can be changed when needed.
The proxy [Dockerfile](https://github.com/ICTU/quality-time/blob/master/components/database/Dockerfile) wraps the {index}`MongoDB` image in a *Quality-time* image so the MongoDB version number can be changed when needed.

*Quality-time* stores its data in a Mongo database using the following collections: `datamodels`, `measurements`, `reports`, `reports_overviews`, and `sessions`.

The two server components are the only components that directly interacts with the database.

Data models, reports, and reports overviews are [temporal objects](https://www.martinfowler.com/eaaDev/TemporalObject.html). Every time a new version of the data model is loaded or the user edits a report or the reports overview, an updated copy of the object (a "document" in Mongo-parlance) is added to the collection. Since each copy has a timestamp, this enables the API-server to retrieve the documents as they were at a specific moment in time and provide time-travel functionality.

### Environment variables
Expand Down
59 changes: 59 additions & 0 deletions docs/src/versioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Versioning policy

This document describes the *Quality-time* versioning policy. It is aimed at *Quality-time* operators and developers.

## Major, minor, and patch releases

*Quality-time* complies with [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

A new **major** release of *Quality-time* is made when operators need to make changes to the Docker composition (besides upgrading version numbers) before upgrading *Quality-time*.

A new **minor** release of *Quality-time* is made when the new version has new or changed functionality.

A new **patch** release of *Quality-time* is made when the new version has only bug fixes.

```{index} MongoDB
```

## Version overview

The table below contains the *Quality-time* releases since the last minor of the previous major release. For each release it shows the release date, the MongoDB version included, the MongoDB feature compatibility (FC) version set in the database, whether migration code was added or removed, and whether up- or downgrading is possible, and if so, to which versions.

| Version | Release date | MongoDB | MongoDB FC | Migrations | Downgrade | Upgrade |
|------------|--------------|---------|------------|------------|----------------|-----------------|
| v5.14.0 | (unreleased) | v7 | v6 | added | not possible | n/a |
| v5.13.0 | 2024-05-23 | v7 | v6 | added | not possible | v5.14.0 |
| v5.12.0 | 2024-05-17 | v7 | v6 | added | not possible | v5.13.0-v5.14.0 |
| v5.11.0 | 2024-04-22 | v7 | v6 | | v5.6.0-v5.10.0 | v5.12.0-v5.14.0 |
| v5.10.0 | 2024-04-15 | v7 | v6 | | v5.6.0-v5.9.0 | v5.11.0-v5.14.0 |
| v5.9.0 | 2024-03-22 | v7 | v6 | | v5.6.0-v5.8.0 | v5.10.0-v5.14.0 |
| v5.8.0 | 2024-02-16 | v7 | v6 | | v5.6.0-v5.7.0 | v5.9.0-v5.14.0 |
| v5.7.0 | 2024-01-31 | v7 | v6 | | v5.6.0 | v5.8.0-v5.14.0 |
| v5.6.0 | 2024-01-12 | v7 | v6 | added | not possible | v5.7.0-v5.14.0 |
| v5.5.0 | 2023-12-15 | v7 | v6 | | v5.1.0-v5.4.0 | v5.6.0-v5.14.0 |
| v5.4.0 | 2023-12-11 | v7 | v6 | | v5.1.0-v5.3.1 | v5.5.0-v5.14.0 |
| v5.3.1 | 2023-11-08 | v7 | v6 | | v5.1.0-v5.3.0 | v5.4.0-v5.14.0 |
| v5.3.0 | 2023-11-07 | **v7** | v6 | | v5.1.0-v5.2.0 | v5.3.1-v5.14.0 |
| v5.2.0 | 2023-09-29 | v6 | v6 | | v5.1.0 | v5.3.0-v5.14.0 |
| v5.1.0 | 2023-09-05 | v6 | **v6** | | not possible | v5.2.0-v5.14.0 |
| v5.0.1 | 2023-06-26 | v6 | v5 | | v4.10.0-v5.0.0 | v5.1.0-v5.2.0 |
| **v5.0.0** | 2023-06-23 | **v6** | v5 | | v4.10.0 | v5.0.1-v5.2.0 |
| v4.10.0 | 2023-04-26 | v5 | v5 | | n/a | v5.0.0-v5.2.0 |

## Background information on down- and upgrade limitations

There are two factors that limit to which versions an existing *Quality-time* instance can be upgraded or downgraded: MongoDB and migration code.

### MongoDB

*Quality-time* uses MongoDB as database. MongoDB sets a feature compatibility version in the database to specify which major version of MongoDB the persisted data is compatible with. When upgrading MongoDB to a new major version, the feature compatibility flag should be set to the previous major version, and only when the upgrade was successful should the feature compatibility flag set to the new major version of MongoDB.

In general, when the feature compatibility of a database is set to version `x`, the database can only be used with MongoDB versions `x` and `x+1`. This limits the down- and upgrade options of *Quality-time* as documented in the table above.

```{seealso}
See the [MongoDB documentation](https://www.mongodb.com/docs/manual/reference/command/setFeatureCompatibilityVersion/) on the feature compatibility version.
```

### Migration code

To support changes in the *Quality-time* functionality, data in the database may need to be restructured. To this end, the API-server may run migration code on startup. This migration code is idempotent, meaning that whenever data already has been migrated it does not make any changes. However, migration code is not reversible, meaning that going back a minor or major update is not possible when a release contains new migration code.
34 changes: 28 additions & 6 deletions release/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_version() -> str:
return latest_tag.tag.tag.strip("v")


def parse_arguments() -> tuple[str, bool]:
def parse_arguments() -> tuple[str, str, bool]:
"""Return the command line arguments."""
current_version = get_version()
description = f"Release Quality-time. Current version is {current_version}."
Expand All @@ -42,7 +42,8 @@ def parse_arguments() -> tuple[str, bool]:
- the workspace has no uncommitted changes
- the workspace has no untracked files
- the changelog has an '[Unreleased]' header
- the changelog contains no release candidates"""
- the changelog contains no release candidates
- the new release has been added to the version overview"""
parser = ArgumentParser(description=description, epilog=epilog, formatter_class=RawDescriptionHelpFormatter)
allowed_bumps_in_rc_mode = ["rc", "rc-major", "rc-minor", "rc-patch", "drop-rc"] # rc = release candidate
allowed_bumps = ["rc-patch", "rc-minor", "rc-major", "patch", "minor", "major"]
Expand All @@ -52,10 +53,10 @@ def parse_arguments() -> tuple[str, bool]:
"-c", "--check-preconditions-only", action="store_true", help="only check the preconditions and then exit"
)
arguments = parser.parse_args()
return arguments.bump, arguments.check_preconditions_only
return arguments.bump, current_version, arguments.check_preconditions_only


def check_preconditions(bump: str) -> None:
def check_preconditions(bump: str, current_version: str) -> None:
"""Check preconditions for version bump."""
messages = []
release_folder = get_release_folder()
Expand All @@ -64,6 +65,7 @@ def check_preconditions(bump: str) -> None:
root = release_folder.parent
messages.extend(failed_preconditions_repo(root))
messages.extend(failed_preconditions_changelog(bump, root))
messages.extend(failed_preconditions_version_overview(current_version, root))
if messages:
formatted_messages = "\n".join([f"- {message}" for message in messages])
sys.exit(f"Please fix these issues before releasing Quality-time:\n{formatted_messages}\n")
Expand Down Expand Up @@ -105,11 +107,31 @@ def failed_preconditions_changelog(bump: str, root: pathlib.Path) -> list[str]:
return messages


def failed_preconditions_version_overview(current_version: str, root: pathlib.Path) -> list[str]:
"""Check that the version overview is properly prepared."""
version_overview = root / "docs" / "src" / "versioning.md"
with version_overview.open() as version_overview_file:
version_overview_lines = version_overview_file.readlines()
missing = f"The version overview ({version_overview}) does not contain"
previous_line = ""
for line in version_overview_lines:
if line.startswith(f"| v{current_version} "):
if previous_line.startswith("| v"):
today = datetime.date.today().isoformat()
release_date = previous_line.split(" | ")[1].strip()
if release_date != today: # Second column is the release date column
return [f"{missing} the release date. Expected today: '{today}', found: '{release_date}'."]
return [] # All good: current version, next version, and release date found
return [f"{missing}) the new version."]
previous_line = line
return [f"{missing} the current version ({current_version})."]


def main() -> None:
"""Create the release."""
os.environ["RELEASE_DATE"] = datetime.date.today().isoformat() # Used by bump-my-version to update CHANGELOG.md
bump, check_preconditions_only = parse_arguments()
check_preconditions(bump)
bump, current_version, check_preconditions_only = parse_arguments()
check_preconditions(bump, current_version)
if check_preconditions_only:
return
# See https://github.com/callowayproject/bump-my-version?tab=readme-ov-file#add-support-for-pre-release-versions
Expand Down

0 comments on commit 512a8e4

Please sign in to comment.