Download the PHP package sebastiaanwouters/diffalyzer without Composer
On this page you can find all versions of the php package sebastiaanwouters/diffalyzer. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download sebastiaanwouters/diffalyzer
More information about sebastiaanwouters/diffalyzer
Files in sebastiaanwouters/diffalyzer
Package diffalyzer
Short Description Analyze git changes and run only affected PHP tests and static analysis. Speeds up PHPUnit, Psalm, ECS, and PHP-CS-Fixer in CI/CD pipelines.
License MIT
Homepage https://github.com/sebastiaanwouters/diffalyzer
Informations about the package diffalyzer
Diffalyzer
A PHP CLI tool that analyzes git changes and outputs affected PHP file paths in formats compatible with PHPUnit, Psalm, ECS, and PHP-CS-Fixer. This enables optimized test and analysis runs by only processing files that are actually affected by changes.
Features
- Git Integration: Analyze uncommitted, staged, or branch-based changes
- Dependency Analysis: Uses nikic/php-parser to build comprehensive dependency graphs
- Multiple Strategies: Choose between conservative, moderate, or minimal analysis depth
- Format-Specific Output: Tailored output for PHPUnit, Psalm, ECS, and PHP-CS-Fixer
- Configurable Full Scans: Define patterns in config file or CLI to trigger complete scans
- Verbose Diagnostics: Clear feedback about what's happening with --verbose mode
- PSR-12 Compliant: Clean, readable, and well-structured code
Installation
Via Composer (Recommended)
After installation, the binary will be available at vendor/bin/diffalyzer.
From Source
Quick Start
Usage
Basic Usage
With Strategies
Git Comparison Options
Full Scan Pattern
Full-scan patterns can be configured via config file (recommended) or CLI flag:
Via config file (recommended):
Via CLI flag (overrides config):
Note: Always use --verbose to see:
- Which pattern is being used
- Which files changed
- Whether the pattern matched any files
- Whether full scan was triggered
Integration Examples
PHPUnit
Psalm
ECS (Easy Coding Standard)
PHP-CS-Fixer
Command Line Options
| Option | Short | Description | Default |
|---|---|---|---|
--output |
-o |
Output format: test (test files only) or files (all files) |
Required |
--strategy |
-s |
Analysis strategy: conservative, moderate, minimal |
conservative |
--from |
Source ref for comparison (branch or commit hash) | ||
--to |
Target ref for comparison (branch or commit hash) | HEAD |
|
--staged |
Only analyze staged files | false |
|
--full-scan-pattern |
Regex (e.g., /\.xml$/) or glob pattern (e.g., *.xml) to trigger full scan (overrides config) |
||
--config |
-c |
Path to config file | Auto-detect |
--verbose |
-v |
Show detailed diagnostic information (outputs to stderr) | false |
--test-pattern |
Custom regex pattern to match test files | ||
--no-cache |
Disable cache and force full rebuild | false |
|
--clear-cache |
Clear cache before analysis | false |
|
--cache-stats |
Show cache statistics after analysis | false |
|
--parallel |
-p |
Number of parallel workers for parsing | Auto-detect |
Configuration File
Diffalyzer supports configuration files to centralize settings like full-scan patterns. Configuration files are automatically detected in the following order:
.diffalyzer.ymldiffalyzer.ymlconfig.yml
Or specify a custom path with --config path/to/config.yml.
Example Configuration
Pattern Types
Glob patterns (recommended for simplicity):
composer.json- Exact filename match*.json- Any file ending with .jsonconfig/**- Any file in config directory (any depth)src/*.php- PHP files in src directory (one level)
Regex patterns (for advanced matching):
- Must start with
/or# /\.config\.(js|ts)$/- Matches .config.js or .config.ts/^(config|deploy)\//- Matches files in config/ or deploy/ directories
Complete Override Behavior
When you define patterns in your config file, they completely replace the built-in defaults:
- With config file: Only your patterns are used
- Without config file: Built-in defaults are used (
composer.json,composer.lock) - With CLI
--full-scan-pattern: CLI always overrides everything (config + built-in)
To disable full scans entirely:
Verbose Mode
Use --verbose (or -v) to see detailed diagnostic information about what diffalyzer is doing:
Verbose output (sent to stderr, won't interfere with stdout):
Or when full scan is triggered:
This makes it much clearer what's happening, especially when you get empty output (which means "run on all files").
Analysis Strategies
Conservative (Default)
Includes all dependency types:
- Use statements (imports)
- Class inheritance (extends)
- Interface implementations
- Trait usage
- Instantiations (
newkeyword) - Static calls
Most comprehensive but may include some false positives.
Moderate
Includes:
- Use statements (imports)
- Class inheritance (extends)
- Interface implementations
- Trait usage
Excludes dynamic method calls and instantiations.
Minimal
Includes only:
- Use statements (imports)
- Direct inheritance (extends/implements)
Fastest but may miss some affected files.
Output Behavior
Partial Scan (Normal Mode)
--output test
Outputs space-separated test file paths that are affected by the changes.
How it works: The tool uses AST-based dependency analysis to find ALL test files that import or use the affected classes. It does NOT assume file naming conventions or directory structures.
Test Method Filtering (New in v1.2.0):
Diffalyzer now supports the :: syntax for specifying individual test methods. When you pass file paths with ::methodName, diffalyzer automatically converts them to PHPUnit's --filter syntax:
- Single method:
tests/UserTest.php::testLogin→tests/UserTest.php --filter testLogin - Multiple methods:
tests/UserTest.php::testLogin tests/FooTest.php::testBar→tests/UserTest.php tests/FooTest.php --filter '/testLogin|testBar/' - Same file, multiple methods:
tests/UserTest.php::testLogin tests/UserTest.php::testLogout→tests/UserTest.php --filter '/testLogin|testLogout/'
This provides an intuitive, framework-agnostic syntax for running specific test methods without needing to remember PHPUnit's --filter syntax.
Examples:
-
Test files that import changed classes
src/User.phpchanges (declaresDiffalyzer\User)tests/UserTest.phpimportsDiffalyzer\User→ included in output- Works regardless of file names or directory structure
-
Transitive dependencies
src/User.phpchangessrc/UserCollector.phpimports/usesUser→ affectedtests/UserCollectorTest.phpimportsUserCollector→ included in output- Full dependency chain is traversed automatically
-
Test files that changed directly
tests/UserTest.phpmodified → included in output
-
No assumptions about structure
- Works with
tests/,test/,Tests/,Test/, or any directory - Works with any test file naming convention (as long as it contains "Test.php")
- Works with custom project structures
- Works with
- Data fixtures via PHP classes
- If tests use fixture/factory classes (e.g.,
UserFixture,UserFactory) - Changes to those fixture classes are tracked via normal dependency analysis
- When
UserFixture.phpchanges → tests importing it are included - No special configuration needed
- If tests use fixture/factory classes (e.g.,
Example output: tests/UserTest.php tests/UserCollectorTest.php tests/Integration/UserFlowTest.php
--output files
Outputs space-separated file paths for all affected files (includes both source and test files).
Use this for static analysis tools (Psalm), code style checkers (ECS, PHP-CS-Fixer), or any tool that needs to process all affected files.
Example output: src/Foo/Bar.php src/Baz/Qux.php tests/FooTest.php
Full Scan Mode
When full-scan patterns match or no specific files are needed:
- All formats output an empty string
- Empty output tells each tool to scan the entire project
- Example:
phpunitwith no arguments runs all tests
Full Scan Triggers:
By default (when no config file is present), these files trigger full scans:
composer.json- Dependencies changed, could affect anythingcomposer.lock- Dependency versions changed
You can customize this behavior in three ways:
- Config file (recommended): Define patterns in
diffalyzer.yml- replaces built-in defaults - CLI flag: Use
--full-scan-pattern- overrides config and built-in defaults - Disable entirely: Set
full_scan_patterns: []in config
Understanding Empty Output:
Empty output is intentional and can mean two things:
- No changes detected - No PHP files were modified
- Full scan triggered - A file matched a full-scan pattern
Use --verbose to see which one:
How It Works
- Git Change Detection: Detects changed PHP files using git diff
- AST Parsing: Parses all project PHP files using nikic/php-parser
- Dependency Graph: Builds forward and reverse dependency maps
- Impact Analysis: Traverses graph to find all affected files
- Format Output: Generates tool-specific output format
Example Workflow
Step 1: Git detects changes
Step 2: Dependency analysis
Step 3: Output by format
For --output files (all source files):
For --output test (test files only):
Result: Run only the 3 tests affected by the User.php change, not all 100+ tests in your suite!
Advanced Integration
Makefile
Use the included Makefile for convenient local development:
Pre-commit Hook
Create .git/hooks/pre-commit:
Make it executable:
Composer Scripts
Add to your composer.json:
Then run:
CI/CD Integration
GitHub Actions
See .github/workflows/ci-example.yml for a complete working example. Basic setup:
GitLab CI
See .gitlab-ci-example.yml for a complete working example. Basic setup:
Troubleshooting
Full-scan pattern not working
Problem: Using --full-scan-pattern but full scan is not triggered.
Solutions:
-
Use
--verboseto debug: This will show you:- Which files actually changed
- Which pattern is being used
- Whether the pattern matched
- Whether full scan was triggered
-
Check pattern syntax:
- Regex patterns must start with
/or#:/\.xml$/,/^config\// - Glob patterns don't need delimiters:
*.xml,phpunit.xml,config/** - When in doubt, use glob patterns (simpler and more intuitive)
- Regex patterns must start with
-
Verify the pattern matches your changed files:
-
Common pattern examples:
- Pattern doesn't match subdirectories?
- For glob: use
config/**notconfig/*for recursive matching - For regex: use
/^config\//to match anything starting withconfig/
- For glob: use
No tests run but I made changes
Cause: You changed a file that no tests depend on.
Solutions:
- Ensure your test files import the classes they test
- Try conservative strategy:
--strategy conservative - Verify your changes are to tracked files (not untracked/ignored)
- Check dependency chain: does a test import your changed class?
All tests run when I change one file
Cause: Full scan was triggered.
Solutions:
- Check if you modified
composer.jsonorcomposer.lock - Check if your change matches
--full-scan-pattern - Review changed files:
git status - This is by design for critical files
Git errors
Cause: Not in a git repository or no commits exist.
Solutions:
- Ensure you're in a git repository:
git init - Create an initial commit:
git add . && git commit -m "Initial commit" - Verify git is accessible:
git --version
Empty output
This is normal behavior and means:
- For PHPUnit: No test files affected OR full scan triggered → run all tests
- For other tools: No files affected OR full scan triggered → analyze all files
Always handle empty output by running the full tool:
Tips & Best Practices
- Use Makefile: Convenient shortcuts for common operations
- CI/CD Branch Comparison: Use
--from origin/mainin pipelines - Start Conservative: Begin with conservative strategy, optimize later if needed
- Fixture Classes: Modern fixtures (PHP classes) are automatically tracked
- Pre-commit Hooks: Use
--stagedflag for pre-commit validation - Full Scan Patterns: Add critical config files to trigger complete scans
- Test Imports: Ensure test files import the classes they test for proper tracking
- Git History: Use
fetch-depth: 0in CI to enable proper branch comparison
Requirements
PHP Version Support
Diffalyzer supports the following PHP versions:
| PHP Version | Status | Tested |
|---|---|---|
| 8.1 | ✅ Supported | ✅ Yes |
| 8.2 | ✅ Supported | ✅ Yes |
| 8.3 | ✅ Supported | ✅ Yes |
| 8.4 | ✅ Supported | ✅ Yes |
| 8.0 or lower | ❌ Not supported | - |
All versions are actively tested in CI/CD with both prefer-lowest and prefer-stable dependency strategies.
Other Requirements
- Git: Any recent version
- Composer: 2.0 or higher
Dependencies
nikic/php-parser^5.0symfony/console^6.4 || ^7.0symfony/process^6.4 || ^7.0symfony/finder^6.4 || ^7.0symfony/yaml^6.4 || ^7.0
License
MIT
Author
Created by Sebastiaan Wouters for optimized PHP testing and analysis workflows.
All versions of diffalyzer with dependencies
nikic/php-parser Version ^5.0
symfony/console Version ^6.4 || ^7.0
symfony/process Version ^6.4 || ^7.0
symfony/finder Version ^6.4 || ^7.0
symfony/yaml Version ^6.4 || ^7.0