The problem
macOS builds and tests need macOS, and macOS only runs on Apple hardware. GitHub offers hosted macOS runners, but teams often run their own Macs for more control over the hardware, the installed tools and the images builds run on.
Running your own brings its own problems:
- State carries over between jobs. A runner that stays up keeps whatever the last job left behind: files, caches, keychain items, half-installed tools. Builds start to depend on that leftover state, and one job can see what another left. GitHub recommends ephemeral runners, which take one job and are then removed, for exactly this reason.
- macOS VMs are scarce. Apple’s macOS license has long allowed only two macOS virtual machines per Mac, and Apple’s virtualization framework enforces it, so every host’s VM slots have to be scheduled with care.
- Images drift. Machines set up by hand slowly stop matching each other, and rebuilding one means someone with shell access and time.
What did macOS CI look like at Vast before Grove? What broke, and who felt it?
What Grove does
Grove provisions an ephemeral VM per job on each macOS host, records per-VM time-series metrics, and drives Packer image builds from a GUI.
- One VM per job. Each job gets a fresh VM started from the current image, and the VM is gone when the job ends, so nothing carries over to the next job.
- Per-VM metrics. Recording each VM over time shows what every job actually used, which is what you need to size VMs and decide how many each host can run.
- Image builds from a GUI. The image is defined in Packer, so it is rebuilt the same way every time, and engineers can start a build from the web app instead of logging in to a machine.
How it’s built
- Data model: Aurora PostgreSQL tables for hosts, jobs, VM lifecycle and metrics. Why this shape?
- API: the REST contract the frontend consumes.
- Two containers, deployed separately: a Go backend-for-frontend serving a Vite/TypeScript frontend, and a runner service that talks to the GitHub App. Why split them?
- Platform: Google Workspace OIDC sign-in, Artifactory as a dependency proxy, Helm deployment on Kubernetes.
Results
Only include outcomes you can state plainly.