Flex internal releases
Internal Flex builds for Opentrons staff and early validation.
App tags use an ot3@ prefix in
opentrons.
Stack repos
| Repo | Role | Internal tag pattern |
|---|---|---|
opentrons | App (taggable) | ot3@X.Y.Z, alpha ot3@X.Y.Z-alpha.N, beta ot3@X.Y.Z-beta.N |
oe-core | Flex robot OS | Same coordinated tag as app (e.g. ot3@X.Y.Z-beta.N) |
ot3-firmware | Flex firmware | Same ot3@* as app + integer vN on same commit |
Robot-stack tooling
just go-plan, just apply-release-plan, just track-builds,
just invalidate-cloudfront, and just verify-release-assets support releases.
just go-plan syncs local clones and writes a reviewable YAML plan under
.build/plans/<app-tag>.plan.yaml. After review, just apply-release-plan
can create and push tags in push order (with resume after partial apply). CloudFront invalidation runs
only when the operator passes --execute to just invalidate-cloudfront.
just go remains available for interactive tables and copy-paste tag commands.
robot-stack-infra is always cloned for reference; it is not included in release
tagging tables.
Plan a release non-interactively (agent default):
just go-plan --path flex --release-type internal --stability beta --version v4.0.0
Apply after review:
just apply-release-plan --plan .build/plans/ot3@4.0.0-beta.0.plan.yaml --dry-run just apply-release-plan --plan .build/plans/ot3@4.0.0-beta.0.plan.yaml --yes
Release branch
Flex internal defaults to each repo's default branch
(opentrons: edge; oe-core / ot3-firmware:
main). Override with --app-branch and
--stack-branch REPO=BRANCH when a release flavor ships from a named branch.
| Repo | Default branch |
|---|---|
opentrons | edge |
oe-core | main |
ot3-firmware | main |
Default version inference: highest ot3@X.Y.Z base in the app repo tag catalog.
When does just go say a new tag is needed?
For each repo, automation/go.py uses the release branch described
above and the coordinated stack tag for the selected stability lane. It compares branch tip commit
to whether that coordinated tag already points at HEAD.
New tag needed when the coordinated tag for this release is missing on the branch or branch HEAD has moved since that tag.
No new tag needed when branch HEAD already matches the coordinated tag.
Flex app tag numbers come from the app monorepo tag catalog
(opentrons or opentrons-ot2). At one semver base, stable, alpha, and beta
are independent lanes (for example ot3@4.0.0-alpha.3 and
ot3@4.0.0-beta.0 can coexist). Change logs compare against the prior tag in the
same lane on the release branch.
Tags must be annotated (git tag -a … -m 'chore(release): …').
When the release branch differs from the repo default, tag blocks print
git checkout <release-branch> first.
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
In just go, Flex uses Stability: stable,
alpha, or beta.
App (opentrons)
- Stable:
ot3@X.Y.Zif not already in the app repo; otherwise patch bump (e.g.ot3@8.5.0→ot3@8.5.1). - Alpha: increment
ot3@X.Y.Z-alpha.Nfrom existing alpha tags at that base in the app repo (first alpha isot3@8.5.0-alpha.0). - Beta: increment
ot3@X.Y.Z-beta.Nfrom existing beta tags at that base. Alpha and beta are independent lanes:ot3@4.0.0-alpha.3andot3@4.0.0-beta.0can coexist. - Change logs compare against the prior tag in the same lane on the release branch.
Robot OS (oe-core)
Uses the same ot3@* stack tag as the app.
Firmware (ot3-firmware)
Tag the coordination marker on every release. Add a new integer vN only when
the release commit does not already have one; vN must be globally unique in the
firmware repo.
git tag -a v70 -m "Flex firmware v70"
git tag -a ot3@4.0.0-beta.0 -m "Coordinated release marker"
git push origin v70 ot3@4.0.0-beta.0
Before pushing the app tag, run
just validate-release-tags --tag <app-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 | ot3-firmware | Firmware, if a new tag is needed |
| 2 | oe-core | Robot OS, if a new tag is needed |
| 3 | opentrons | App monorepo, always last |
Flex 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 flex --tag ot3@8.5.0-alpha.0 --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 Flex build) - Robot OS build in
oe-core
The Rich table lists key jobs (deploy, desktop builds, dispatch spawn, robot image build). The Slack copy block includes only two links:
Flex release `ot3@8.5.0-alpha.0` - app: <app workflow run URL> - flex: <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, run
invalidation and wait for completion (omit --execute to print the AWS command only):
just invalidate-cloudfront --non-interactive --path flex --tag ot3@8.5.0-alpha.0 --execute --wait
Invalidates /app/* and /ot3-oe/* 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
Verify manifests, updater YAMLs, and artifact URLs for the release tag:
just verify-release-assets --non-interactive --path flex --tag ot3@8.5.0
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 Flex artifacts live on ot3-development.builds.opentrons.com.
| Artifact | URL |
|---|---|
App releases.json |
https://ot3-development.builds.opentrons.com/app/releases.json |
Robot releases.json (source of truth) |
https://ot3-development.builds.opentrons.com/ot3-oe/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 use the same filenames under the internal host:
alpha.ymlalpha-mac.ymlalpha-linux.ymlbeta.ymlbeta-mac.ymlbeta-linux.ymllatest.ymllatest-mac.ymllatest-linux.yml
See also: Flex internal assets.
Alpha and beta on Flex internal
In just go, choose Release type: internal and
Stability: alpha or beta. At one semver base, alpha and beta
are independent release flavors with separate counters, not a strict
promote-alpha-to-beta ladder.
Stack tags on opentrons and oe-core match the app.
ot3-firmware uses the same ot3@* coordination tag plus integer
vN. Validate with just validate-release-tags --tag <app-tag>.
See coordinated tagging and
release channel hierarchy.
| Train | Stability | Tag example | Notes |
|---|---|---|---|
| VM isolation | beta | ot3@4.0.0-beta.0 | Beta app channel; beta counter at the base |
| CRS | alpha | ot3@4.0.0-alpha.4 | Alpha app channel; alpha counter at the base (can coexist with beta) |
| Stable | stable | ot3@4.0.0 | Same prompted base version |
When both channels need updates in the same release cycle, publish desktop builds beta first, then alpha:
- Beta publish overwrites
beta.ymlandalpha.yml(alpha users temporarily see the beta build). - Alpha publish restores
alpha.ymlonly;beta.ymlstays on beta.
Git tag order can differ. YAML pointers follow the last desktop build
publish. Beta without follow-up alpha leaves alpha-channel users on beta even when
alpha artifacts remain in releases.json (for example
ot3@4.0.0-alpha.4 tagged before ot3@4.0.0-beta.1, but
alpha.yml points at beta.1). See
release channel hierarchy and
coordinated tagging reference.
Before pushing the app tag, run
just validate-release-tags --tag <app-tag>.