Run in CI
Rector belongs in CI the same way as PHPStan: run it with --dry-run on every pull request and fail the job when it finds changes. That keeps the codebase at the level you agreed on and makes every future upgrade a one-line config change.
The command
vendor/bin/rector process --dry-run --no-progress-bar
The exit code is 1 when Rector would change a file, so the job fails and shows the diff. For inline annotations use --output-format=github or --output-format=gitlab, see CLI options.
Cache between runs
While parsing your application code, Rector caches the parsed objects to a directory, so the next run only parses files that changed. On CI runners the temp directory is empty every time, so set a stable path you can persist between jobs. Without it, each job parses all code from scratch.
<?php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withCache(
// a path that works locally as well as on CI job runners
cacheDirectory: '/tmp/rector'
);
The default path, when not specified, may vary per (runner) OS, so set it explicitly to keep it the same on CI and development.
GitHub Actions
Use the cache action to persist the directory between jobs:
- name: Rector Cache
uses: actions/cache@v4
with:
path: /tmp/rector
key: ${{ runner.os }}-rector-${{ github.run_id }}
restore-keys: ${{ runner.os }}-rector-
- run: mkdir -p /tmp/rector
- name: Rector Dry Run
run: php vendor/bin/rector process --dry-run --no-progress-bar --output-format=github
With this key configuration, runs on branches inherit the cache from their parent, if any.
Debugging the cache locally
Run Rector on your development machine:
vendor/bin/rector process --dry-run
You can find the cache in /tmp/rector, in folders like 0a, 0b, 0c, holding the parsed objects from the latest run. When a rule change is not picked up, run once with --clear-cache.
Let Rector open the pull request
Instead of failing the job, some teams let Rector run without --dry-run on a schedule and commit the result as a pull request. See how to make Rector contribute your pull requests every day.