diff --git a/.github/workflows/backend-ci.yaml b/.github/workflows/backend-ci.yaml index 780c1ecb70..dec1940277 100644 --- a/.github/workflows/backend-ci.yaml +++ b/.github/workflows/backend-ci.yaml @@ -13,7 +13,7 @@ jobs: strategy: matrix: php: - - '8.3' + - '8.4' steps: - uses: actions/checkout@v7 @@ -26,6 +26,28 @@ jobs: - name: Run code style check run: composer run-script check-cs -- --format=checkstyle | cs2pr + env: + PHP_CS_FIXER_IGNORE_ENV: 1 + + deptrac: + name: Deptrac + runs-on: "ubuntu-26.04" + strategy: + fail-fast: false + matrix: + php: + - '8.4' + steps: + - uses: actions/checkout@v7 + - name: Install Composer dependencies + uses: ibexa/gh-workflows/actions/composer-install@main + with: + gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} + satis-network-token: ${{ secrets.SATIS_NETWORK_TOKEN }} + - name: Run deptrac + run: composer run-script deptrac tests: name: Unit tests & SQLite integration tests @@ -36,7 +58,6 @@ jobs: fail-fast: false matrix: php: - - '8.3' - '8.4' steps: @@ -85,7 +106,6 @@ jobs: fail-fast: false matrix: php: - - '8.3' - '8.4' image: - 'postgres:14' @@ -137,7 +157,6 @@ jobs: fail-fast: false matrix: php: - - '8.3' - '8.4' image: - 'mysql:8.0' @@ -189,7 +208,6 @@ jobs: fail-fast: false matrix: php: - - '8.3' - '8.4' steps: - uses: actions/checkout@v7 diff --git a/.github/workflows/gha-docker-solr.yaml b/.github/workflows/gha-docker-solr.yaml index f045fdf60f..dd148cc8d6 100644 --- a/.github/workflows/gha-docker-solr.yaml +++ b/.github/workflows/gha-docker-solr.yaml @@ -18,7 +18,7 @@ jobs: runs-on: "ubuntu-26.04" strategy: matrix: - php-version: [8.3, 8.4] + php-version: [8.4] permissions: packages: write services: diff --git a/.gitignore b/.gitignore index 0e0fe9fb47..d066dbaba1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,6 @@ var/ composer.lock .php-cs-fixer.cache .phpunit.result.cache +/.deptrac.cache phpstan.neon .rules/ diff --git a/composer.json b/composer.json index 8ab252a362..2cab86426e 100644 --- a/composer.json +++ b/composer.json @@ -64,6 +64,7 @@ }, "require-dev": { "behat/behat": "^3.6.1", + "deptrac/deptrac": "^4.7", "friends-of-behat/mink-extension": "^2.4", "ibexa/code-style": "~2.1.0", "ibexa/rector": "~6.0.x-dev", @@ -94,6 +95,7 @@ "Ibexa\\Bundle\\LegacySearchEngine\\": "src/bundle/LegacySearchEngine", "Ibexa\\Contracts\\Core\\": "src/contracts", "Ibexa\\Core\\": "src/lib", + "Ibexa\\InternalContracts\\Core\\": "src/internal-contracts/", "Ibexa\\Tests\\Core\\": "tests/lib", "Ibexa\\Tests\\Integration\\Core\\": "tests/integration/Core", "Ibexa\\Tests\\Bundle\\Core\\": "tests/bundle/Core", @@ -128,6 +130,7 @@ "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", "unit": "phpunit -c phpunit.xml", "phpstan": "phpstan analyse", + "deptrac": "php vendor/bin/deptrac analyse", "integration": [ "Composer\\Config::disableProcessTimeout", "phpunit -c phpunit-integration-legacy.xml" @@ -140,6 +143,7 @@ }, "scripts-descriptions": { "check-cs": "Run code style checker for all files", + "deptrac": "Run Deptrac architecture testing", "fix-cs": "Fix Coding standard issues in current checkout.", "test": "Run all tests (unit & integration, not functional), might not work on Windows." }, diff --git a/deptrac.baseline.yaml b/deptrac.baseline.yaml new file mode 100644 index 0000000000..9f2b7999e2 --- /dev/null +++ b/deptrac.baseline.yaml @@ -0,0 +1,91 @@ +deptrac: + skip_violations: + Ibexa\Contracts\Core\Event\View\PostBuildViewEvent: + - Ibexa\Core\MVC\Symfony\View\View + Ibexa\Contracts\Core\Limitation\Target\Builder\VersionBuilder: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\MVC\EventSubscriber\ConfigScopeChangeSubscriber: + - Ibexa\Core\MVC\Symfony\Event\ScopeChangeEvent + Ibexa\Contracts\Core\MVC\Templating\BaseRenderStrategy: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + - Ibexa\Core\MVC\Symfony\SiteAccess + - Ibexa\Core\MVC\Symfony\Templating\RenderOptions + Ibexa\Contracts\Core\MVC\Templating\RenderStrategy: + - Ibexa\Core\MVC\Symfony\Templating\RenderOptions + Ibexa\Contracts\Core\MVC\View\VariableProvider: + - Ibexa\Core\MVC\Symfony\View\View + Ibexa\Contracts\Core\MVC\View\ViewMatcherRegistryInterface: + - Ibexa\Core\MVC\Symfony\Matcher\ViewMatcherInterface + Ibexa\Contracts\Core\Persistence\Content\Type\CriterionHandlerInterface: + - Ibexa\Core\Persistence\Legacy\Content\Type\Gateway\CriterionVisitor\CriterionVisitor + Ibexa\Contracts\Core\Persistence\Filter\Doctrine\FilteringQueryBuilder: + - Ibexa\Core\Base\Exceptions\DatabaseException + - Ibexa\Core\Persistence\Legacy\Content\Gateway + - Ibexa\Core\Persistence\Legacy\Content\Location\Gateway + - Ibexa\Core\Repository\Values\Content\VersionInfo + Ibexa\Contracts\Core\Persistence\Handler: + - Ibexa\Core\Persistence\Legacy\URL\Handler + Ibexa\Contracts\Core\Pool\Pool: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Content: + - Ibexa\Core\FieldType\Value + Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Location\SubtreeTermAggregation: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\AbstractImageCompositeCriterion: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\AbstractImageRangeCriterion: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Dimensions: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\FileSize: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Height: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Orientation: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + - Ibexa\Core\FieldType\Image\Orientation + Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Width: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\URLWildcard\Query\Criterion\SourceUrl: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\URLWildcard\Query\SortClause: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\URLWildcard\Query\SortClause\DestinationUrl: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Content\URLWildcard\Query\SortClause\Id: + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\Filter\Filter: + - Ibexa\Core\Base\Exceptions\BadStateException + - Ibexa\Core\Base\Exceptions\InvalidArgumentException + Ibexa\Contracts\Core\Repository\Values\User\User: + - Ibexa\Core\FieldType\Value + Ibexa\Contracts\Core\Repository\Values\User\UserGroup: + - Ibexa\Core\FieldType\Value + Ibexa\Contracts\Core\Test\IbexaKernelTestCase: + - Ibexa\Core\Repository\Values\User\UserReference + - Ibexa\Tests\Core\Repository\LegacySchemaImporter + Ibexa\Contracts\Core\Test\IbexaKernelTestTrait: + - Ibexa\Core\Repository\Values\User\UserReference + - Ibexa\Tests\Core\Repository\LegacySchemaImporter + Ibexa\Contracts\Core\Test\IbexaTestKernel: + - Ibexa\Bundle\Core\IbexaCoreBundle + - Ibexa\Bundle\LegacySearchEngine\IbexaLegacySearchEngineBundle + - Ibexa\Tests\Integration\Core\IO\FlysystemTestAdapter + - Ibexa\Tests\Integration\Core\IO\FlysystemTestAdapterInterface + Ibexa\Contracts\Core\Test\Repository\SetupFactory: + - Ibexa\Core\Base\ServiceContainer + - Ibexa\Tests\Integration\Core\Repository\IdManager + Ibexa\Contracts\Core\Test\Repository\SetupFactory\Legacy: + - Ibexa\Bundle\Core\DependencyInjection\ServiceTags + - Ibexa\Core\Base\Container\Compiler\Search\FieldRegistryPass + - Ibexa\Core\Base\ServiceContainer + - Ibexa\Core\Persistence\Legacy\Content\Language\CachingHandler + - Ibexa\Core\Persistence\Legacy\Content\Type\MemoryCachingHandler + - Ibexa\Core\Persistence\Legacy\Handler + - Ibexa\Core\Repository\Values\User\UserReference + - Ibexa\Tests\Core\Repository\IdManager\Php + - Ibexa\Tests\Core\Repository\LegacySchemaImporter + - Ibexa\Tests\Integration\Core\LegacyTestContainerBuilder + - Ibexa\Tests\Integration\Core\Repository\IdManager diff --git a/deptrac.yaml b/deptrac.yaml new file mode 100644 index 0000000000..75bc12dc23 --- /dev/null +++ b/deptrac.yaml @@ -0,0 +1,37 @@ +imports: + - deptrac.baseline.yaml + +deptrac: + paths: + - ./src + - ./tests + layers: + - name: Bundle + collectors: + - type: directory + value: src/bundle/.* + - type: directory + value: src/lib/.* + - name: Contracts + collectors: + - type: directory + value: src/contracts/.* + - name: InternalContracts + collectors: + - type: directory + value: src/internal-contracts/.* + - name: Test + collectors: + - type: directory + value: tests/.* + ruleset: + Bundle: + - Contracts + - InternalContracts + Contracts: ~ + InternalContracts: + - Contracts + Test: + - Bundle + - Contracts + - InternalContracts diff --git a/src/internal-contracts/.gitkeep b/src/internal-contracts/.gitkeep new file mode 100644 index 0000000000..e69de29bb2