Table of Contents
- Introduction
- Setting Up PHPCS for WordPress
- Integrating PHPStan for Static Analysis
- GitHub Actions Workflow Setup
- PR Annotations and Quality Gates
- Integrating WP HealthKit in CI/CD
- Frequently Asked Questions
- Conclusion
Introduction
Manual code review is essential but slow. Developers wait days for feedback on pull requests, and reviewers can miss subtle issues in large diffs. WordPress plugin automated code review CI/CD pipelines address these limitations by running automated checks on every pull request, providing instant feedback on code quality, security issues, and violations of coding standards.
Automated code review doesn't replace human review—it augments it. Tools like PHPCS (PHP Code Sniffer) verify that your code follows WordPress coding standards, PHPStan detects type errors and potential bugs, and security scanners identify vulnerabilities. By catching these issues automatically, human reviewers can focus on logic, design, and architectural concerns rather than formatting and obvious bugs.
Setting up a robust automated code review pipeline involves three components: local linters that developers use before pushing code, CI/CD checks that run on every pull request, and WP HealthKit integration that provides comprehensive security and quality analysis. This guide walks through setting up each component.
Setting Up PHPCS for WordPress
PHPCS (PHP Code Sniffer) checks your code against configurable standards. WordPress provides official coding standards through the WordPress Coding Standards ruleset. This is the first tool to implement because it catches the most common issues. PHPCS is a linter that examines code structure and enforces style rules. The WordPress Coding Standards ruleset includes hundreds of rules covering naming conventions, documentation requirements, security practices, and code organization. PHPCS checks operate quickly on local machines, making them ideal for running before every commit. By catching style violations early through automation, you prevent them from being reviewed in pull requests, saving review time for more important concerns. Developers can fix style issues automatically in most cases using the phpcbf tool, which corrects violations without changing functionality. Implementing PHPCS is a one-time setup investment that pays dividends throughout your plugin's development lifecycle. Once configured, every developer runs the same checks consistently, eliminating debate about style conventions and ensuring code review focuses on logic and security rather than formatting.
First, install PHPCS and the WordPress standards:
composer require --dev "squizlabs/php_codesniffer:*" \
"wp-coding-standards/wpcs:*"
Create a phpcs.xml.dist file in your repository root:
<?xml version="1.0"?>
<ruleset name="WordPress Plugin Standards">
<description>PHPCS Rules for WordPress Plugin</description>
<rule ref="WordPress-Core"/>
<rule ref="WordPress-Docs"/>
<!-- Exclude generated files -->
<exclude-pattern>/vendor/</exclude-pattern>
<exclude-pattern>/node_modules/</exclude-pattern>
<exclude-pattern>/*.min.js</exclude-pattern>
<exclude-pattern>/*.min.css</exclude-pattern>
<!-- Check all PHP files -->
<file>.</file>
<arg name="extensions" value="php"/>
<arg value="sp"/>
</ruleset>
Run PHPCS locally to find issues:
vendor/bin/phpcs --standard=phpcs.xml.dist
Fix automatically fixable issues:
vendor/bin/phpcbf --standard=phpcs.xml.dist
Add these commands to your package.json or composer.json for easy access:
{
"scripts": {
"lint": "phpcs --standard=phpcs.xml.dist",
"lint:fix": "phpcbf --standard=phpcs.xml.dist"
}
}
Developers can now run npm run lint locally before pushing, catching issues early. This prevents failed CI builds and speeds up the review process.
For a practical example, PHPCS will catch missing documentation:
// FAILS: Missing documentation
function my_plugin_render_block() {
return '<div>Content</div>';
}
// PASSES: Properly documented
/**
* Renders a custom block.
*
* @param array $attributes Block attributes.
* @return string The rendered HTML.
*/
function my_plugin_render_block( $attributes ) {
return '<div>Content</div>';
}
Integrating PHPStan for Static Analysis
While PHPCS checks code style, PHPStan performs static type analysis to catch logical errors before runtime. PHPStan can detect undefined variables, type mismatches, incorrect function arguments, and other issues that cause bugs. Static analysis complements style checking: while PHPCS ensures code follows conventions, PHPStan ensures code logic is correct. Many bugs arise from type errors: calling methods on null values, accessing undefined array keys, or passing wrong argument types to functions. PHPStan catches these errors before they reach production. The tool performs sophisticated data flow analysis, tracking variable types through your code and identifying when you access properties that don't exist or call methods on potentially-null values. This is particularly valuable in WordPress where many functions return either an object or false depending on success. PHPStan's strict mode can be aggressive, requiring explicit type declarations and null checks everywhere. However, this aggressiveness forces better code quality: developers must think about error cases and handle them properly. Starting with lower strictness levels and gradually increasing them allows codebases to improve incrementally. PHPStan integrates naturally with IDE tools like PHPStorm, providing real-time feedback as developers write code rather than waiting for CI/CD results.
Install PHPStan:
composer require --dev phpstan/phpstan
Create phpstan.neon configuration:
parameters:
level: 5
paths:
- src/
- includes/
excludePaths:
- vendor/
- node_modules/
ignoreErrors:
- '#Call to an undefined method WP_#'
- '#Access to undefined constant ABSPATH#'
rules:
- PHPStan\Rules\Functions\CallToFunctionStatementWithoutSideEffectsRule
Run PHPStan locally:
vendor/bin/phpstan analyse
PHPStan catches type errors like:
// PHPStan error: Cannot access property on non-object
$user = get_user_by( 'login', 'admin' );
echo $user->email; // ERROR: $user might be false
// Correct version
$user = get_user_by( 'login', 'admin' );
if ( $user ) {
echo $user->email;
}
Add to your composer.json scripts:
{
"scripts": {
"analyze": "phpstan analyse"
}
}
PHPStan's type checking catches bugs that manual review would miss, reducing production issues significantly.
GitHub Actions Workflow Setup
GitHub Actions provides free CI/CD for public repositories. Create .github/workflows/lint-and-analyze.yml. GitHub Actions integrates automated code review directly into your development workflow. Rather than relying on developers to remember to run tools locally, GitHub Actions runs them automatically on every push and pull request. This ensures no code reaches main branch without passing automated checks. The workflow approach scales effortlessly: adding new analysis tools just means adding new jobs. GitHub displays results prominently in the PR interface, making it impossible for developers to miss issues. By combining multiple tools—PHPCS for style, PHPStan for static analysis, security scanners for vulnerabilities—you create comprehensive automated review that would be impractical to perform manually. The feedback loop becomes immediate: developers push code, automated tools run within seconds, results display, and developers know whether their code is ready for review. This tight feedback loop improves code quality significantly compared to discovering issues during manual review.
name: Lint and Analyze
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- name: Install dependencies
run: composer install --no-progress
- name: Run PHPCS
run: composer run lint
phpstan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- name: Install dependencies
run: composer install --no-progress
- name: Run PHPStan
run: composer run analyze
This workflow:
- Runs on every push to main/develop and on pull requests
- Sets up PHP 8.0
- Installs Composer dependencies
- Runs PHPCS and PHPStan
GitHub displays results directly on the pull request, providing instant feedback to developers.
PR Annotations and Quality Gates
Enhance your workflow to create PR annotations that highlight specific issues:
name: Code Review
on:
pull_request:
branches: [ main ]
jobs:
code-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- name: Install dependencies
run: composer install --no-progress
- name: Run PHPCS with GitHub annotations
id: phpcs
run: |
composer run lint -- \
--report=json > phpcs-report.json
continue-on-error: true
- name: Annotate PHPCS violations
uses: rtCamp/action-phpcs-code-review@main
with:
files: "{{ github.workspace }}"
standard: phpcs.xml.dist
continue-on-error: true
- name: Run PHPStan
id: phpstan
run: |
composer run analyze -- \
--error-format=table > phpstan-report.txt
continue-on-error: true
- name: Add PHPStan comment to PR
if: always()
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('phpstan-report.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '## PHPStan Analysis\n\n```\n' + report + '\n```'
});
This creates visible annotations on the PR showing exactly which lines have issues:
Line 42: Missing documentation for function
Line 89: Undefined variable $user_data
Line 156: Call to undefined method
Developers see issues before merging and can fix them immediately.
Integrating WP HealthKit in CI/CD
WP HealthKit provides comprehensive security and quality analysis. Integrate it into your workflow:
name: Security Audit with WP HealthKit
on:
pull_request:
branches: [ main ]
jobs:
wp-healthkit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Upload to WP HealthKit
run: |
curl -X POST https://api.wphealthkit.io/api/v1/audit \
-H "Authorization: Bearer ${{ secrets.WPHEALTHKIT_TOKEN }}" \
-H "Content-Type: application/zip" \
--data-binary @plugin.zip \
-o audit-results.json
- name: Parse WP HealthKit results
run: |
cat audit-results.json | jq '.'
- name: Comment results on PR
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('audit-results.json', 'utf8'));
let comment = '## WP HealthKit Security Audit\n\n';
comment += `Security Score: ${results.score}/100\n`;
comment += `Issues Found: ${results.issues.length}\n\n`;
if (results.issues.length > 0) {
comment += '### Issues\n';
results.issues.slice(0, 5).forEach(issue => {
comment += `- **${issue.title}** (${issue.severity}): ${issue.file}:${issue.line}\n`;
});
}
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Fail if critical issues found
run: |
if [ "$(jq '.critical_issues' audit-results.json)" -gt 0 ]; then
echo "Critical security issues found"
exit 1
fi
This workflow:
- Uploads your plugin to WP HealthKit for analysis
- Parses the results
- Comments findings on the PR
- Fails the build if critical issues are detected
This creates a quality gate preventing code with security vulnerabilities from being merged. Integrating multiple security tools creates comprehensive automated review that would be impossible to perform manually. Each tool specializes in specific issues: PHPCS catches style violations, PHPStan catches type errors, WP HealthKit catches security vulnerabilities and plugin-specific issues. Running all three tools ensures broad coverage. The PR comment feedback is particularly valuable because it's visible to developers immediately, allowing them to understand and fix issues before requesting review from maintainers. Automated feedback also reduces review burden: maintainers can focus on logic and architecture rather than style and security technicalities. Failed builds from critical issues prevent accidental merging of vulnerable code. This safety net is invaluable for preventing regressions in security posture. Teams should gradually increase analysis strictness as the codebase matures. Starting with low strictness levels and gradually enabling stricter checks prevents overwhelming developers while still providing value. Once codebases achieve high quality, maintaining that quality is easier than achieving it initially.
Make Code Review Automatic and Comprehensive
Automated code review catches issues humans miss while freeing reviewers to focus on architecture and logic. Integrate WP HealthKit into your CI/CD pipeline to get comprehensive security analysis on every pull request.
Additional Resources
For a comprehensive view of how WP HealthKit approaches plugin analysis, explore our 17 verification layers or browse the plugin directory to see real audit scores. Ready to check your own plugin? Run a free audit now.
Broader Context and Best Practices
Step-by-step tutorials for WordPress plugin development serve a critical role in the ecosystem by bridging the gap between documentation and practical implementation. WordPress.org documentation explains what functions are available, but tutorials show how to combine them into working solutions. This practical knowledge is especially valuable for patterns that span multiple WordPress subsystems, such as building a custom REST API endpoint that validates input, checks permissions, queries the database, and returns properly formatted responses. Each step involves different WordPress APIs that must work together correctly.
The most effective WordPress development tutorials teach not just the how but the why behind each decision. Understanding why WordPress uses nonces instead of simpler tokens, why capability checks should test specific capabilities rather than roles, or why prepared statements matter more than escaping for SQL queries gives developers the foundation to make good decisions when they encounter situations that tutorials haven't covered. This deeper understanding is what separates developers who can follow instructions from developers who can architect secure, maintainable solutions.
Testing and validation are often the most overlooked aspects of WordPress plugin tutorials, yet they are arguably the most important. A tutorial that shows how to build a feature without showing how to verify it works correctly and handles edge cases teaches only half the lesson. Modern WordPress development tutorials should include PHPUnit test examples, WP-CLI test commands, and browser testing strategies alongside the implementation code. This testing-first mindset helps developers build confidence in their code and catch regressions before they reach production.
The WordPress developer community's shift toward more professional development practices has elevated the expectations for plugin quality significantly. Practices like dependency management with Composer, automated testing with PHPUnit, continuous integration with GitHub Actions, and static analysis with PHPStan were once considered optional extras. They are now expected baseline practices for serious plugin development. Understanding these tools and how they integrate into the WordPress development workflow is essential knowledge for any developer building plugins that others will rely on.
Broader Context and Best Practices
Step-by-step tutorials for WordPress plugin development serve a critical role in the ecosystem by bridging the gap between documentation and practical implementation. WordPress.org documentation explains what functions are available, but tutorials show how to combine them into working solutions. This practical knowledge is especially valuable for patterns that span multiple WordPress subsystems, such as building a custom REST API endpoint that validates input, checks permissions, queries the database, and returns properly formatted responses. Each step involves different WordPress APIs that must work together correctly.
The most effective WordPress development tutorials teach not just the how but the why behind each decision. Understanding why WordPress uses nonces instead of simpler tokens, why capability checks should test specific capabilities rather than roles, or why prepared statements matter more than escaping for SQL queries gives developers the foundation to make good decisions when they encounter situations that tutorials haven't covered. This deeper understanding is what separates developers who can follow instructions from developers who can architect secure, maintainable solutions.
Frequently Asked Questions
What's the difference between PHPCS and PHPStan?
PHPCS checks code style and formatting—whether your code follows the WordPress coding standards. PHPStan performs static type analysis to detect logical errors like undefined variables or type mismatches. Use both: PHPCS for consistency, PHPStan for correctness.
Can I run these checks locally before pushing?
Yes, and you should! Set up Git pre-commit hooks to run PHPCS and PHPStan before allowing commits. This prevents failed CI builds:
# .git/hooks/pre-commit
#!/bin/sh
composer run lint || exit 1
composer run analyze || exit 1
Should I fail the build for style violations?
This depends on your team culture. Some teams want zero style violations (enforce with CI failures), while others treat violations as suggestions. Consistency is more important than the specific choice.
How do I suppress specific warnings?
Use rule-specific comments:
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Intentional raw query
$results = $wpdb->get_results( $query );
For PHPStan:
/** @phpstan-ignore-next-line */
$data = $questionable_function();
What security issues should fail the build?
Critical issues like SQL injection vulnerabilities, hardcoded credentials, and authentication bypasses should fail the build. Medium-severity issues like missing input validation should trigger warnings. Configure WP HealthKit to enforce a minimum security score before merging.
How do I handle legacy code that violates standards?
Use phpcs.xml.dist to exclude files or rules progressively. Fix violations gradually while maintaining a quality gate for new code:
<exclude-pattern>/legacy/</exclude-pattern>
<!-- But still check legacy for critical issues -->
<rule ref="WordPress.Security"/>
Conclusion
WordPress plugin automated code review CI/CD pipelines transform code quality by providing instant feedback on standards violations, logical errors, and security issues. By integrating PHPCS for style checking, PHPStan for type analysis, and WP HealthKit for comprehensive security scanning, you create a robust quality gate that catches issues before they reach production.
The best code review is continuous, not episodic. Automated checks run on every pull request, preventing both the merge of problematic code and the review bottleneck of manual checking. Developers get immediate feedback, reviewers focus on architecture, and your codebase maintains consistent quality standards.
Setting up automated code review requires initial effort but pays dividends in code quality, faster development cycles, and reduced production issues. Start with PHPCS and PHPStan, then add WP HealthKit for comprehensive security analysis. Your future self—and your users—will thank you.
Begin implementing automated code review in your CI/CD pipeline today. Use WP HealthKit to catch security issues automatically across your entire codebase.