A long-lived CI server accumulates state that the pipeline quietly depends on — a global package, a cached credential, a directory somebody created in 2017. A hosted runner has none of it, every time.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
extensions: pdo_mysql, redis
coverage: none
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpunit
coverage: none is worth setting explicitly because the default installs Xdebug, which triples the runtime of every test job for a report nobody asked for. Pinning the runner image to ubuntu-20.04 rather than ubuntu-latest is the other habit: latest moves, and a build that broke because the image changed underneath is a bad morning with no commit to blame. The freshness is the whole value — a pipeline that assumes nothing is a pipeline that works on a new machine.