feat: add QA pipeline with security and mutation testing tools

Add comprehensive PHP quality assurance tooling:

**New tools:**
- roave/security-advisories - Blocks packages with known CVEs
- infection/infection - Mutation testing for test quality
- rector/rector - Automated refactoring and PHP upgrades
- psalm/plugin-laravel - Better Laravel support in Psalm

**New config files:**
- qa.yaml - QA pipeline definition for `core php qa` command
- infection.json5 - Mutation testing configuration
- rector.php - Automated refactoring rules

**QA Pipeline stages:**
1. Quick: security audit, code style, PHPStan
2. Standard: Psalm, tests
3. Full: Rector dry-run, mutation testing

**Current status:**
- Security: No vulnerabilities
- Pint: Pass
- PHPStan: Level 1, 0 errors
- Psalm: Level 8, 0 errors, 93% type inference
- Tests: 197 passing
- Rector: 225 files with potential improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Snider 2026-01-29 23:21:12 +00:00
parent 560c6aec4d
commit 94ce7bc1e7
6 changed files with 181 additions and 1 deletions

6
.gitignore vendored
View file

@ -20,3 +20,9 @@ public/build
/coverage
/docs/.vitepress/dist
docs/.vitepress/cache/
# QA tools
.infection/
infection.log
infection-summary.log
.rector-cache/

View file

@ -17,6 +17,7 @@
},
"require-dev": {
"fakerphp/faker": "^1.23",
"infection/infection": "^0.32.3",
"larastan/larastan": "^3.9",
"laravel/pint": "^1.18",
"mockery/mockery": "^1.6",
@ -26,6 +27,9 @@
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpunit/phpunit": "^11.5",
"psalm/plugin-laravel": "^3.0",
"rector/rector": "^2.3",
"roave/security-advisories": "dev-latest",
"spatie/laravel-activitylog": "^4.8",
"vimeo/psalm": "^6.14"
},
@ -72,7 +76,8 @@
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": true,
"phpstan/extension-installer": true
"phpstan/extension-installer": true,
"infection/extension-installer": true
}
},
"minimum-stability": "stable",

20
infection.json5 Normal file
View file

@ -0,0 +1,20 @@
{
"$schema": "https://raw.githubusercontent.com/infection/infection/0.29.0/resources/schema.json",
"source": {
"directories": ["src"]
},
"logs": {
"text": "infection.log",
"summary": "infection-summary.log"
},
"mutators": {
"@default": true
},
"phpUnit": {
"configDir": "."
},
"testFramework": "phpunit",
"tmpDir": ".infection",
"minMsi": 50,
"minCoveredMsi": 70
}

View file

@ -8,6 +8,10 @@
findUnusedBaselineEntry="false"
findUnusedCode="false"
>
<plugins>
<pluginClass class="Psalm\LaravelPlugin\Plugin" />
</plugins>
<issueHandlers>
<MissingOverrideAttribute>
<errorLevel type="suppress">

107
qa.yaml Normal file
View file

@ -0,0 +1,107 @@
# PHP Quality Assurance Pipeline
# This file defines the QA process for `core php qa` command
#
# Usage: core php qa [--fix] [--full]
# --fix Apply automatic fixes where possible
# --full Run full suite including slow checks (mutation testing)
name: PHP Quality Assurance
version: 1.0.0
# Tool versions and config files
tools:
pint:
config: pint.json
description: Code style (PSR-12 + Laravel conventions)
phpstan:
config: phpstan.neon
level: 1
description: Static analysis (type checking)
psalm:
config: psalm.xml
level: 8
description: Static analysis (deeper type inference)
infection:
config: infection.json5
description: Mutation testing (test quality)
rector:
config: rector.php
description: Automated refactoring and upgrades
# QA Pipeline stages
stages:
# Stage 1: Quick checks (< 30 seconds)
quick:
- name: Security Audit
command: composer audit
description: Check dependencies for known vulnerabilities
fix: false
- name: Code Style
command: ./vendor/bin/pint --test
fix_command: ./vendor/bin/pint
description: Check PSR-12 and Laravel code style
- name: PHPStan
command: ./vendor/bin/phpstan analyse --no-progress
description: Static analysis level 1
fix: false
# Stage 2: Standard checks (< 2 minutes)
standard:
- name: Psalm
command: ./vendor/bin/psalm --no-progress
description: Deep static analysis
fix: false
- name: Tests
command: ./vendor/bin/phpunit --testdox
description: Run test suite
fix: false
# Stage 3: Full checks (can be slow)
full:
- name: Rector (dry-run)
command: ./vendor/bin/rector process --dry-run
fix_command: ./vendor/bin/rector process
description: Check for automated improvements
- name: Mutation Testing
command: ./vendor/bin/infection --min-msi=50 --min-covered-msi=70 --threads=4
description: Test suite quality via mutation testing
fix: false
slow: true
# Exit codes
exit_codes:
0: All checks passed
1: Code style issues (fixable)
2: Static analysis errors
3: Test failures
4: Security vulnerabilities
5: Mutation score too low
# Recommended CI configuration
ci:
# Run on every push
push:
- quick
- standard
# Run on PRs to main
pull_request:
- quick
- standard
- full
# Thresholds
thresholds:
phpstan_level: 1
psalm_level: 8
test_coverage: 70
mutation_msi: 50
mutation_covered_msi: 70

38
rector.php Normal file
View file

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return RectorConfig::configure()
->withPaths([
__DIR__.'/src',
])
->withSkip([
__DIR__.'/src/Core/Activity',
__DIR__.'/src/Core/Tests',
__DIR__.'/src/Mod/Trees',
])
->withSets([
// PHP version upgrades
LevelSetList::UP_TO_PHP_82,
// Code quality
SetList::CODE_QUALITY,
SetList::CODING_STYLE,
SetList::DEAD_CODE,
SetList::EARLY_RETURN,
SetList::TYPE_DECLARATION,
])
->withImportNames(
importShortClasses: false,
removeUnusedImports: true
)
->withPreparedSets(
deadCode: true,
codeQuality: true,
typeDeclarations: true,
earlyReturn: true,
);