PHP-QA-CI: A Comprehensive Quality Assurance Pipeline in a Single Dependency
Setting up quality assurance for PHP projects is a pain. You need to install a dozen different tools, each with its own config files and quirks. But what if you could get a complete, battle-tested QA pipeline with just one Composer dependency?
The Problem with Traditional QA Setup
The traditional approach to setting up QA tools is time-consuming:
- Installing multiple dev dependencies individually
- Creating configuration files for each tool
- Writing scripts to run tools in the correct order
- Ensuring consistency across different projects
- Maintaining and updating configurations as tools evolve
- Training team members on different tool interfaces
This fragmented approach creates problems. You get inconsistent setups across projects. Maintenance becomes a nightmare. Teams often skip important QA steps because it's just too complicated.
Enter PHP-QA-CI
PHP-QA-CI solves these problems. Built by Long Term Support LTD, it gives you a complete QA pipeline through a single Composer dependency.
The key innovation is simple. Instead of manually orchestrating multiple tools, PHP-QA-CI provides:
- Pre-configured, sensible defaults for all integrated tools
- Logical execution order that fails fast on errors
- Consistent interface across all projects
- Easy customization when needed
- Version-specific branches for different PHP versions
The Complete Tool Suite
Installing PHP-QA-CI gives you immediate access to a complete suite of QA tools, organized into logical categories:
The tools run in order from fastest to slowest. This gives you quick feedback:
1. Validation and Checks
- PSR-4 Validation - Checks code namespaces for PSR-4 compliance (built-in script)
- Composer Check for Issues - Runs composer diagnose and dumps the autoloader
- Strict Types Enforcing - Finds and fixes files missing strict types declarations
2. Linting
- PHP Parallel Lint - Lightning-fast PHP syntax error checking
3. Static Analysis
- PHPStan - Static code analysis
4. Testing
- PHPUnit - Unit testing
- Infection - Mutation testing that deliberately breaks your code to test how good your tests are
5. Documentation
- Markdown Links Checker - Finds broken links in README.md and docs files (built-in script)
6. Final Checks
- Uncommitted Changes Check - Makes sure you don't have uncommitted changes
7. Code Formatting
- Beautifier and Fixer - Automatically formats PHP code and applies coding standards
- PHP Code Sniffer - Catches any remaining coding standards violations
Installation and Basic Usage
Getting started with PHP-QA-CI requires just a single Composer command:
{
"require-dev": {
"lts/php-qa-ci": "dev-master@dev"
},
"config": {
"bin-dir": "bin"
}
}
Install the package (using the PHP 8.4 branch):
composer require --dev lts/php-qa-ci:dev-php8.4
That's it! You now have access to the complete QA pipeline:
#!/bin/bash
# Run the complete QA pipeline
./bin/qa
# Run with a specific PHP version
export PHP_QA_CI_PHP_EXECUTABLE=/usr/bin/php8.3
./bin/qa
# Run on a specific directory
./bin/qa /path/to/scan
# Run a single tool (example with PHPStan)
./bin/qa -t phpstan
The pipeline runs tools in an order designed to "fail fast." It catches basic issues first before running the more time-consuming analyses.
PHP Version Support
PHP-QA-CI maintains separate branches for different PHP versions. This ensures compatibility and lets you use version-specific features:
master
- Stable release branchphp8.3
- PHP 8.3 specific configurationsphp8.4
- PHP 8.4 support (current recommended branch as of 2025)
This branching strategy gives you optimal configurations for each PHP version. It still maintains backward compatibility when needed.
Configuration and Customization
PHP-QA-CI works out of the box with sensible defaults, but it's easy to customize. The tool looks for custom configurations in your project's qaConfig
directory. If it doesn't find them, it uses the defaults.
Creating Custom Configurations
#!/bin/bash
# Create custom configuration directory
mkdir -p qaConfig
# Copy and customize PHPStan configuration
cp vendor/lts/php-qa-ci/configDefaults/generic/phpstan.neon qaConfig/
# Edit qaConfig/phpstan.neon as needed
# Copy and customize PHP CS Fixer configuration
cp vendor/lts/php-qa-ci/configDefaults/generic/php_cs.php qaConfig/
# Edit qaConfig/php_cs.php as needed
# The QA pipeline will automatically use your custom configs
PHPStan Custom Configuration Example
Here's how to extend the default PHPStan configuration for your project:
includes:
- vendor/lts/php-qa-ci/configDefaults/generic/phpstan.neon
parameters:
level: 9
paths:
- src
- tests
excludePaths:
- tests/fixtures
ignoreErrors:
- '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition::children\(\)#'
reportUnmatchedIgnoredErrors: false
checkMissingIterableValueType: false
PHP CS Fixer Custom Configuration
Customize coding standards while maintaining the base configuration:
<?php
declare(strict_types=1);
// Include the default configuration
$config = require __DIR__ . '/../vendor/lts/php-qa-ci/configDefaults/generic/php_cs.php';
// Get the default finder
$finder = require __DIR__ . '/../vendor/lts/php-qa-ci/configDefaults/generic/php_cs_finder.php';
// Customize the finder if needed
$finder
->exclude('legacy')
->notPath('src/Migrations/Version*.php');
// Add or override rules
$rules = $config->getRules();
$rules['php_unit_test_class_requires_covers'] = false;
$rules['php_unit_internal_class'] = false;
return $config
->setFinder($finder)
->setRules($rules);
Symfony Project Integration
PHP-QA-CI includes special considerations for Symfony projects. When installing in a Symfony project, you have two options:
#!/bin/bash
# For Symfony projects: choose between Symfony defaults or php-qa-ci defaults
# Option 1: Use php-qa-ci defaults (more extensive)
rm phpunit.xml.dist
ln -s vendor/lts/php-qa-ci/configDefaults/generic/phpunit.xml
# Option 2: Keep Symfony defaults
# Simply accept the recipe prompts during installation
# Create project-specific overrides
mkdir -p qaConfig
echo "parameters:
level: 8
paths:
- src
excludePaths:
- var
- vendor" > qaConfig/phpstan.neon
The PHP-QA-CI defaults are more comprehensive than Symfony's defaults. You get additional static analysis rules and stricter coding standards.
Advanced Features
Hooks System
PHP-QA-CI supports pre and post execution hooks, allowing you to integrate custom logic into the pipeline:
#!/bin/bash
# Create custom hooks for the QA pipeline
mkdir -p qaConfig
# Pre-hook: Run before QA pipeline starts
cat > qaConfig/preBashHook.bash << 'EOF'
#!/bin/bash
echo "Starting QA pipeline for project: $(basename $(pwd))"
echo "PHP Version: $($PHP_QA_CI_PHP_EXECUTABLE --version | head -n1)"
# Clear any caches that might affect results
if [ -d "var/cache" ]; then
rm -rf var/cache/*
fi
EOF
# Post-hook: Run after QA pipeline completes
cat > qaConfig/postBashHook.bash << 'EOF'
#!/bin/bash
echo "QA Pipeline completed!"
# Generate a summary report
if [ -f "infection.log" ]; then
echo "Mutation Score: $(grep -oP 'Mutation Score Indicator \(MSI\): \K[0-9.]+' infection.log)%"
fi
# Send notification (example)
# curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
# -H 'Content-type: application/json' \
# --data '{"text":"QA Pipeline completed successfully!"}'
EOF
chmod +x qaConfig/*.bash
Mutation Testing with Infection
One of the most powerful features is mutation testing via Infection. It tests the quality of your test suite by introducing small changes to your code. Then it checks if your tests catch these mutations:
{
"source": {
"directories": [
"src"
]
},
"logs": {
"text": "infection.log",
"summary": "summary.log",
"debug": "debug.log",
"perMutator": "per-mutator.md"
},
"mutators": {
"@default": true,
"global-ignoreSourceCodeByRegex": [
"Assert::.*"
]
},
"testFramework": "phpunit",
"testFrameworkOptions": "--configuration=phpunit.xml"
}
Performance Optimization
The pipeline is optimized for performance in several ways:
- Fail-fast approach - basic checks run first
- Parallel execution where possible
- Intelligent caching of results
- Option to run quick tests only during development
CI/CD Integration
PHP-QA-CI works seamlessly in CI environments. Here's an example GitHub Actions workflow:
name: Quality Assurance
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
qa:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.1', '8.2', '8.3']
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: xdebug
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run QA Pipeline
run: ./bin/qa
env:
PHP_QA_CI_PHP_EXECUTABLE: /usr/bin/php${{ matrix.php-version }}
The pipeline works just as well with GitLab CI, Jenkins, or Bitbucket Pipelines. The consistent interface means your local development experience matches your CI environment exactly.
Real-World Benefits
Consistency Across Projects
With PHP-QA-CI, all your projects use the same QA pipeline, making it easy for developers to move between projects without learning new tools or configurations.
Time Savings
Setting up a complete QA pipeline manually takes hours or even days. With PHP-QA-CI, you're up and running in minutes with a battle-tested configuration.
Maintenance Reduction
Instead of maintaining configurations for a dozen tools across multiple projects, you maintain just one dependency. Tool configuration updates are handled centrally.
Best Practices by Default
The default configurations include years of PHP development best practices. Your code meets high quality standards without you having to research what those standards should be.
Comparison with Manual Setup
Consider what manual setup of these tools would require:
Aspect | Manual Setup | PHP-QA-CI |
---|---|---|
Initial Setup Time | 2-4 hours | 5 minutes |
Configuration Files | 10-15 files | 0 (uses defaults) |
Composer Dependencies | 12+ packages | 1 package |
Execution Scripts | Custom required | Single qa command |
Cross-project Consistency | Manual synchronization | Automatic |
Tool Updates | Individual updates | Single update |
Troubleshooting Common Issues
Permission Issues
If you encounter permission issues with the qa script:
chmod +x vendor/lts/php-qa-ci/bin/qa
# Or use composer's bin directory
chmod +x bin/qa
Memory Limits
Some tools like PHPStan may require increased memory limits:
export PHP_QA_CI_PHP_EXECUTABLE="php -d memory_limit=512M"
./bin/qa
Tool-Specific Issues
Individual tools can be run in isolation for debugging:
# Run only PHPStan
./bin/qa phpstan
# Run with verbose output
./bin/qa --verbose
Future Development
PHP-QA-CI keeps evolving with the PHP ecosystem. Current development focuses on:
- Support for newer PHP versions as they're released
- Integration of emerging QA tools
- Performance optimizations for large codebases
- Enhanced reporting and metrics
- Better IDE integration support
Conclusion
PHP-QA-CI changes how you set up quality assurance for PHP projects. It provides a complete, pre-configured pipeline through a single dependency. This removes the barriers to implementing comprehensive quality checks.
Whether you're starting a new project or improving QA in an existing codebase, PHP-QA-CI offers immediate value with minimal setup. The combination of sensible defaults, easy customization, and comprehensive tool coverage makes it essential for any serious PHP development workflow.
The tool embodies the philosophy of the PHP language itself: pragmatic, powerful, and focused on developer productivity. By abstracting away QA pipeline complexity, PHP-QA-CI lets developers focus on what matters most. Writing quality code.
Get Started Today
Ready to streamline your PHP quality assurance workflow? Visit the PHP-QA-CI GitHub repository or install it directly via Composer:
composer require --dev lts/php-qa-ci:dev-master@dev