Run builds in VMs
Give every build of a pipeline a clean macOS VM with Tart, picked by the Flutter version.
Run each build of a pipeline in a new Tart VM. The runner clones the VM from an image for the build’s Flutter version, runs every step inside it, and deletes it when the build ends. Nothing a build installs survives into the next one, and apps pinned to different Flutter versions can share one Runner Mac.
Image names, base images, environment variables, oore.image.yaml fields,
and the full build sequence are in
Runner settings.
What you need
- Tart 2.41.1 or newer on the Runner Mac.
- The runner account logged in to macOS. Apple’s Virtualization framework needs that login session, the same one iOS signing uses. On a dedicated build Mac, turn on automatic login for the runner account.
- Disk space for the images. An image for iOS builds starts from a download of about 69 GB, and an Android-only image from about 26 GB. Budget well over 100 GB on a Runner Mac that builds iOS, and more for each further Flutter version.
- Xcode on the host too, if the pipeline uploads to TestFlight or the App Store. The upload runs on the host.
- Project developer, maintainer, instance admin, or instance owner access to edit the pipeline.
1. Install Tart
Install Tart with Homebrew, then check the version. Homebrew’s formula can lag behind Tart releases:
brew install openai/tools/tart
tart --versionIf Homebrew installs a version older than 2.41.1, remove it and install the release directly:
brew uninstall openai/tools/tart
cd /tmp && curl -fLO https://github.com/openai/tart/releases/download/2.41.1/tart.tar.gz
tar -xzf tart.tar.gz
sudo rm -rf /Applications/tart.app && sudo mv tart.app /Applications/
sudo mkdir -p /usr/local/bin
sudo ln -sf /Applications/tart.app/Contents/MacOS/tart /usr/local/bin/tart
/usr/local/bin/tart --versionThe runner looks for tart in /opt/homebrew/bin, then /usr/local/bin,
then its service PATH. It checks at the start of every VM build, so it needs
no restart. Run oore doctor on the Runner Mac to confirm that it finds Tart.
2. Turn on VM isolation
In the pipeline editor:
- Open the pipeline and select Edit.
- Under Build > Runner, set Isolation to In a fresh macOS VM for the pipeline’s Flutter version.
- Select Save changes.
If the repository has a .oore.yaml, set isolation there instead. The file
wins over the editor when it exists:
version: 1
platforms: [android, ios]
isolation: vmThe Flutter version comes from a checked-in .fvmrc, then the pipeline’s
Flutter version, then stable.
3. Build the image
Start a build of the pipeline. If the runner has no image for that Flutter
version yet, it builds one before the build runs and keeps it for later
builds. The download and setup stream into the build log under vm-start.
The first image from a base can take an hour or more, depending on the
connection.
To build an image ahead of time, start any VM build that uses the Flutter version.
4. Add tools the base image lacks
If the app needs Android SDK packages, Homebrew formulae, or setup commands
that the image does not have, add oore.image.yaml to the repository root:
version: 1
android_packages:
- 'platforms;android-36'
brew:
- graphicsmagick
setup:
- gem install bundlerThe next build creates a new image for that project. Each edit to the file creates another one, and the runner deletes images that no build used for 30 days.
Verify the result
- The build log has a
vm-startstep. It records how long the VM took to start, usually 10 to 30 seconds, and lists the caches it restored. tart liston the Runner Mac shows the local image, such asoore-flutter-3.47.7, and no leftover VM after the build ends.- A second build of the same pipeline skips the image build.
Troubleshooting
The build fails because Tart is not installed
The log says the pipeline runs in a VM but Tart is not installed on this runner. Install Tart 2.41.1 or newer as in step 1, then re-run the build.
The VM does not boot
The runner account is not logged in to macOS. Log in, or turn on automatic login for that account, then re-run the build.
The build waits for a VM slot
Apple allows two macOS VMs per Mac, so a Mac runs at most two VM builds at a time across all of its runners. A third build waits, and its log says so. Add another Runner Mac for more VM builds at once.
The first build takes an hour
The runner is downloading and building the image. Later builds of the same Flutter version reuse it.
The disk fills up
Delete images you no longer need with tart delete <image>. To find base
images, run tart list --source oci. To rebuild an image from scratch, delete
it, such as tart delete oore-flutter-3.47.7, and start a build.
Instrumented Android tests fail
Android emulators have no hardware acceleration inside a macOS guest. Keep instrumented tests in a pipeline that runs on the host.
Next step
Route builds with runner labels to send VM pipelines to the Runner Macs that have Tart and the disk space for its images.