The minimal setup that works: a three-branch model (feature branches into a staging branch into main), with a pipeline that lints, tests, builds, and deploys to staging before any human approves production. Start with linting: running PHP_CodeSniffer against the WordPress Coding Standards on every push catches the most errors for the least effort. GitHub Actions or GitLab CI both do the job. The one rule you cannot skip: never update plugins directly on production.
TL;DR:
- Running PHP_CodeSniffer for WordPress coding standards on every push quickly catches major errors with minimal effort.
- Maintaining a three-branch model and gating merges with pull requests ensures code quality and prevents direct plugin updates on production.
- Layering in PHPUnit, plugin activation tests, and vulnerability scans greatly improves reliability, especially when versions are pinned in CI.
- Reproducing builds within CI using lockfiles and managing assets through CI ensures consistency and reduces deployment risks.
- Implementing an atomic deployment process with symlink swapping minimizes downtime and prevents half-finished updates from breaking the site.
Table of Contents
- How to set up CI for WordPress: the pipeline overview
- Which branch strategy works for agency WordPress projects?
- What CI checks and tools should you actually run?
- How should agencies handle asset builds and dependencies?
- Why does staging environment parity actually matter?
- What deployment strategy avoids downtime?
- What WordPress-specific problems catch agencies out?
- Quick start: 10 steps to a minimal WordPress CI pipeline
- What agency teams get wrong about WordPress CI
- How WPCTO keeps agency WordPress pipelines running
- Sources
- FAQ
How to set up CI for WordPress: the pipeline overview
A CI pipeline for WordPress does not need to be complicated to be effective. It needs to run the same checks every time, in the same order, without a human forgetting a step. That is the entire value proposition.
The standard stages, in order, are:
- Lint – PHPCS against WordPress Coding Standards, plus a JavaScript linter if you have custom blocks or scripts.
- Test – unit and integration tests (PHPUnit, WP-CLI activation checks).
- Security scan – dependency and vulnerability checks against your Composer lockfile.
- Build – compile assets, install production dependencies, produce a deployable artefact.
- Deploy to staging – automatic, no human needed.
- Manual approval gate – a person signs off.
- Deploy to production – automatic once approved.
A full run through this sequence typically takes 2–4 minutes once configured properly, which is fast enough that developers actually wait for it instead of skipping it. Parallelise the lint and test stages where your CI platform supports it. A rough YAML fragment for the lint stage in GitHub Actions looks like this:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: vendor/bin/phpcs --standard=WordPress .
That single job, wired into every pull request, is Continuous Integration for WordPress in its simplest and most valuable form.
Which branch strategy works for agency WordPress projects?
Keep it to three branch tiers and resist the temptation to add more:
- feature/* – one branch per ticket or task, merged via pull request.
- develop (or staging) – the integration branch; every feature lands here first and deploys automatically to a staging environment.
- main (production) – only updated via approved pull request from staging; deploys to the live site.
Gate every merge into develop and main with a pull request review, even on small teams. It forces a second pair of eyes before code touches a client’s live site.
What belongs in Git: theme code, custom plugins, mu-plugins, and composer.json. What must never appear in a commit: .env files, the uploads directory, and any wp-config.php containing real database credentials. Add all three to .gitignore on day one.
For urgent fixes, branch a hotfix/* directly off main, patch it, then merge back into both main and develop so the fix doesn’t get lost on the next release.
What CI checks and tools should you actually run?
Start with PHPCS running the WordPress Coding Standards on every single push. This is the highest-value first step because it flags deprecated functions, incorrect hook usage, and standards violations before they ever reach a test suite, let alone a client’s browser.
From there, layer in:
- PHPUnit for anything with custom business logic (custom post type behaviour, ACF field logic, bespoke REST endpoints).
- WP-CLI activation tests to confirm plugins and themes actually activate cleanly on a fresh database, scriptable directly by WP-CLI inside the CI runner.
- Dependency scans against your
composer.lockto catch known vulnerabilities before they ship. - SAST/SCA tooling where your platform offers it natively.
On tool choice, all four major options do the job, so weigh them by your team’s existing stack rather than by feature checklists:
- GitHub Actions — flexible, huge marketplace of pre-built actions, good if your code already lives on GitHub.
- GitLab CI — strong for agencies managing many client repos at once, since pipeline inheritance and include templates let you maintain one shared pipeline definition and roll security fixes out everywhere at once.
- Bitbucket Pipelines — sensible default if you’re already on Bitbucket and don’t want another vendor.
- Buddy — a visual pipeline builder that suits teams who want less YAML and more drag-and-drop.
Pro Tip: Pin your PHP and MySQL versions inside the CI runner container rather than letting the platform default to “latest”. Version drift between CI and your actual hosting environment is one of the most common reasons a test passes in the pipeline and fails on the server.
How should agencies handle asset builds and dependencies?
Reproducibility is the goal: run npm install and composer install inside the CI runner itself, never on your laptop, so the build is identical every time regardless of who triggers it.
- Commit lockfiles (
composer.lock,package-lock.json) so every install pulls exact versions, not “whatever’s newest today”. - Use Composer with WPackagist to manage plugins as dependencies where practical, instead of hand-uploading zip files.
- Run
npm run buildin the runner to compile assets, then deploy the compiled output, not the raw source. - Deploy the built artefact from CI, never from a developer’s local machine, and keep files excluded by
.gitignore(uploads, caches, vendor folders you regenerate) out of the deploy payload entirely.
Why does staging environment parity actually matter?
Staging that doesn’t match production is worse than no staging at all, because it gives you false confidence. Match PHP version, plugin versions, and server configuration exactly, or your test results are meaningless.
- Run Behat acceptance tests against staging for critical user flows (checkout, form submissions, membership logins).
- Follow automated tests with manual QA, then hold a manual approval gate before anything touches production.
- Sync only the parts of the database you need for realistic testing. A full production database overwrite onto staging risks exposing real customer data to a less secure environment and often breaks local plugin configuration.
Detailed guidance on building this correctly sits in WPCTO’s practical guide to WordPress staging.
Pro Tip: Containerise your staging environment rather than running it on a shared server. Pinning the exact PHP and MySQL versions your CI runner uses avoids the “works on staging, fails in production” trap that eats entire afternoons.
What deployment strategy avoids downtime?
Atomic deploys solve the biggest risk in WordPress deployment: a half-finished upload leaving the site in a broken state mid-swap. Deploy code into a fresh, timestamped release folder, then swap a current symlink to point at it only once the new code is fully in place. That symlink-swap pattern means visitors never see a half-updated site.
- Use
rsyncover SSH, or a deployment tool such as Deployer, to push the built artefact into the new release folder. - Purge object and page caches (
wp cache flush) immediately after the symlink swap, or visitors will see stale content. - Put a protected environment or manual approval step in front of any deploy that touches a client’s live production site. No exceptions, no matter how small the change looks.
What WordPress-specific problems catch agencies out?
WordPress has quirks that generic CI advice doesn’t cover, and they’re what actually breaks client sites:
- ACF field groups – enable ACF JSON so field group definitions live in Git as version-controlled files, not trapped in a database only one developer can edit.
- Structural database changes – script these with WP-CLI or WP Migrate CLI rather than hand-editing tables; never let a migration overwrite transactional tables like orders or form submissions.
- Media uploads – offload the
uploadsdirectory to object storage, or exclude it from code deploys entirely; syncing gigabytes of images through your pipeline slows every build for no benefit. - Plugin updates – never apply them directly to production. Update on develop, test thoroughly on staging, then let the pipeline promote the change to production. This single habit, backed by WPCTO’s own operational experience, prevents more outages than any monitoring dashboard. WPCTO’s own plugin update playbook walks through the workflow in more detail.
Quick start: 10 steps to a minimal WordPress CI pipeline
- Initialise a Git repository with theme, custom plugins, and
composer.jsoncommitted. - Add
.gitignoreentries for.env,uploads, and any credentialed config files. - Set up the three-branch model:
feature/*,develop,main. - Choose a CI platform: GitHub Actions or GitLab CI both work well.
- Add a lint job running
vendor/bin/phpcs --standard=WordPress .. - Add
composer install --no-dev --optimize-autoloaderto the build stage. - Add
npm run buildfor front-end assets. - Add a WP-CLI activation test to confirm plugins and themes load cleanly.
- Deploy the built artefact to staging via
rsyncor Deployer on every merge todevelop. - Add a manual approval gate before production, then repeat the deploy step against
main.
If you’d rather see the financial case for doing this properly before you build it yourself, WPCTO’s WordPress Profit Calculator shows agencies how much recurring revenue sits in the maintenance work they’re currently doing manually.
What agency teams get wrong about WordPress CI

The failure pattern is always the same: someone updates a plugin directly on production on a Friday afternoon, it conflicts with a theme function, and the site goes down over the weekend. A manual approval gate would have caught it on staging first.
What we see most often in agency portfolios isn’t a lack of ambition. It’s inconsistency: one client project has a proper pipeline, ten others still get deployed over FTP because nobody had the afternoon to set it up. The fix isn’t more tooling. It’s applying the same three-branch pattern everywhere, without exception, so no client site is the “one we forgot to protect.”
— Marcel
How WPCTO keeps agency WordPress pipelines running
Building the pipeline is the easy part. Keeping it maintained across dozens of client sites, each on different plugin combinations and hosting stacks, is where agency teams lose their evenings. That’s the gap WPCTO exists to close.
WPCTO sits behind your agency handling the ongoing operational side: maintenance and care plans, security monitoring, performance optimisation, plugin and theme management, hosting and migrations, and fractional CTO consulting when a client needs pipeline architecture decided properly rather than guessed at. Agencies use WPCTO’s agency services to keep every client site on a consistent, monitored deployment process without adding a DevOps hire, and the white-label support option means your client never even sees WPCTO’s name on the invoice.
If you want to see exactly how much recurring revenue is sitting uncaptured in your current WordPress client base, run it through the WordPress Profit Calculator. It takes under 90 seconds, and it’s usually the number that makes the CI conversation worth having internally.
Sources
- WordPress DevOps: How to Set Up CI/CD That Actually Works – onPoint Studio
- Why WordPress agencies are moving their CI/CD pipelines to GitLab: A practical DevOps guide – WP Tavern
- WP-CLI: Manage WordPress from the command line
FAQ
How do you set up CI/CD from scratch?
Connect your repository to a CI platform such as GitHub Actions or GitLab CI, define pipeline stages for lint, test, build, and deploy in a YAML config file, then trigger the pipeline on every push or pull request.
Can ChatGPT build a WordPress website?
ChatGPT can generate boilerplate PHP, CSS, or configuration snippets to speed up development, but it cannot replace a tested CI pipeline, proper staging, or human review before code reaches a client’s live site.
What are the best WordPress development tools?
WP-CLI, Composer, and PHP_CodeSniffer with the WordPress Coding Standards cover most day-to-day development needs, while GitHub Actions or GitLab CI handle the automation layer around them.
How do you integrate plugins into WordPress safely?
Manage plugins through Composer and WPackagist where possible so versions are locked and reproducible, then push updates through develop and staging before they ever reach production, never applying updates directly to a live site.
What’s the fastest first step to improve WordPress deployment?
Add a linting stage using PHP_CodeSniffer against the WordPress Coding Standards on every push. It’s the single change that catches the most problems for the least setup effort.
