Guides

CI runners

Send each GitHub Actions job to a fresh Moil box by changing runs-on, or run a single command in a box from any CI system.

runs-on: moil-*CLI from any CI
What runs in MoilThe whole job, in a box of its ownOne command per step
SetupConnect the GitHub App, change one lineAn API key stored as a CI secret
Works withGitHub ActionsAnything that can run Node

1. Change runs-on

Connect GitHub from the dashboard, then swap your runner label. Each job boots a clean Ubuntu 24.04 box with common toolchains and is deleted when the job ends.

.github/workflows/test.yml
name: teston: [push, pull_request]jobs:  test:    runs-on: ubuntu-24.04    runs-on: moil-medium    steps:      - uses: actions/checkout@v4      - run: npm ci && npm test
Each job gets a fresh 4 vCPU · 8 GiB box, deleted when the job ends.
Jobs · push to main
  • lint moil-medium passed
  • test (node 22) moil-medium passed
  • e2e (chromium) moil-medium passed

Runner sizes

LabelBox
moil-small2 vCPU · 4 GiB
moil-medium4 vCPU · 8 GiB
moil-large8 vCPU · 16 GiB
moil-xlarge16 vCPU · 32 GiB
moil-2xlarge32 vCPU · 64 GiB

Free workspaces get moil-small and moil-medium, Pro adds moil-large, and Team can use every size. Runners are billed like any box, by the second — see pricing.

2. The CLI from any CI

A step creates a box, uploads the checkout, runs one command and deletes the box. First store an API key as a secret:

moil keys create --name github-ci --expires-in 90d --json | jq -r .key | gh secret set MOIL_API_KEY
.github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    env:
      MOIL_API_KEY: ${{ secrets.MOIL_API_KEY }}
    steps:
      - uses: actions/checkout@v4
      - name: Run the tests in a Moil box
        run: npx moil@latest run --push . --timeout 10m -e CI=1 -- 'npm ci && npm test'
  • The step fails when the command fails, and the command has a time limit.
  • Pass secrets explicitly with -e NAME="$NAME". Pull requests from forks get no secrets, so the step can’t run there.

Questions

What does the GitHub App need?

Only what it takes to register a one-job runner when a job asks for a moil-* label and remove it afterwards, on the repositories you select. GitHub lists each permission on the install screen before you approve it.

What happens if a job hangs?

The box is deleted when the job ends, is cancelled or hits its timeout-minutes. Set a timeout on long jobs so a stuck one can’t run all day.

Can I skip the GitHub App?

Yes — the CLI route needs nothing but an API key.

Something else?

Write to support@moil.dev.