diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 5e4089f..b6bd290 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -63,6 +63,9 @@ jobs: - name: Static analysis run: vendor/bin/phpstan analyse --memory-limit=1G -c phpstan.dist.neon + - name: Architecture (Deptrac) + run: vendor/bin/deptrac analyse --no-interaction + - name: Create and migrate test database env: DATABASE_URL: postgresql://app:!ChangeMe!@postgres:5432/app?serverVersion=16&charset=utf8 diff --git a/.gitignore b/.gitignore index f48a397..8eb4e04 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ phpstan.* !phpstan.dist.neon ###< phpstan/phpstan ### + +.deptrac.cache diff --git a/composer.json b/composer.json index 9dfe4b4..aae5fa9 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,8 @@ "stan": "phpstan analyse --memory-limit=1G", "stan-baseline": "phpstan analyse --memory-limit=1G --generate-baseline", "test": "phpunit", - "cs": "php-cs-fixer fix" + "cs": "php-cs-fixer fix", + "deptrac": "deptrac analyse --no-interaction" }, "conflict": { "symfony/symfony": "*" @@ -105,6 +106,7 @@ }, "require-dev": { "dama/doctrine-test-bundle": "^8.6", + "deptrac/deptrac": "^4.6", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.2", "phpstan/phpstan-doctrine": "^2.0", diff --git a/composer.lock b/composer.lock index cf350c8..6ee4be7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b14a697ba14ca17f0a5361d3e5fff5fc", + "content-hash": "7f5ff8c2e2a69f08b4522770b961fc80", "packages": [ { "name": "composer/semver", @@ -7759,6 +7759,151 @@ } ], "packages-dev": [ + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, { "name": "dama/doctrine-test-bundle", "version": "v8.6.0", @@ -7828,6 +7973,91 @@ }, "time": "2026-01-21T07:39:44+00:00" }, + { + "name": "deptrac/deptrac", + "version": "4.6.1", + "source": { + "type": "git", + "url": "https://github.com/deptrac/deptrac.git", + "reference": "6ff20dec210f119a4ddebdf8e28603689f34eb67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/deptrac/deptrac/zipball/6ff20dec210f119a4ddebdf8e28603689f34eb67", + "reference": "6ff20dec210f119a4ddebdf8e28603689f34eb67", + "shasum": "" + }, + "require": { + "composer/xdebug-handler": "^3.0", + "jetbrains/phpstorm-stubs": "2024.3 || 2025.3 || 2026.1", + "nikic/php-parser": "^5", + "php": "^8.2", + "phpdocumentor/graphviz": "^2.1", + "phpdocumentor/type-resolver": "^1.9.0 || ^2.0.0", + "phpstan/phpdoc-parser": "^1.5.0 || ^2.1.0", + "phpstan/phpstan": "^2.0", + "psr/container": "^2.0", + "psr/event-dispatcher": "^1.0", + "symfony/config": "^6.4 || ^7.4 || ^8.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.4 || ^8.0", + "symfony/event-dispatcher": "^6.4 || ^7.4 || ^8.0", + "symfony/event-dispatcher-contracts": "^3.4", + "symfony/filesystem": "^6.4 || ^7.4 || ^8.0", + "symfony/finder": "^6.4 || ^7.4 || ^8.0", + "symfony/yaml": "^6.4 || ^7.4 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8", + "ergebnis/composer-normalize": "^2.45", + "ext-libxml": "*", + "symfony/stopwatch": "^6.4 || ^7.4 || ^8.0" + }, + "suggest": { + "ext-dom": "For using the JUnit output formatter" + }, + "bin": [ + "deptrac" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": true, + "target-directory": "tools" + } + }, + "autoload": { + "psr-4": { + "Deptrac\\Deptrac\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tim Glabisch" + }, + { + "name": "Simon Mönch" + }, + { + "name": "Denis Brumann" + } + ], + "description": "Deptrac is a static code analysis tool that helps to enforce rules for dependencies between software layers.", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/deptrac/deptrac/issues", + "source": "https://github.com/deptrac/deptrac/tree/4.6.1" + }, + "time": "2026-05-13T08:23:06+00:00" + }, { "name": "fakerphp/faker", "version": "v1.24.1", @@ -7891,6 +8121,50 @@ }, "time": "2024-11-21T13:46:39+00:00" }, + { + "name": "jetbrains/phpstorm-stubs", + "version": "v2026.1", + "source": { + "type": "git", + "url": "https://github.com/JetBrains/phpstorm-stubs", + "reference": "2cdd054c4109dfb76667c9198bf9427606354243" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/2cdd054c4109dfb76667c9198bf9427606354243", + "reference": "2cdd054c4109dfb76667c9198bf9427606354243", + "shasum": "" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v3.86", + "nikic/php-parser": "^v5.6", + "phpdocumentor/reflection-docblock": "^5.6", + "phpunit/phpunit": "^12.3" + }, + "type": "library", + "autoload": { + "files": [ + "PhpStormStubsMap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "PHP runtime & extensions header files for PhpStorm", + "homepage": "https://www.jetbrains.com/phpstorm", + "keywords": [ + "autocomplete", + "code", + "inference", + "inspection", + "jetbrains", + "phpstorm", + "stubs", + "type" + ], + "time": "2026-02-19T20:12:01+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.13.4", @@ -8127,6 +8401,59 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpdocumentor/graphviz", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/GraphViz.git", + "reference": "115999dc7f31f2392645aa825a94a6b165e1cedf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/115999dc7f31f2392645aa825a94a6b165e1cedf", + "reference": "115999dc7f31f2392645aa825a94a6b165e1cedf", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "mockery/mockery": "^1.2", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^8.2 || ^9.2", + "psalm/phar": "^4.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\GraphViz\\": "src/phpDocumentor/GraphViz", + "phpDocumentor\\GraphViz\\PHPStan\\": "./src/phpDocumentor/PHPStan" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "description": "Wrapper for Graphviz", + "support": { + "issues": "https://github.com/phpDocumentor/GraphViz/issues", + "source": "https://github.com/phpDocumentor/GraphViz/tree/2.1.0" + }, + "time": "2021-12-13T19:03:21+00:00" + }, { "name": "phpstan/extension-installer", "version": "1.4.3", diff --git a/deptrac.yaml b/deptrac.yaml new file mode 100644 index 0000000..4c819d3 --- /dev/null +++ b/deptrac.yaml @@ -0,0 +1,59 @@ +# Permissive baseline (#15): codifies the dependency directions observed in the +# current codebase as a starting ruleset. Tighten incrementally as the +# architecture evolves — see ticket #15 for the rationale. +deptrac: + paths: + - ./src + + layers: + - name: Controller + collectors: + - type: directory + value: src/Controller/.* + + - name: Presenter + collectors: + - type: directory + value: src/Presenter/.* + + - name: Repository + collectors: + - type: directory + value: src/Repository/.* + + - name: Entity + collectors: + - type: directory + value: src/Entity/.* + + - name: Service + collectors: + - type: directory + value: src/Services/.* + + - name: Fixtures + collectors: + - type: directory + value: src/Factory/.* + - type: directory + value: src/Story/.* + + ruleset: + Controller: + - Entity + - Presenter + - Repository + - Service + Presenter: + - Entity + Repository: + - Entity + Entity: + - Entity + - Repository + # Services currently have no internal App\ dependencies — kept empty + # intentionally to flag the first dependency a Service ever takes on. + Service: ~ + Fixtures: + - Entity + - Repository diff --git a/symfony.lock b/symfony.lock index 621dcae..06495fc 100644 --- a/symfony.lock +++ b/symfony.lock @@ -11,6 +11,9 @@ "config/packages/dama_doctrine_test_bundle.yaml" ] }, + "deptrac/deptrac": { + "version": "4.6.1" + }, "doctrine/deprecations": { "version": "1.1", "recipe": {