Your Mac isn't your CI runner, even when the distro name matches

A macOS terminal isn't a Linux CI runner at all, obviously — but even a Linux VM on your Mac can drift from what CI actually runs, silently, without you changing anything. "It works locally" and "it works in CI" aren't the same claim unless the local environment actually matches the one CI uses, not just the same distro family in general.

A real, current example: the ubuntu-latest trap

This is happening right now, not a hypothetical: GitHub Actions' ubuntu-latest runner label is migrating from Ubuntu 24.04 to Ubuntu 26.04, rolling out gradually between October 19 and November 19, 2026. A workflow pinned to ubuntu-latest will silently start running on a different OS version during that window, with different preinstalled tool versions and some removed packages — exactly the kind of change that breaks a pipeline with zero code changes on your end. Pinning to an explicit version (ubuntu-24.04 instead of ubuntu-latest) avoids the surprise, but only if you actually know which version you're pinned to and test against that one specifically.

Matching a workspace to your actual pinned runner

Velo's own official-image picker happens to offer both Ubuntu 26.04 LTS and Ubuntu 24.04 LTS Server images side by side — pick whichever one matches your CI YAML's actual pin, not whatever's newest. A disposable workspace built from the same version your pipeline runs on is the closest local reproduction of that runner's environment you can get on a Mac, and it costs nothing to throw away and recreate when you're done checking.

The practical loop

Create a disposable workspace matching your pinned runner version, run the same install and test steps your CI job runs, iterate locally against real failures instead of push-wait-read-logs each time, then discard the workspace once you've confirmed the fix. This is materially faster than the CI feedback loop for catching environment-specific breakage — a missing system package, a tool version mismatch — before it costs you a real pipeline run.

What this doesn't replace

Worth being honest about the limit: this reproduces the OS and tool environment, not the whole CI system. Secrets, environment variables scoped to CI specifically, matrix builds across multiple versions at once, and whatever your actual pipeline orchestration does around the job itself aren't part of this loop. It catches "does this run on the OS my pipeline uses" cheaply and early — it doesn't replace actually running the pipeline before merging.

Related reading: the disposable VM workflow for QA and DevOps, Ubuntu on Apple Silicon, and which distro fits which workload. Or download Velo Workspaces and try it yourself.