diff --git a/.github/workflows/backend-ci.yaml b/.github/workflows/backend-ci.yaml index 449acd1..c22c400 100644 --- a/.github/workflows/backend-ci.yaml +++ b/.github/workflows/backend-ci.yaml @@ -10,7 +10,7 @@ on: jobs: tests: name: Tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-latest" timeout-minutes: 10 strategy: @@ -20,26 +20,16 @@ jobs: - '8.3' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup PHP Action uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} coverage: none - extensions: pdo_sqlite, gd tools: cs2pr - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $TRAVIS_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} - - - uses: "ramsey/composer-install@v3" + - uses: ramsey/composer-install@v4 with: dependency-versions: "highest" composer-options: "--prefer-dist --no-progress --no-suggest" diff --git a/.github/workflows/pr-assign.yaml b/.github/workflows/pr-assign.yaml deleted file mode 100644 index ea9165c..0000000 --- a/.github/workflows/pr-assign.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Assign Pull Request to maintainers - -on: - pull_request_target: ~ - -jobs: - assign: - uses: ibexa/gh-workflows/.github/workflows/pr-assign.yml@main - secrets: - robot-token: ${{ secrets.EZROBOT_PAT }} diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 0000000..2ed9ab4 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1 @@ +sonar.cpd.exclusions=skeleton/** diff --git a/composer.json b/composer.json index 42bae6b..92cfbd9 100644 --- a/composer.json +++ b/composer.json @@ -13,10 +13,12 @@ }, "require-dev": { "composer/composer": "^2.1", - "friendsofphp/php-cs-fixer": "^3.0", - "ibexa/code-style": "~2.1.0", - "phpstan/phpstan": "^0.12.75", - "phpunit/phpunit": "^9.0" + "ibexa/code-style": "~2.3.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2", + "phpstan/phpstan-symfony": "^2.0", + "phpunit/phpunit": "^12" }, "bin": [ "bin/ibexa-bundle-generator" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cc55f95..aab4991 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,32 +1,2 @@ parameters: - ignoreErrors: - - - message: "#^Cannot cast array\\\\|bool\\|int\\|string to string\\.$#" - count: 1 - path: src/lib/Composer/ScriptHandler.php - - - - message: "#^Parameter \\#1 \\$targetDir of method Ibexa\\\\BundleGenerator\\\\Generator\\\\BundleGeneratorConfiguration\\:\\:setTargetDir\\(\\) expects string\\|null, string\\|false given\\.$#" - count: 1 - path: src/lib/Composer/ScriptHandler.php - - - - message: "#^Parameter \\#1 \\$path of function basename expects string, string\\|false given\\.$#" - count: 1 - path: src/lib/Generator/BundleGenerator.php - - - - message: "#^Parameter \\#1 \\$str of function strtr expects string, string\\|false given\\.$#" - count: 1 - path: src/lib/Generator/BundleGenerator.php - - - - message: "#^Parameter \\#1 \\$targetDir of method Ibexa\\\\BundleGenerator\\\\Generator\\\\BundleGenerator\\:\\:createSkeletonIterator\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: src/lib/Generator/BundleGenerator.php - - - - message: "#^Parameter \\#2 \\$targetDir of method Symfony\\\\Component\\\\Filesystem\\\\Filesystem\\:\\:mirror\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: src/lib/Generator/BundleGenerator.php - + ignoreErrors: [] diff --git a/skeleton/extension/.github/pull_request_template.md b/skeleton/extension/.github/pull_request_template.md deleted file mode 100644 index c5b2f37..0000000 --- a/skeleton/extension/.github/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -| Question | Answer | -|--------------------------|----------------------------------------| -| **Type** | feature/bug/improvement | -| **Target Ibexa version** | `v5.x` - please update `x` accordingly | -| **BC breaks** | yes/no | - - - -#### Checklist: - -- [ ] Provided PR description. -- [ ] Tested the solution manually. -- [ ] Provided automated test coverage. -- [ ] Checked that target branch is set correctly (main for features, the oldest supported for bugs). -- \ No newline at end of file diff --git a/skeleton/extension/.github/workflows/backend-ci.yaml b/skeleton/extension/.github/workflows/backend-ci.yaml index 9456cab..0a18287 100644 --- a/skeleton/extension/.github/workflows/backend-ci.yaml +++ b/skeleton/extension/.github/workflows/backend-ci.yaml @@ -16,7 +16,7 @@ jobs: php: - '8.3' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup PHP Action uses: shivammathur/setup-php@v2 @@ -26,7 +26,7 @@ jobs: extensions: 'pdo_sqlite, gd' tools: cs2pr - - uses: ramsey/composer-install@v3 + - uses: ramsey/composer-install@v4 with: dependency-versions: "highest" @@ -37,7 +37,7 @@ jobs: name: Deptrac runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Deptrac uses: smoench/deptrac-action@master @@ -53,7 +53,7 @@ jobs: - '8.3' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup PHP Action uses: shivammathur/setup-php@v2 @@ -63,7 +63,7 @@ jobs: extensions: pdo_sqlite, gd tools: cs2pr - - uses: ramsey/composer-install@v3 + - uses: ramsey/composer-install@v4 with: dependency-versions: "highest" composer-options: "--prefer-dist --no-progress --no-suggest" diff --git a/skeleton/extension/.github/workflows/frontend-ci.yaml b/skeleton/extension/.github/workflows/frontend-ci.yaml index a064636..e703428 100644 --- a/skeleton/extension/.github/workflows/frontend-ci.yaml +++ b/skeleton/extension/.github/workflows/frontend-ci.yaml @@ -20,8 +20,8 @@ jobs: timeout-minutes: 5 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-node@v5 with: node-version: '22' - run: yarn install diff --git a/skeleton/extension/composer.json b/skeleton/extension/composer.json index 601aad2..c6eb9cb 100644 --- a/skeleton/extension/composer.json +++ b/skeleton/extension/composer.json @@ -8,17 +8,17 @@ "require": { "php": ">=8.3", "ibexa/core": "~5.0.x-dev", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.3", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.3", - "symfony/yaml": "^7.3" + "symfony/config": "^7.4", + "symfony/dependency-injection": "^7.4", + "symfony/event-dispatcher": "^7.4", + "symfony/http-foundation": "^7.4", + "symfony/http-kernel": "^7.4", + "symfony/yaml": "^7.4" }, "require-dev": { "dama/doctrine-test-bundle": "^8.2", "deptrac/deptrac": "^3.0", - "ibexa/code-style": "~2.1.0", + "ibexa/code-style": "~2.3.0", "ibexa/phpstan": "~5.0.x-dev", "ibexa/rector": "~5.0.x-dev", "ibexa/test-core": "~5.0.x-dev", @@ -27,7 +27,7 @@ "phpstan/phpstan-strict-rules": "^2", "phpstan/phpstan-symfony": "^2.0", "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^7.3" + "symfony/phpunit-bridge": "^7.4" }, "autoload": { "psr-4": { diff --git a/skeleton/ibexa-ee/.github/pull_request_template.md b/skeleton/ibexa-ee/.github/pull_request_template.md deleted file mode 100644 index c5b2f37..0000000 --- a/skeleton/ibexa-ee/.github/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -| Question | Answer | -|--------------------------|----------------------------------------| -| **Type** | feature/bug/improvement | -| **Target Ibexa version** | `v5.x` - please update `x` accordingly | -| **BC breaks** | yes/no | - - - -#### Checklist: - -- [ ] Provided PR description. -- [ ] Tested the solution manually. -- [ ] Provided automated test coverage. -- [ ] Checked that target branch is set correctly (main for features, the oldest supported for bugs). -- \ No newline at end of file diff --git a/skeleton/ibexa-ee/.github/workflows/backend-ci.yaml b/skeleton/ibexa-ee/.github/workflows/backend-ci.yaml index 57f41cc..03b4be2 100644 --- a/skeleton/ibexa-ee/.github/workflows/backend-ci.yaml +++ b/skeleton/ibexa-ee/.github/workflows/backend-ci.yaml @@ -3,7 +3,6 @@ name: Backend build on: push: branches: - - main - '[0-9]+.[0-9]+' pull_request: ~ @@ -16,28 +15,14 @@ jobs: php: - '8.3' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 + - uses: ibexa/gh-workflows/actions/composer-install@main with: - php-version: ${{ matrix.php }} - coverage: none - extensions: 'pdo_sqlite, gd' - tools: cs2pr - - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $TRAVIS_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} - - - uses: ramsey/composer-install@v3 - with: - dependency-versions: "highest" + 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 code style check run: composer run-script check-cs -- --format=checkstyle | cs2pr @@ -46,7 +31,7 @@ jobs: name: Deptrac runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Deptrac uses: smoench/deptrac-action@master @@ -60,31 +45,17 @@ jobs: matrix: php: - '8.3' + - '8.4' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 + - uses: ibexa/gh-workflows/actions/composer-install@main with: - php-version: ${{ matrix.php }} - coverage: none - extensions: pdo_sqlite, gd - tools: cs2pr - - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $TRAVIS_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} - - - uses: ramsey/composer-install@v3 - with: - dependency-versions: "highest" - composer-options: "--prefer-dist --no-progress --no-suggest" + 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: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" @@ -100,7 +71,7 @@ jobs: needs: tests services: postgres: - image: postgres:10 + image: ${{ matrix.image }} ports: - 5432 env: @@ -120,35 +91,25 @@ jobs: matrix: php: - '8.3' + - '8.4' + image: + - 'postgres:14' + - 'postgres:18' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 + - uses: ibexa/gh-workflows/actions/composer-install@main with: - php-version: ${{ matrix.php }} - coverage: none - extensions: pdo_pgsql, gd - tools: cs2pr - - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $TRAVIS_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} - - - uses: ramsey/composer-install@v3 - with: - dependency-versions: "highest" + 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: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - name: Run integration test suite vs Postgresql + - name: Run integration test suite vs PostgreSQL run: composer run-script --timeout=600 test-integration env: DATABASE_URL: "pgsql://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/testdb?server_version=10" @@ -158,7 +119,7 @@ jobs: needs: tests services: mysql: - image: ghcr.io/ibexa/core/mysql + image: ${{ matrix.image }} ports: - 3306/tcp env: @@ -173,37 +134,27 @@ jobs: --health-retries=5 --tmpfs=/var/lib/mysql runs-on: "ubuntu-24.04" - timeout-minutes: 10 + timeout-minutes: 60 strategy: fail-fast: false matrix: php: - '8.3' + - '8.4' + image: + - 'mysql:8.0' + - 'mysql:8.4' steps: - - uses: actions/checkout@v4 - - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: none - extensions: pdo_mysql, gd, redis - tools: cs2pr - - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $TRAVIS_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} + - uses: actions/checkout@v6 - - uses: ramsey/composer-install@v3 + - uses: ibexa/gh-workflows/actions/composer-install@main with: - dependency-versions: "highest" + 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: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" diff --git a/skeleton/ibexa-ee/.github/workflows/browser-tests.yaml b/skeleton/ibexa-ee/.github/workflows/browser-tests.yaml index b2caa0c..7213d9c 100644 --- a/skeleton/ibexa-ee/.github/workflows/browser-tests.yaml +++ b/skeleton/ibexa-ee/.github/workflows/browser-tests.yaml @@ -17,5 +17,7 @@ jobs: secrets: SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - TRAVIS_GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_TOKEN }} + AUTOMATION_CLIENT_ID: ${{ secrets.AUTOMATION_CLIENT_ID }} + AUTOMATION_CLIENT_INSTALLATION: ${{ secrets.AUTOMATION_CLIENT_INSTALLATION }} + AUTOMATION_CLIENT_SECRET: ${{ secrets.AUTOMATION_CLIENT_SECRET }} SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/skeleton/ibexa-ee/composer.json b/skeleton/ibexa-ee/composer.json index 85fd8ea..8632018 100644 --- a/skeleton/ibexa-ee/composer.json +++ b/skeleton/ibexa-ee/composer.json @@ -16,18 +16,18 @@ "require": { "php": ">=8.3", "ibexa/core": "~5.0.x-dev", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.3", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.3", - "symfony/yaml": "^7.3" + "symfony/config": "^7.4", + "symfony/dependency-injection": "^7.4", + "symfony/event-dispatcher": "^7.4", + "symfony/http-foundation": "^7.4", + "symfony/http-kernel": "^7.4", + "symfony/yaml": "^7.4" }, "require-dev": { "dama/doctrine-test-bundle": "^8.2", "deptrac/deptrac": "^3.0", "ibexa/behat": "~5.0.x-dev", - "ibexa/code-style": "~2.1.0", + "ibexa/code-style": "~2.3.0", "ibexa/phpstan": "~5.0.x-dev", "ibexa/rector": "~5.0.x-dev", "ibexa/test-core": "~5.0.x-dev", @@ -36,7 +36,7 @@ "phpstan/phpstan-strict-rules": "^2", "phpstan/phpstan-symfony": "^2.0", "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^7.3" + "symfony/phpunit-bridge": "^7.4" }, "autoload": { "psr-4": { diff --git a/skeleton/ibexa-ee/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php b/skeleton/ibexa-ee/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php index a2042d8..94ad7d0 100644 --- a/skeleton/ibexa-ee/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php +++ b/skeleton/ibexa-ee/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php @@ -18,8 +18,10 @@ final class __VENDOR_NAMESPACE____BUNDLE_NAME__Extension extends Extension implements PrependExtensionInterface { - public function load(array $configs, ContainerBuilder $container): void - { + public function load( + array $configs, + ContainerBuilder $container + ): void { $loader = new YamlFileLoader( $container, new FileLocator(__DIR__ . '/../Resources/config') diff --git a/skeleton/ibexa-ee/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php b/skeleton/ibexa-ee/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php index ab47642..748450c 100644 --- a/skeleton/ibexa-ee/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php +++ b/skeleton/ibexa-ee/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php @@ -10,6 +10,4 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; -final class __VENDOR_NAMESPACE____BUNDLE_NAME__Bundle extends Bundle -{ -} +final class __VENDOR_NAMESPACE____BUNDLE_NAME__Bundle extends Bundle {} diff --git a/skeleton/ibexa-ee/tests/integration/bootstrap.php b/skeleton/ibexa-ee/tests/integration/bootstrap.php index ece3843..1ebba3b 100644 --- a/skeleton/ibexa-ee/tests/integration/bootstrap.php +++ b/skeleton/ibexa-ee/tests/integration/bootstrap.php @@ -6,9 +6,11 @@ */ declare(strict_types=1); +use Ibexa\Contracts\Core\Search\VersatileHandler; use Ibexa\Contracts\Core\Test\Persistence\Fixture\FixtureImporter; use Ibexa\Tests\Core\Repository\LegacySchemaImporter; use Ibexa\Tests\Integration\__BUNDLE_NAME__\TestKernel; +use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArrayInput; @@ -44,7 +46,7 @@ '--quiet' => true, ])); -/** @var \Psr\Container\ContainerInterface $testContainer */ +/** @var ContainerInterface $testContainer */ $testContainer = $kernel->getContainer()->get('test.service_container'); $schemaImporter = $testContainer->get(LegacySchemaImporter::class); @@ -57,7 +59,7 @@ $fixtureImporter->import($fixture); } -/** @var \Ibexa\Contracts\Core\Search\VersatileHandler $handler */ +/** @var VersatileHandler $handler */ $handler = $testContainer->get('ibexa.spi.search'); $handler->purgeIndex(); diff --git a/skeleton/ibexa-oss/.github/pull_request_template.md b/skeleton/ibexa-oss/.github/pull_request_template.md deleted file mode 100644 index c5b2f37..0000000 --- a/skeleton/ibexa-oss/.github/pull_request_template.md +++ /dev/null @@ -1,15 +0,0 @@ -| Question | Answer | -|--------------------------|----------------------------------------| -| **Type** | feature/bug/improvement | -| **Target Ibexa version** | `v5.x` - please update `x` accordingly | -| **BC breaks** | yes/no | - - - -#### Checklist: - -- [ ] Provided PR description. -- [ ] Tested the solution manually. -- [ ] Provided automated test coverage. -- [ ] Checked that target branch is set correctly (main for features, the oldest supported for bugs). -- \ No newline at end of file diff --git a/skeleton/ibexa-oss/.github/workflows/backend-ci.yaml b/skeleton/ibexa-oss/.github/workflows/backend-ci.yaml index b352584..8b9ce94 100644 --- a/skeleton/ibexa-oss/.github/workflows/backend-ci.yaml +++ b/skeleton/ibexa-oss/.github/workflows/backend-ci.yaml @@ -3,7 +3,6 @@ name: Backend build on: push: branches: - - main - '[0-9]+.[0-9]+' pull_request: ~ @@ -16,19 +15,12 @@ jobs: php: - '8.3' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 + - uses: ibexa/gh-workflows/actions/composer-install@main with: - php-version: ${{ matrix.php }} - coverage: none - extensions: 'pdo_sqlite, gd' - tools: cs2pr - - - uses: ramsey/composer-install@v3 - with: - dependency-versions: "highest" + gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} - name: Run code style check run: composer run-script check-cs -- --format=checkstyle | cs2pr @@ -37,7 +29,7 @@ jobs: name: Deptrac runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Deptrac uses: smoench/deptrac-action@master @@ -51,22 +43,15 @@ jobs: matrix: php: - '8.3' + - '8.4' steps: - - uses: actions/checkout@v4 - - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: none - extensions: pdo_sqlite, gd - tools: cs2pr + - uses: actions/checkout@v6 - - uses: "ramsey/composer-install@v1" + - uses: ibexa/gh-workflows/actions/composer-install@main with: - dependency-versions: "highest" - composer-options: "--prefer-dist --no-progress --no-suggest" + gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} - name: Setup problem matchers for PHPUnit run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" diff --git a/skeleton/ibexa-oss/composer.json b/skeleton/ibexa-oss/composer.json index 4c96c54..565f4cb 100644 --- a/skeleton/ibexa-oss/composer.json +++ b/skeleton/ibexa-oss/composer.json @@ -10,18 +10,18 @@ "require": { "php": ">=8.3", "ibexa/core": "~5.0.x-dev", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.3", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.3", - "symfony/yaml": "^7.3" + "symfony/config": "^7.4", + "symfony/dependency-injection": "^7.4", + "symfony/event-dispatcher": "^7.4", + "symfony/http-foundation": "^7.4", + "symfony/http-kernel": "^7.4", + "symfony/yaml": "^7.4" }, "require-dev": { "dama/doctrine-test-bundle": "^8.2", "deptrac/deptrac": "^3.0", "ibexa/behat": "~5.0.x-dev", - "ibexa/code-style": "~2.1.0", + "ibexa/code-style": "~2.3.0", "ibexa/phpstan": "~5.0.x-dev", "ibexa/rector": "~5.0.x-dev", "ibexa/test-core": "~5.0.x-dev", @@ -30,7 +30,7 @@ "phpstan/phpstan-strict-rules": "^2", "phpstan/phpstan-symfony": "^2.0", "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^7.3" + "symfony/phpunit-bridge": "^7.4" }, "autoload": { "psr-4": { diff --git a/skeleton/ibexa-oss/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php b/skeleton/ibexa-oss/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php index a2042d8..94ad7d0 100644 --- a/skeleton/ibexa-oss/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php +++ b/skeleton/ibexa-oss/src/bundle/DependencyInjection/__VENDOR_NAMESPACE____BUNDLE_NAME__Extension.php @@ -18,8 +18,10 @@ final class __VENDOR_NAMESPACE____BUNDLE_NAME__Extension extends Extension implements PrependExtensionInterface { - public function load(array $configs, ContainerBuilder $container): void - { + public function load( + array $configs, + ContainerBuilder $container + ): void { $loader = new YamlFileLoader( $container, new FileLocator(__DIR__ . '/../Resources/config') diff --git a/skeleton/ibexa-oss/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php b/skeleton/ibexa-oss/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php index ab47642..748450c 100644 --- a/skeleton/ibexa-oss/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php +++ b/skeleton/ibexa-oss/src/bundle/__VENDOR_NAMESPACE____BUNDLE_NAME__Bundle.php @@ -10,6 +10,4 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; -final class __VENDOR_NAMESPACE____BUNDLE_NAME__Bundle extends Bundle -{ -} +final class __VENDOR_NAMESPACE____BUNDLE_NAME__Bundle extends Bundle {} diff --git a/skeleton/ibexa-oss/tests/integration/bootstrap.php b/skeleton/ibexa-oss/tests/integration/bootstrap.php index ece3843..1ebba3b 100644 --- a/skeleton/ibexa-oss/tests/integration/bootstrap.php +++ b/skeleton/ibexa-oss/tests/integration/bootstrap.php @@ -6,9 +6,11 @@ */ declare(strict_types=1); +use Ibexa\Contracts\Core\Search\VersatileHandler; use Ibexa\Contracts\Core\Test\Persistence\Fixture\FixtureImporter; use Ibexa\Tests\Core\Repository\LegacySchemaImporter; use Ibexa\Tests\Integration\__BUNDLE_NAME__\TestKernel; +use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArrayInput; @@ -44,7 +46,7 @@ '--quiet' => true, ])); -/** @var \Psr\Container\ContainerInterface $testContainer */ +/** @var ContainerInterface $testContainer */ $testContainer = $kernel->getContainer()->get('test.service_container'); $schemaImporter = $testContainer->get(LegacySchemaImporter::class); @@ -57,7 +59,7 @@ $fixtureImporter->import($fixture); } -/** @var \Ibexa\Contracts\Core\Search\VersatileHandler $handler */ +/** @var VersatileHandler $handler */ $handler = $testContainer->get('ibexa.spi.search'); $handler->purgeIndex(); diff --git a/src/lib/Command/GenerateBundleCommand.php b/src/lib/Command/GenerateBundleCommand.php index 27ae14c..487e6f9 100644 --- a/src/lib/Command/GenerateBundleCommand.php +++ b/src/lib/Command/GenerateBundleCommand.php @@ -11,6 +11,8 @@ use Ibexa\BundleGenerator\Generator\BundleGenerator; use Ibexa\BundleGenerator\Generator\BundleGeneratorConfiguration; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -65,11 +67,15 @@ protected function configure(): void ); } - protected function interact(InputInterface $input, OutputInterface $output): void - { + protected function interact( + InputInterface $input, + OutputInterface $output + ): void { + /** @var QuestionHelper $helper */ $helper = $this->getHelper('question'); - if (!$input->getArgument('package-name')) { + $packageName = $this->getNullableStringArgument($input, 'package-name'); + if (empty($packageName)) { $defaultPackageName = BundleGenerator::getDefaultPackageName(); $question = new Question( @@ -77,10 +83,14 @@ protected function interact(InputInterface $input, OutputInterface $output): voi $defaultPackageName ); - $input->setArgument('package-name', $helper->ask($input, $output, $question)); + $input->setArgument('package-name', $this->getNullableStringAnswer( + $helper->ask($input, $output, $question), + 'package-name' + )); } - if (!$input->getOption('vendor-name')) { + $vendorName = $this->getNullableStringOption($input, 'vendor-name'); + if (empty($vendorName)) { $defaultVendorName = BundleGenerator::getDefaultVendorName(); $question = new Question( @@ -88,49 +98,89 @@ protected function interact(InputInterface $input, OutputInterface $output): voi $defaultVendorName ); - $input->setOption('vendor-name', $helper->ask($input, $output, $question)); + $vendorName = $this->getNullableStringAnswer( + $helper->ask($input, $output, $question), + 'vendor-name' + ); + $input->setOption('vendor-name', $vendorName); } - if (!$input->getOption('vendor-namespace')) { - $defaultVendorNamespace = BundleGenerator::getDefaultVendorNamespace( - $input->getOption('vendor-name') - ); + if ($this->getNullableStringOption($input, 'vendor-namespace') === null) { + $defaultVendorNamespace = BundleGenerator::getDefaultVendorNamespace($vendorName); $question = new Question( 'Bundle vendor namespace e.g Ibexa [' . ($defaultVendorNamespace ?? 'n/a') . ']: ', $defaultVendorNamespace ); - $input->setOption('vendor-namespace', $helper->ask($input, $output, $question)); + $input->setOption('vendor-namespace', $this->getNullableStringAnswer( + $helper->ask($input, $output, $question), + 'vendor-namespace' + )); } - if (!$input->getOption('bundle-name')) { - $defaultBundleName = BundleGenerator::getDefaultBundleName( - $input->getArgument('package-name') - ); + if ($this->getNullableStringOption($input, 'bundle-name') === null) { + $defaultBundleName = BundleGenerator::getDefaultBundleName($packageName); $question = new Question( "Bundle name without 'Bundle' suffix e.g IbexaPageBuilder [" . ($defaultBundleName ?? 'n/a') . ']: ', $defaultBundleName ); - $input->setOption('bundle-name', $helper->ask($input, $output, $question)); + $input->setOption('bundle-name', $this->getNullableStringAnswer( + $helper->ask($input, $output, $question), + 'bundle-name' + )); } } - protected function execute(InputInterface $input, OutputInterface $output): int - { + protected function execute( + InputInterface $input, + OutputInterface $output + ): int { $config = new BundleGeneratorConfiguration(); - $config->setTargetDir($input->getArgument('target-dir')); - $config->setPackageName($input->getArgument('package-name')); - $config->setSkeletonName($input->getOption('skeleton-name')); - $config->setVendorName($input->getOption('vendor-name')); - $config->setVendorNamespace($input->getOption('vendor-namespace')); - $config->setBundleName($input->getOption('bundle-name')); + $config->setTargetDir($this->getNullableStringArgument($input, 'target-dir')); + $config->setPackageName($this->getNullableStringArgument($input, 'package-name')); + $config->setSkeletonName($this->getNullableStringOption($input, 'skeleton-name')); + $config->setVendorName($this->getNullableStringOption($input, 'vendor-name')); + $config->setVendorNamespace($this->getNullableStringOption($input, 'vendor-namespace')); + $config->setBundleName($this->getNullableStringOption($input, 'bundle-name')); $generator = new BundleGenerator(); $generator->generate($config); return self::SUCCESS; } + + private function getNullableStringArgument( + InputInterface $input, + string $name + ): ?string { + return $this->getNullableStringValue($input->getArgument($name), sprintf('Argument "%s"', $name)); + } + + private function getNullableStringOption( + InputInterface $input, + string $name + ): ?string { + return $this->getNullableStringValue($input->getOption($name), sprintf('Option "%s"', $name)); + } + + private function getNullableStringAnswer( + mixed $value, + string $name + ): ?string { + return $this->getNullableStringValue($value, sprintf('Question "%s"', $name)); + } + + private function getNullableStringValue( + mixed $value, + string $source + ): ?string { + if (is_string($value) || $value === null) { + return $value; + } + + throw new InvalidArgumentException(sprintf('%s must be a string or null.', $source)); + } } diff --git a/src/lib/Composer/ScriptHandler.php b/src/lib/Composer/ScriptHandler.php index d6c7c95..40a889b 100644 --- a/src/lib/Composer/ScriptHandler.php +++ b/src/lib/Composer/ScriptHandler.php @@ -12,6 +12,7 @@ use Composer\Script\Event; use Ibexa\BundleGenerator\Generator\BundleGenerator; use Ibexa\BundleGenerator\Generator\BundleGeneratorConfiguration; +use InvalidArgumentException; final class ScriptHandler { @@ -25,7 +26,7 @@ public static function generate(Event $event): void $config->setVendorName(self::askForVendorName($io)); $config->setVendorNamespace(self::askForVendorNamespace($io, $config)); $config->setBundleName(self::askForBundleName($io, $config)); - $config->setTargetDir(realpath('.')); + $config->setTargetDir(self::getCurrentDirectory()); $generator = new BundleGenerator(); $generator->generate($config); @@ -35,53 +36,73 @@ private static function askForPackageName(IOInterface $io): string { $defaultPackageName = BundleGenerator::getDefaultPackageName(); - return $io->ask( + return self::getStringValue($io->ask( "Package name e.g ibexa-page-builder [$defaultPackageName]: ", $defaultPackageName - ); + ), 'Package name'); } private static function askForVendorName(IOInterface $io): string { $defaultVendorName = BundleGenerator::getDefaultVendorName(); - return $io->ask( + return self::getStringValue($io->ask( 'Package vendor name e.g ibexa [' . ($defaultVendorName ?? 'n/a') . ']: ', $defaultVendorName - ); + ), 'Vendor name'); } - private static function askForVendorNamespace(IOInterface $io, BundleGeneratorConfiguration $config): string - { + private static function askForVendorNamespace( + IOInterface $io, + BundleGeneratorConfiguration $config + ): string { $defaultVendorNamespace = BundleGenerator::getDefaultVendorNamespace($config->getVendorName()); - return $io->ask( + return self::getStringValue($io->ask( 'Bundle vendor namespace e.g Ibexa [' . ($defaultVendorNamespace ?? 'n/a') . ']: ', $defaultVendorNamespace - ); + ), 'Vendor namespace'); } - private static function askForBundleName(IOInterface $io, BundleGeneratorConfiguration $config): string - { + private static function askForBundleName( + IOInterface $io, + BundleGeneratorConfiguration $config + ): string { $defaultBundleName = BundleGenerator::getDefaultBundleName($config->getPackageName()); - return $io->ask( + return self::getStringValue($io->ask( "Bundle name without 'Bundle' suffix e.g IbexaPageBuilder [" . ($defaultBundleName ?? 'n/a') . ']: ', $defaultBundleName - ); + ), 'Bundle name'); } private static function askForSkeletonName(IOInterface $io): string { $skeletons = BundleGenerator::getAvailableSkeletons(); if (count($skeletons) === 1) { - return reset($skeletons); + return self::getStringValue(reset($skeletons), 'Skeleton'); } - return (string) $io->select( + return self::getStringValue($io->select( 'Skeleton', array_combine($skeletons, $skeletons), BundleGenerator::DEFAULT_SKELETON_NAME - ); + ), 'Skeleton'); + } + + private static function getStringValue( + mixed $value, + string $source + ): string { + if (is_string($value)) { + return $value; + } + + throw new InvalidArgumentException(sprintf('%s must be a string.', $source)); + } + + private static function getCurrentDirectory(): string + { + return self::getStringValue(realpath('.'), 'Current directory'); } } diff --git a/src/lib/Generator/BundleGenerator.php b/src/lib/Generator/BundleGenerator.php index 96ac91b..3385b7a 100644 --- a/src/lib/Generator/BundleGenerator.php +++ b/src/lib/Generator/BundleGenerator.php @@ -9,6 +9,7 @@ namespace Ibexa\BundleGenerator\Generator; use FilesystemIterator; +use InvalidArgumentException; use Iterator; use RecursiveCallbackFilterIterator; use RecursiveDirectoryIterator; @@ -18,14 +19,18 @@ final class BundleGenerator { - public const DEFAULT_SKELETON_NAME = 'ibexa-ee'; + public const string DEFAULT_SKELETON_NAME = 'ibexa-ee'; - private const SKELETON_DIRECTORY = __DIR__ . '/../../../skeleton/'; + private const string SKELETON_DIRECTORY = __DIR__ . '/../../../skeleton/'; public function generate(BundleGeneratorConfiguration $config): void { $fs = new Filesystem(); - $fs->mirror($this->getSkeletonDirectory($config), $config->getTargetDir()); + $targetDir = $config->getTargetDir(); + if (null === $targetDir) { + throw new InvalidArgumentException('Target directory cannot be null'); + } + $fs->mirror($this->getSkeletonDirectory($config), $targetDir); $replacements = [ '__PACKAGE_NAME__' => $config->getPackageName(), @@ -35,11 +40,11 @@ public function generate(BundleGeneratorConfiguration $config): void '__CONFIG_ROOT__' => str_replace('-', '_', $config->getVendorName() . '_' . $config->getPackageName()), ]; - $iterator = $this->createSkeletonIterator($config->getTargetDir()); + $iterator = $this->createSkeletonIterator($targetDir); foreach ($iterator as $file) { if (!$file->isDir()) { - $content = strtr(file_get_contents($file->getPathname()), $replacements); + $content = strtr($this->getFileContents($file), $replacements); $fs->dumpFile($file->getPathname(), $content); } } @@ -50,7 +55,7 @@ public function generate(BundleGeneratorConfiguration $config): void } /** - * @return iterator + * @return Iterator */ private function createSkeletonIterator(string $targetDir): Iterator { @@ -83,7 +88,7 @@ private function getSkeletonDirectory(BundleGeneratorConfiguration $config): str public static function getDefaultPackageName(): string { - return basename(realpath('.')); + return basename(self::getCurrentDirectory()); } public static function getDefaultVendorName(): ?string @@ -123,7 +128,7 @@ public static function getAvailableSkeletons(): array $skeletons = []; $iterator = new FilesystemIterator(self::SKELETON_DIRECTORY); - /** @var \SplFileInfo $fileInfo */ + /** @var SplFileInfo $fileInfo */ foreach ($iterator as $fileInfo) { if (!$fileInfo->isDir()) { continue; @@ -134,4 +139,27 @@ public static function getAvailableSkeletons(): array return $skeletons; } + + private static function getCurrentDirectory(): string + { + $realPath = realpath('.'); + if (false === $realPath) { + throw new InvalidArgumentException('Unable to get current directory real path'); + } + + return $realPath; + } + + private function getFileContents(SplFileInfo $file): string + { + $pathname = $file->getPathname(); + + $contents = file_get_contents($pathname); + + if ($contents === false) { + throw new InvalidArgumentException("Unable to get contents of the file '$pathname'"); + } + + return $contents; + } } diff --git a/src/lib/Generator/BundleGeneratorConfiguration.php b/src/lib/Generator/BundleGeneratorConfiguration.php index 0064e71..dba8004 100644 --- a/src/lib/Generator/BundleGeneratorConfiguration.php +++ b/src/lib/Generator/BundleGeneratorConfiguration.php @@ -10,23 +10,17 @@ final class BundleGeneratorConfiguration { - /** @var string|null */ - private $skeletonName; + private ?string $skeletonName; - /** @var string|null */ - private $packageName; + private ?string $packageName; - /** @var string|null */ - private $vendorName; + private ?string $vendorName; - /** @var string|null */ - private $vendorNamespace; + private ?string $vendorNamespace; - /** @var string|null */ - private $bundleName; + private ?string $bundleName; - /** @var string|null */ - private $targetDir; + private ?string $targetDir; public function getSkeletonName(): ?string {