Versions, channels and releases
One version for every artifact, stable releases and developer previews, and how to read the build a deployment runs.
One version number names everything OpenSmartRoute ships - the Python package, the osr command line, the
npm client, the platform API and web images, the Helm chart, the Compose bundle, the Azure Marketplace
package, the browser extension and the desktop app - and every deployment tells you which build it runs. This
page says what the numbers mean, how to read them on each surface, and how a release is made.
One version
The release version is X.Y.Z (Semantic Versioning). Every artifact of a release - the
packages, images, chart, extension and installers - is stamped from one source, and a consistency check fails
any build where a version drifts. There
is no separate extension version, desktop version, SDK version or platform version: pip install opensmartroute==1.3.0, npm install @opensmartroute/sdk@1.3.0, osr-platform-api:1.3.0, chart 1.3.0, the
extension 1.3.0 and OpenSmartRoute-1.3.0-win-x64.exe were all built from the tag v1.3.0.
- A minor release (
1.3.0->1.4.0) adds; the public Python API only grows. - A patch release (
1.3.0->1.3.1) fixes; nothing new is announced. - A major release may remove what was deprecated two minors earlier.
SECURITY.mdlists the supported versions: the current minor gets every fix; an earlier minor of the same major gets security fixes for 90 days after the minor that superseded it shipped (the table names the date); earlier majors get nothing. The table is computed from the changelog's release dates, so the window never depends on how quickly minors follow each other.
Cadence
Minor releases are cut when the [Unreleased] section carries something users need, at most once a week
unless a security fix or a broken release forces a patch; patch releases ship whenever a fix is ready. Every
release soaks as a developer preview on the hosted platform first (below). A minor that ships faster than
that is not wrong, but the 90-day window above is what protects the people who installed the one before it.
Two channels
Every build is either a stable release or a developer preview, decided from the git tags alone - no one types a build number:
| Channel | Built from | Version | Where it goes |
|---|---|---|---|
| stable | the tag vX.Y.Z | X.Y.Z | PyPI, npm, the image tags X.Y.Z / X.Y / latest, the release downloads, extension/latest.json, desktop/latest.json + latest*.yml, the browser stores |
| developer preview | any other commit on main | <next>-preview.<N> | the hosted platform (opensmartroute.ai), extension/preview.json, desktop/preview.json + preview*.yml |
<next> is the release the preview leads up to: the pyproject version while its tag does not exist yet
(a merged release pull request, about to be tagged), otherwise the next patch after the last release.
N counts the commits since the last release tag, so previews sort and read in order:
1.3.0 -> 1.3.1-preview.1 ... 1.3.1-preview.89 -> 1.4.0-preview.3 (release PR merged) -> 1.4.0.
The hosted platform deploys every merge to main by default, so what you use at opensmartroute.ai is the
developer preview of the next release - the [Unreleased] section of the changelog is what
it carries beyond the last stable release. Every release also redeploys the platform from its tag, so the
deployment moves to the stamped stable build (channel: stable, footer without the preview badge) once the
release is cut. An operator can pin production to releases only by setting OSR_DEPLOY_PREVIEWS=false in the
deployment's configuration: main keeps building and testing its images, the preview is reported but not
rolled out, and production changes only when a release is tagged. Self-hosted installations pull stable images
and stay on releases either way.
Browser manifests take up to four integers, so a preview extension carries X.Y.Z.N (1.3.1.89) in
manifest.json; Chrome and Edge show the readable label (1.3.1-preview.89) as version_name. A release
carries X.Y.Z. Previews are never submitted to the browser stores. The desktop installers carry the label in
their file names (OpenSmartRoute-1.3.1-preview.89-win-x64.exe) and a preview build's updater follows the
preview*.yml feed, so an installed release only ever updates to the next release.
Reading the version
| Surface | What it shows |
|---|---|
osr --version, opensmartroute.__version__ | the package release, 1.3.0 |
GET /api/v1/info -> build, GET /healthz -> build | {"version": "1.3.1-preview.89", "release": "1.3.0", "channel": "preview", "commit": "4ced2b2..."} on a published image; channel is null for a checkout or a hand-built image, which report the release alone |
| the website footer | v<build version>; a developer preview badge when the deployment runs main ahead of the next release |
GET /api/v1/releases | every release's notes, the running build, and unreleased - what has landed since the last release (GET /api/v1/releases/{version} with unreleased as the version returns that section alone) |
GET /extension/release.json | the extension build offered for download with its channel; ?channel=preview for the preview, ?channel=stable for the release only |
GET /desktop/release.json | the same for the desktop app's installers |
| the dashboard's What's new card and the release mail | the stable release notes, sent once per release version - previews never announce |
| image labels | org.opencontainers.image.version and .revision on osr-platform-api and osr-platform-web (docker inspect) |
The build stamp reaches the images as build arguments (OSR_BUILD_VERSION, OSR_BUILD_CHANNEL,
OSR_BUILD_COMMIT) and the API as the settings
OSR_PLATFORM_BUILD_VERSION, OSR_PLATFORM_BUILD_CHANNEL and OSR_PLATFORM_BUILD_COMMIT. Anyone building the
image by hand can pass the same arguments (docker build --build-arg OSR_BUILD_VERSION=... ); without them the
image is honest about not knowing its channel.
Downloads
opensmartroute.ai/downloads always resolves to the current stable
release: /download/<artifact> redirects to the versioned file and /download/latest.json lists them with
SHA-256 checksums. Versioned files never change once published (cached for a year); the latest.json
pointers move with each release.
The browser extension follows the same rule with two pointers: /extension/download/<browser> offers the
stable release and /extension/download/<browser>?channel=preview the developer preview. While no stable
release of the extension has been published yet, the preview stands in and the page says so
(Browser extension, Where the packages come from). The desktop app is served the same way from
/desktop (/desktop/release.json?channel=preview, installers and update feeds under /desktop/download/).
Unreleased changes
Every user-visible change lands as a bullet under ## [Unreleased] in the changelog the moment it merges -
that section is the developer preview's release notes and the draft of the next release's. The website
renders it on the changelog page, GET /api/v1/releases returns it as unreleased, and it becomes
the dated ## [X.Y.Z] section when the release is cut. Nothing is announced to users until then:
the release mail and the What's new card key off the stable release version.
How a release is made
Releases are cut in two steps from the main branch; nobody edits a version or a tag by hand.
- Prepare: the version is bumped everywhere at once,
[Unreleased]rolls into[X.Y.Z] - date, the compare links and the supported-versions table are refreshed, and the change is reviewed like any other. From the moment it merges, main-branch builds areX.Y.Z-preview.N- release candidates of X.Y.Z. - Release: the consistency check and the full test and routing gates run, the packages are built, the
annotated tag
vX.Y.Zis created (its message is the changelog section), PyPI and npm are published, the images are stampedstable, the Compose bundle, Helm chart and Marketplace zip land on the downloads page, and the extension and desktop builds follow on the tag (stable packages behindlatest.json, store submissions). Everything is then fetched back the way a user would: the PyPI files must match the built checksums, the image must report the version and answer/readyz, and the extension and desktop pointers the website serves and the platform's/api/v1/info(build, platform package, SDK) must all answerX.Y.Z- a channel left behind fails the release by name instead of staying on the previous version unnoticed. Firefox signing by Mozilla cannot hold a release back: when its review outlasts the wait, the other browsers ship and the signed.xpicompletes the manifest as soon as Mozilla returns it. - Announce. The next deploy of the hosted platform runs the new version; its release-news job mails the digest of the changelog section to opted-in users once and the dashboard shows the What's new card (Platform guide, Campaigns).
A red verification stage means the release is not usable as published: fix forward with a patch release, never by moving a tag.