lts / php-qa-ci
Simple PHP QA pipeline and scripts. Largely just a collection of dependencies with configuration and scripts to run them together
Package info
github.com/LongTermSupport/php-qa-ci
Language:Python
Type:composer-plugin
pkg:composer/lts/php-qa-ci
Requires
- php: ^8.3
- composer-plugin-api: ^2.0
- ext-json: *
- ext-openssl: *
- ext-tokenizer: *
- ext-xml: *
- ergebnis/composer-normalize: ^2.42
- funkyproject/reflection-file: @stable
- php-parallel-lint/php-console-color: @stable
- php-parallel-lint/php-parallel-lint: @stable
- phpstan/extension-installer: @stable
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: @stable
- phpunit/phpunit: @stable
- sqlftw/sqlftw: ^0.1.17
- thecodingmachine/safe: ^3.3.0
Requires (Dev)
- roave/security-advisories: dev-master
Suggests
- nunomaduro/larastan: Laravel specific checks (PHPStan Wrapper)
- phploc/phploc: get some stats, not currently compatible with latest symfony
- phpstan/phpstan-deprecation-rules: Checks for deprecated functions and methods
- phpstan/phpstan-doctrine: Adds checks for Doctrine
- phpstan/phpstan-mockery: Prevents Mockery from failing on Stan
- phpstan/phpstan-phpunit: Adds checks for PHPUnit tests
- phpstan/phpstan-symfony: Symfony specific checks
- sllh/composer-versions-check: To be brought back in when there is a PHP8 version...
Replaces
This package is auto-updated.
Last update: 2026-03-16 10:44:32 UTC
README
A comprehensive quality assurance and continuous integration pipeline for PHP 8.3+ projects, written in Bash. Runs tools in a logical order designed to fail as quickly as possible, suitable for both local development and CI.
This package is written for and tested on Linux.
Install
composer require --dev lts/php-qa-ci:dev-php8.4@dev
The qa script will be installed in your project's bin directory. By default, Composer uses vendor/bin, but you can configure a custom location in your composer.json:
"config": { "bin-dir": "bin" }
For Symfony projects, you can accept the prompts to run recipes, but you will then need to decide whether to stick with Symfony defaults or the php-qa-ci defaults (which are more extensive). If you decide to keep the php-qa-ci defaults, remove the config files created by the Symfony recipe:
# Revert to php-qa-ci PHPUnit configs (compare files first)
rm phpunit.xml.dist
ln -s vendor/lts/php-qa-ci/configDefaults/generic/phpunit.xml
Required Composer Configuration
Your project's composer.json must allow the required plugins:
{
"config": {
"allow-plugins": {
"ergebnis/composer-normalize": true,
"lts/php-qa-ci": true,
"phpstan/extension-installer": true
}
}
}
What It Does
PHP-QA-CI orchestrates multiple PHP quality tools across four phases:
Phase 1 -- Code Modification:
- Rector (safe functions, PHPUnit, PHP 8.4 upgrades)
- PHP CS Fixer
Phase 2 -- Linting and Validation: 3. PSR-4 Validation 4. Composer Checks 5. Strict Types Enforcement 6. PHP Lint 7. Composer Require Checker 8. Markdown Links Checker
Phase 3 -- Static Analysis: 9. PHPStan (level max)
Phase 4 -- Testing: 10. PHPUnit 11. Infection (mutation testing, optional, requires Xdebug)
Post-Success: PHPLoc (stats only, cannot fail)
See Pipeline Architecture for full details.
Tool Delivery
PHP-QA-CI uses a hybrid approach to tool delivery:
- PHARs (via PHIVE): PHPStan, PHP CS Fixer, Infection, Composer Require Checker -- delivered in
vendor-phar/ - Composer dependencies: PHPUnit, phpstan-strict-rules, phpstan-phpunit, parallel-lint
- Isolated Composer project: Rector -- in
tools/rector/with its owncomposer.jsonto prevent dependency conflicts
The phpstan/phpstan package is in the replace section of composer.json since PHPStan is provided via PHAR. This prevents version conflicts when consuming projects also require PHPStan extensions.
Custom PHPStan Rules
PHP-QA-CI ships with custom PHPStan rules that are auto-loaded via the PHPStan extension installer:
- ForbidMockingFinalClassRule -- Prevents mocking of final classes
- ForbidAllowMockWithoutExpectationsRule -- Bans
#[AllowMockObjectsWithoutExpectations] - ForbidDangerousFunctionsRule -- Bans exec/eval/unserialize and similar
- ForbidEmptyCatchBlockRule -- Requires catch blocks to have a body
- RequireDeclareStrictTypesRule -- Requires
declare(strict_types=1)in all PHP files
Projects can add their own rules alongside these defaults.
Quick Setup Scripts
GitHub Actions Setup
Automatically install the GitHub Actions workflow for continuous integration:
vendor/lts/php-qa-ci/scripts/install-github-actions.bash
This will:
- Create
.github/workflows/qa.ymlwith an optimized QA pipeline - Auto-detect your PHP version from
composer.json - Configure smart caching for faster builds
- Set up artifact storage for test results
Branch Protection Setup
Configure GitHub branch protection rules with sensible defaults:
# Standard protection (admins can bypass) vendor/lts/php-qa-ci/scripts/setup-branch-protection.bash # Hardened protection (CI enforced for everyone) vendor/lts/php-qa-ci/scripts/setup-branch-protection.bash --harden
Prerequisites: Requires GitHub CLI (gh) installed and authenticated.
CI/CD Workflows
PHP-QA-CI includes three GitHub Actions workflows in .github/workflows/:
ci.yml-- Runs on push/PR tophp8.4, executesbash ci.bashqa.yml-- Template workflow for consuming projects (copy to your project)update-deps.yml-- Weekly scheduled workflow that updates all dependencies (Composer, PHARs via PHIVE, isolated Rector), runs the full QA pipeline, and creates an auto-merge PR if green
See GitHub Actions Integration for setup details.
Claude Code Integration
PHP-QA-CI integrates with Claude Code to provide development guardrails and automation.
Deployment
Deploy skills and hooks to your project:
vendor/lts/php-qa-ci/scripts/deploy-skills.bash vendor/lts/php-qa-ci .
This will:
- Copy hooks to
.claude/hooks/ - Register them in
.claude/settings.json - Detect and configure hooks-daemon if present (see hooks-daemon documentation for installation)
- Migrate from legacy classic hooks if found
Included Hooks
php-qa-ci__auto-continue.py-- Reduces confirmation promptsphp-qa-ci__prevent-destructive-git.py-- Blocks commands that destroy uncommitted changesphp-qa-ci__discourage-git-stash.py-- Discourages git stash with escape hatchphp-qa-ci__block-plan-time-estimates.py-- Prevents time estimates in plan documentsphp-qa-ci__validate-claude-readme-content.py-- Ensures docs contain instructions, not logsphp-qa-ci__enforce-markdown-organization.py-- Enforces doc organization
See .claude/hooks/README.md for detailed hook documentation after deployment.
Composer Plugins
PHP-QA-CI registers three Composer plugins:
- PhiveUpdatePlugin -- Manages PHAR installation via PHIVE
- SkillsDeployPlugin -- Deploys Claude Code skills and hooks
- PhpStanGuardPlugin -- Prevents
phpstan/phpstanfrom being installed alongside the PHAR
Docs
Comprehensive documentation is available in the ./docs folder:
- Pipeline Architecture -- Tool execution order and phases
- Tools Overview -- All tools with configuration details
- Configuration -- Customizing tool settings and overrides
- Coding Standards -- PHP CS Fixer and Rector configuration
- GitHub Actions Integration -- CI/CD setup guide
- Continuous Integration -- General CI usage and workflows
- Platform Detection -- Symfony/Laravel specific settings
Tool-specific documentation:
- PHPStan -- Static analysis configuration and custom rules
- PHPUnit -- Test runner configuration and modes
- Infection -- Mutation testing setup
Other Notes
Specify PHP Binary Path
If you are running multiple PHP versions, you can specify which one to use:
export PHP_QA_CI_PHP_EXECUTABLE=/bin/php84 vendor/bin/qa # Or inline: PHP_QA_CI_PHP_EXECUTABLE=/bin/php84 vendor/bin/qa
Running Specific Tools
# Run only PHPStan vendor/bin/qa -t stan # Run only PHP CS Fixer vendor/bin/qa -t fixer # Run on specific path vendor/bin/qa -t stan -p src/Domain
Branches
php8.4-- Default branch, targets PHP 8.4php8.3-- PHP 8.3 support
Long Term Support
This package was brought to you by Long Term Support LTD, a company run and founded by Joseph Edmonds.
You can get in touch with Joseph at https://ltscommerce.dev/
Check out Joseph's recent book The Art of Modern PHP 8