Move workflows to Anvil runners
CI → Run on Anvil reads a GitHub repository's workflows, shows exactly which lines change, and opens one pull request that switches them to an Anvil runner. Nothing runs differently until you merge it.
Open the pull request #
- Open CI → Run on Anvil.
- Pick the repository. Only GitHub repositories with the Anvil app are listed.
- Pick a size:
anvil-2cpu,anvil-4cpuoranvil-8cpu. - Untick any workflow you want to leave out.
- Click Open pull request, and merge it on GitHub when its checks look right.

The pull request comes from the Anvil app on a branch named anvil/runners-<id>. Its description lists every changed line.
What changes and what doesn't #
Anvil changes only the runs-on line of each job, and keeps your comments, quotes and indentation.
runs-on today |
After |
|---|---|
ubuntu-latest, ubuntu-24.04, ubuntu-22.04 |
anvil-4cpu (the size you picked) |
[ubuntu-latest] or a one-item list |
the same list with anvil-4cpu |
blacksmith-4vcpu-ubuntu-2404 and other Blacksmith Ubuntu labels |
anvil-4cpu |
${{ matrix.os }} with Ubuntu entries in the matrix |
an expression that sends only the Ubuntu entries to Anvil (below) |
Already anvil, anvil-*, or with anvil-sticky |
left alone |
self-hosted, several labels, a runner group |
left alone |
macos-*, windows-*, *-arm |
left alone: Anvil runs Linux x64 jobs |
Any other expression, such as ${{ inputs.runner }} |
left alone |
Jobs that call a reusable workflow (uses:) have no runner of their own; change the called workflow instead.
Matrix jobs #
Matrix values often appear elsewhere (if: matrix.os == 'ubuntu-latest', cache keys, job names), so Anvil doesn't touch the matrix. It changes runs-on to pick Anvil for the Ubuntu entries only:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
- runs-on: ${{ matrix.os }}
+ runs-on: ${{ matrix.os == 'ubuntu-latest' && 'anvil-4cpu' || matrix.os }}The macOS entry keeps running on GitHub. A matrix built by an expression (fromJSON(...)) is left alone, because Anvil can't see its values.
Go back #
Change runs-on back, or revert the pull request. Nothing else in the workflow changed.
Do it by hand #
The same change works in any editor:
jobs:
test:
runs-on: anvil-4cpu
Sizes, caches and limits are in Runner sizes and labels.