Flex internal releases

Internal Flex builds for Opentrons staff and early validation. App tags use an ot3@ prefix in opentrons.

Stack repos

RepoRoleInternal tag pattern
opentronsApp (taggable)ot3@X.Y.Z, alpha ot3@X.Y.Z-alpha.N, beta ot3@X.Y.Z-beta.N
oe-coreFlex robot OSSame coordinated tag as app (e.g. ot3@X.Y.Z-beta.N)
ot3-firmwareFlex firmwareSame ot3@* as app + integer vN on same commit

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

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.

RepoDefault branch
opentronsedge
oe-coremain
ot3-firmwaremain

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)

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.

StepRepoNotes
1ot3-firmwareFirmware, if a new tag is needed
2oe-coreRobot OS, if a new tag is needed
3opentronsApp 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:

  1. App workflow on the monorepo (App test, build, and deploy)
  2. Kickoff cross-repo dispatch (Start Flex build)
  3. 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, print a copy-paste command (it does not run invalidation):

just invalidate-cloudfront --non-interactive --path flex --tag ot3@8.5.0-alpha.0

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

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.

ArtifactURL
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:

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.

TrainStabilityTag exampleNotes
VM isolationbetaot3@4.0.0-beta.0Beta app channel; beta counter at the base
CRSalphaot3@4.0.0-alpha.4Alpha app channel; alpha counter at the base (can coexist with beta)
Stablestableot3@4.0.0Same prompted base version

When both channels need updates in the same release cycle, ship beta before alpha so beta desktop builds do not leave alpha updater YAML pointing at the wrong build. That rule is for updater metadata only; alpha and beta remain independent tag lanes at the same semver base. See release channel hierarchy and coordinated tagging reference.

Before pushing the app tag, run just validate-release-tags --tag <app-tag>.