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

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 branch
  • php8.3 - PHP 8.3 specific configurations
  • php8.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