Attempts to add CI to a WordPress project usually stall on “we have no tests, so what would it run?”. In fact there is a good deal you can catch automatically without a test suite, and what it catches tends to be the most embarrassing class of incident: a syntax error reaching production, a deploy without a rebuild, a plugin that stops the site booting.
1. Syntax — the cheapest and surest check
php -l only parses, so it is very fast. It does, however, accept one file at a time — hand it several and it checks the first and stops. That is why xargs -n1 is required.
find wp-content/themes wp-content/plugins -name '*.php' -not -path '*/vendor/*' -print0 | xargs -0 -n1 -P4 php -l
That single line prevents a large share of white-screen incidents. A parse error fires the moment the file is loaded, so a file used on exactly one admin screen is no exception.
2. Coding standards — so reviews are not arguments
With PHPCS and the WordPress standard in place, indentation, missing escaping and prefix conventions are raised by a tool rather than by a colleague.
composer require --dev squizlabs/php_codesniffer wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer
vendor/bin/phpcs --standard=phpcs.xml.dist
Committing the ruleset itself matters. Declaring your text domain and function prefixes in phpcs.xml.dist means a mistyped translation domain or an unprefixed global function is caught automatically. Turning every rule on at once buries you in thousands of warnings, so start by checking changed files only and widen from there — that version actually survives.
3. Build check — “I forgot to rebuild”
If part two led you to commit build output, verifying that the output still matches the source is CI’s job, not a person’s. The omission will happen, and the symptom is somebody asking why the styles have not changed.
npm ci
npm run build
git diff --exit-code assets/dist
--exit-code fails the step when a difference exists, so a rebuild that does not match what was committed stops the pipeline right there.
4. Boot smoke test — does the site actually come up?
The most valuable check of the four. Install WordPress against a throwaway database, activate your theme and plugins, and confirm the home page answers 200.
wp core install --url=http://127.0.0.1:8080 --title=CI --admin_user=ci --admin_password=ci --admin_email=ci@example.com --skip-email
wp theme activate our-theme
wp plugin activate --all
test "$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/)" = "200"
Simply getting wp plugin activate --all to pass filters out fatal errors at activation time — redeclared functions and references to classes that do not exist surface here.
What CI will not tell you
One final rule: keep secrets out of CI logs. Inject deploy keys and database passwords as masked secrets, and never leave behind a debugging step that dumps the whole environment. The conclusion from part three applies here unchanged.
Automation continues in the development workflow archive, and the order in which we verify and deploy in practice is published on our process page.
Next part
The final part is rollback. It rests on one fact — putting the old code back does not put the old data back — and that is why the order has to be decided in advance.