Files
michaelschiemer/docs/quality/code-quality-scanner.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

113 lines
3.8 KiB
Markdown

# Code Quality Scanner
This module provides repository-aware rules that validate architectural conventions. It currently ships with the following rules:
- `StringableImplementation`: classes that define `__toString()` must implement `Stringable`
- `FinalClass`: value-object classes must be declared `final`
- `ReadonlyClass`: value-object classes must be declared `readonly`
- `ReadonlyGetter`: readonly properties (or classes) should be exposed directly; avoid `get*()` wrappers
- `NoInheritance`: inheritance is forbidden (except for a small allow list, e.g. Exceptions)
## Command Line Usage
Run the scanner from the project root:
```bash
php console.php quality:scan # scans src/ by default
php console.php quality:scan app/path # scan a custom directory
php console.php quality:scan --skip-errors # skip classes/files that cannot be parsed
```
The command groups violations by rule and shows file locations:
```
❌ Found 2 violation(s). Scanned 185 files, 174 classes in 6.91s
StringableImplementation (2)
• App\Domain\User\ValueObjects\UserId
↳ src/Domain/User/ValueObjects/UserId.php:42
Classes defining __toString() must implement Stringable explicitly.
```
The exit code is `0` when all checks pass, or `1` when violations are found. You can wire this command into CI to block regressions.
### Skipping Faulty Classes
Some parts of the repository (legacy examples, experimental prototypes, etc.) may not load because they contain invalid PHP constructs or depend on unavailable interfaces. Use the `--skip-errors` flag to collect a warning and continue scanning the remaining classes:
```bash
php console.php quality:scan --skip-errors
```
When the flag is omitted, any parsing/reflection error stops the scan and the command exits with a non-zero status.
## Adding New Rules
Rules implement `App\Framework\Quality\CodeQuality\CodeQualityRule`:
```php
use App\Framework\Quality\CodeQuality\CodeQualityRule;
use App\Framework\Quality\CodeQuality\Results\RuleViolation;
use App\Framework\Quality\CodeQuality\ValueObjects\ClassInspection;
final class MyCustomRule implements CodeQualityRule
{
public function name(): string
{
return 'MyCustomRule';
}
public function check(ClassInspection $inspection): array
{
if ($this->isValid($inspection)) {
return [];
}
$line = $inspection->getMethodLine('someMethod');
return [
RuleViolation::create(
$inspection->className(),
$inspection->filePath(),
$this->name(),
'Explain what must change.',
$line
),
];
}
}
```
Register the rule inside `CodeQualityScanCommand`:
```php
$this->scanner = new CodeQualityScanner(
$fileScanner,
$reflectionService,
[
new RequireStringableImplementationRule(),
new MyCustomRule(),
],
$logger
);
```
Because rules leverage full reflection data and the actual file path, you have the flexibility to enforce namespacing, attribute usage, dependency boundaries, and more.
## Storage Permissions
The scanner runs inside the console bootstrap. When Redis is unavailable, the framework falls back to the filesystem cache. The cache directory now resolves to `<project-root>/storage/cache`, but you still need to make sure it exists and is writable:
```bash
mkdir -p storage/cache
chmod -R ug+rw storage
```
If you run the command from another working directory (e.g. inside Docker), set the base path explicitly so the cache resolver finds the right storage folder:
```bash
APP_BASE_PATH=/home/michael/dev/michaelschiemer php console.php quality:scan
```
The CLI entry point already exports `APP_BASE_PATH`; keep the environment variable handy for custom runners, background workers, or integration tests.