OT-2 internal releases
Internal OT-2 builds. App and robot OS share the same calendar version with an
internal@ tag prefix in both
opentrons-ot2 and
buildroot.
Calendar semver (internal)
Same Eastern calendar year and month as external, but the patch encodes day + same-day build number:
DNN = day × 100 + build_num (build_num is 1–99 per day)
Examples for May 26, 2026:
| Tag | Meaning |
|---|---|
internal@26.5.2601 | First stable internal build that day |
internal@26.5.2602 | Second stable internal build same day |
internal@26.5.101 | First stable internal build on May 1 |
Stack repos
| Repo | Role | Tag pattern |
|---|---|---|
opentrons-ot2 | App (taggable) | internal@YY.M.DNN |
buildroot | OT-2 robot OS | Same as app |
Robot-stack tooling
just go, just track-builds, and just invalidate-cloudfront
are advisory: they sync local clones under this workspace, print tables and analysis,
and emit copy-paste commands. A human (or agent) runs git tag -a, git push,
and aws cloudfront create-invalidation elsewhere. Nothing here pushes tags, triggers CI,
or invalidates CloudFront by itself.
robot-stack-infra is always cloned for reference; it is not included in release
tagging tables.
Plan a release non-interactively, for example:
just go --non-interactive --skip-assumptions --path flex --release-type external --stability stable
Release branch
OT-2 internal tags default-branch HEAD. No
chore_release branch is used.
| Repo | Default branch |
|---|---|
opentrons-ot2 | edge |
buildroot | opentrons-develop |
When does just go say a new tag is needed?
For each repo, automation/go.py uses the release branch described
above, finds the newest annotated tag for the selected channel on that branch
(sorted by creator date, merged into the branch), and compares the branch tip commit.
New tag needed when the branch tip commit is not the same commit as that latest channel tag.
No new tag needed when branch HEAD already matches the latest channel tag.
Tags must be annotated (git tag -a … -m 'chore(release): …') so
git tag -l --sort=-creatordate reflects real release order. Stack repo tag messages
often reference the monorepo release version.
Pushing a tag triggers CI builds in the tagged repo. The app monorepo tag drives app artifacts; stack repo tags drive robot OS and firmware builds.
How the next tag is chosen
go defaults the base version to today’s Eastern date
(YY.M.DNN with build_num = 1).
Stable internal
Collect tags for the same year, month, and day with no alpha/beta suffix.
Set the next build number to max(existing) + 1 (or 1 if none).
Alpha / beta internal
Same day and base patch, but tags gain a bare suffix: -alpha or -beta
(not -alpha.N). Same-day rebuilds still increment DNN in the patch.
Examples: internal@26.5.2601-alpha, internal@26.5.2602-alpha.
buildroot receives the matching tag when its branch is ahead of the latest internal tag.
Tag push order
Push annotated tags in this order. Dependent stack repos first, app monorepo last.
just go prints this reminder at the end of a release run.
| Step | Repo | Notes |
|---|---|---|
| 1 | buildroot | Robot OS, if a new tag is needed |
| 2 | opentrons-ot2 | App monorepo, always last |
OT-2 stack repos only get a new tag when their release branch tip is ahead of the latest channel tag on that branch.
Track release builds
After pushing the app tag, run (non-interactive form):
just track-builds --non-interactive --path ot2 --tag internal@26.5.2601 --wait
automation/track_builds.py locates GitHub Actions runs for:
- App workflow on the monorepo (
App test, build, and deploy) - Kickoff cross-repo dispatch (
Start OT-2 build) - Robot OS build in
buildroot
The Rich table lists key jobs (deploy, desktop builds, dispatch spawn, robot image build). The Slack copy block includes only two links:
OT-2 release `internal@26.5.2601` - app: <app workflow run URL> - ot2: <robot OS workflow run URL>
--wait polls every 15 seconds until app, kickoff, and robot OS
workflow runs all appear (default timeout 900 seconds). Polling checks workflow runs only; job
details are fetched afterward with retries for transient GitHub 404s. Exit code 2 if
a run is still missing after the timeout.
CloudFront invalidation
CI does not invalidate CloudFront automatically. After builds finish, print a copy-paste command (it does not run invalidation):
just invalidate-cloudfront --non-interactive --path ot2 --tag internal@26.5.2601
Invalidates /app/* and /ot2-br/* on the channel host.
Uses AWS profile robotics_robot_stack_prod-admin when credentials allow distribution
lookup; otherwise the script prints a lookup command and placeholder ID.
Validate published artifacts
Optionally regenerate live manifest inventories:
just assets-pages
Or per-platform reports: just flex-assets / just ot2-assets.
Pages: external assets,
internal assets.
Where to find published releases
Internal OT-2 artifacts live on ot2-development.builds.opentrons.com.
| Artifact | URL |
|---|---|
App releases.json |
https://ot2-development.builds.opentrons.com/app/releases.json |
Robot releases.json (source of truth) |
https://ot2-development.builds.opentrons.com/ot2-br/releases.json |
Robot releases.json is the source of truth for on-robot updates.
Desktop app updates use channel YAMLs (latest.yml, prerelease YAMLs) via
electron-updater; those YAMLs are authoritative.
App releases.json is parsed by a CloudFront edge function to pick the latest stable
semver from production and route latest* requests accordingly.
Electron-updater YAMLs for internal app builds:
alpha.ymlalpha-mac.ymlalpha-linux.ymlbeta.ymlbeta-mac.ymlbeta-linux.ymllatest.ymllatest-mac.ymllatest-linux.yml
See also: OT-2 internal assets.
Alpha and beta on OT-2 internal
In just go, choose Release type: internal and
Stability: alpha or beta.
| Stability | Tag example | Notes |
|---|---|---|
| Stable | internal@26.5.2601 | Same-day rebuilds bump DNN |
| Alpha | internal@26.5.2601-alpha | Bare -alpha suffix, not numbered |
| Beta | internal@26.5.2601-beta | Bare -beta suffix |
Internal alpha/beta differs from external OT-2: external uses numbered prereleases
(-alpha.0, -alpha.1) on the monthly build base for that release, while internal uses
unnumbered -alpha / -beta suffixes combined with the
day/build patch scheme.