diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bdc7455..b1dbae1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @kununu/rosa-mota-backend +* @kununu/backend-libraries diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml deleted file mode 100644 index bed9754..0000000 --- a/.github/workflows/code_quality.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Qodana -on: - workflow_dispatch: - pull_request: - push: - branches: # Specify your branches here - - main # The 'main' branch - - 'releases/*' # The release branches - -jobs: - qodana: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - checks: write - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - name: 'Install composer dependencies' - uses: php-actions/composer@v6 - with: - php_version: '8.3' - version: 2 - ssh_key: ${{ secrets.CLONE_SSH_KEY }} - ssh_key_pub: ${{ secrets.CLONE_SSH_KEY_PUB }} - - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2025.2 - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000..de9023b --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,123 @@ +name: Continuous Integration + +on: + push: + branches: + - main + pull_request: + types: [ opened, synchronize, reopened ] + +env: + fail-fast: true + +jobs: + checks: + name: Code Checks + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + coverage: none + tools: composer-dependency-analyser, composer-normalize, composer-require-checker + + - name: Install Composer Dependencies + uses: ramsey/composer-install@v3 + with: + dependency-versions: "highest" + composer-options: "--prefer-stable --optimize-autoloader --no-progress --no-interaction" + + - name: Run Composer Dependency Analyser + run: composer-dependency-analyser + + - name: Run Composer Require Checker + run: composer-require-checker + + - name: Run Composer Normalize + run: composer-normalize --dry-run --indent-size 2 --indent-style space --no-check-lock --no-update-lock + + - name: Run code style sniffer + run: vendor/bin/phpcs --standard=phpcs.xml Kununu/ tests/ + + - name: Run PHP CS Fixer + run: vendor/bin/php-cs-fixer check --using-cache=no --config php-cs-fixer.php + + - name: Run PHPStan + run: vendor/bin/phpstan analyse + + - name: Run Rector + run: vendor/bin/rector process --ansi --dry-run --config rector.php Kununu/ tests/ + + build: + needs: checks + name: PHPUnit + runs-on: ubuntu-latest + strategy: + matrix: + dependencies: + - lowest + - highest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + coverage: pcov + + - name: Install Composer Dependencies + uses: ramsey/composer-install@v3 + with: + dependency-versions: ${{ matrix.dependencies }} + composer-options: "--prefer-stable --optimize-autoloader --no-progress --no-interaction" + + - name: Run PHPUnit + run: | + vendor/bin/phpunit --colors=always --testdox \ + --log-junit tests/.results/tests-junit.xml \ + --coverage-clover tests/.results/tests-clover.xml + + - name: Upload coverage files + uses: actions/upload-artifact@v4 + with: + name: ${{ github.job }}-8.4-${{ matrix.dependencies }}-coverage + include-hidden-files: true + path: tests/.results/ + + sonarcloud: + needs: build + name: SonarCloud Checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/download-artifact@v4 + with: + name: build-8.4-highest-coverage + path: tests/.results/ + + - name: Fix Code Coverage Paths + working-directory: tests/.results/ + run: | + sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' tests-clover.xml + sed -i 's@'$GITHUB_WORKSPACE'@/github/workspace/@g' tests-junit.xml + + - name: SonarCloud Scan + uses: SonarSource/sonarqube-scan-action@v7.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/cs_sniff.yml b/.github/workflows/cs_sniff.yml deleted file mode 100644 index 3de262e..0000000 --- a/.github/workflows/cs_sniff.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: CI -on: - pull_request: - -jobs: - cs: - name: cs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - coverage: none - - - name: Cache Composer dependencies - uses: actions/cache@v4 - with: - path: /tmp/composer-cache - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer - - - name: Install composer dependencies - uses: php-actions/composer@v6 - with: - php_version: '8.3' - version: 2 - args: --optimize-autoloader --no-progress --no-interaction - ssh_key: ${{ secrets.CLONE_SSH_KEY }} - ssh_key_pub: ${{ secrets.CLONE_SSH_KEY_PUB }} - - - name: Run code style sniffer - run: vendor/bin/phpcs --standard=phpcs.xml Kununu/ tests/ - - - name: Run PHP CS Fixer - run: vendor/bin/php-cs-fixer check --using-cache=no --config php-cs-fixer.php - - - name: Run PHPStan - run: vendor/bin/phpstan analyse - - - name: Run Rector - run: vendor/bin/rector process --ansi --dry-run --config rector.php Kununu/ tests/ diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml deleted file mode 100644 index 002c718..0000000 --- a/.github/workflows/testing.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CI -on: - pull_request: - -jobs: - tests: - name: tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - coverage: none - - - name: Cache Composer dependencies - uses: actions/cache@v4 - with: - path: /tmp/composer-cache - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer - - - name: Install composer dependencies - uses: php-actions/composer@v6 - with: - php_version: '8.3' - version: 2 - args: --optimize-autoloader --no-progress --no-interaction - ssh_key: ${{ secrets.CLONE_SSH_KEY }} - ssh_key_pub: ${{ secrets.CLONE_SSH_KEY_PUB }} - - - name: Run tests - run: vendor/bin/phpunit \ No newline at end of file diff --git a/README.md b/README.md index 51b8790..ae313ee 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Qodana](https://github.com/kununu/code-tools/actions/workflows/code_quality.yml/badge.svg)](https://github.com/kununu/code-tools/actions/workflows/code_quality.yml) - +![Continuous Integration](https://github.com/kununu/code-tools/actions/workflows/continuous-integration.yml/badge.svg) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=kununu_code-tools&metric=alert_status)](https://sonarcloud.io/dashboard?id=kununu_code-tools)

Brancher

diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php new file mode 100644 index 0000000..236115a --- /dev/null +++ b/composer-dependency-analyser.php @@ -0,0 +1,27 @@ +addPathToExclude(__DIR__ . '/tests') + ->ignoreErrorsOnPath(__DIR__ . '/Kununu/Sniffs/', [ErrorType::UNKNOWN_CLASS]) + ->ignoreErrorsOnExtensions( + [ + 'ext-mbstring', + 'ext-tokenizer', + ], + [ErrorType::SHADOW_DEPENDENCY] + ) + ->ignoreErrorsOnPackages( + [ + 'friendsofphp/php-cs-fixer', + 'phpstan/phpstan', + 'rector/rector', + 'squizlabs/php_codesniffer', + ], + [ErrorType::UNUSED_DEPENDENCY] + ); diff --git a/composer-require-checker.json b/composer-require-checker.json new file mode 100644 index 0000000..36cdc19 --- /dev/null +++ b/composer-require-checker.json @@ -0,0 +1,27 @@ +{ + "symbol-whitelist": [ + "mb_strlen", + "PHP_CodeSniffer\\Exceptions\\DeepExitException", + "PHP_CodeSniffer\\Files\\File", + "PHP_CodeSniffer\\Sniffs\\Sniff", + "PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\Files\\LineLengthSniff", + "T_CLASS", + "T_FUNCTION", + "T_CLOSE_CURLY_BRACKET", + "T_COMMA", + "T_NULLABLE", + "T_OPEN_TAG", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_READONLY", + "T_SEMICOLON", + "T_STRING", + "T_USE", + "T_VAR", + "T_VARIABLE", + "T_WHITESPACE", + "T_CONST", + "T_DECLARE" + ] +} diff --git a/composer.json b/composer.json index 41d4625..94c5298 100644 --- a/composer.json +++ b/composer.json @@ -1,64 +1,71 @@ { - "name": "kununu/code-tools", - "description": "Code Tools", - "type": "composer-plugin", - "license": "MIT", - "authors": [ - { - "name": "Team Rosa Mota", - "email": "rosamota-dev@kununu.com" - } - ], - "require": { - "php": ">=8.3", - "phpat/phpat": "^0.11.4", - "phpstan/phpstan": "^2.1", - "composer-plugin-api": "^2.0", - "composer/composer": "^2.8", - "friendsofphp/php-cs-fixer": "^3.75", - "rector/rector": "^2.0", - "squizlabs/php_codesniffer": "^3.10", - "symfony/yaml": "^6.4 || ^7.4" - }, - "require-dev": { - "phpunit/phpunit": "^11.5" - }, - "autoload": { - "psr-4": { - "Kununu\\": "Kununu/" - } - }, - "autoload-dev": { - "psr-4": { - "Tests\\": "tests/" - } + "name": "kununu/code-tools", + "description": "Code Tools", + "license": "MIT", + "type": "composer-plugin", + "authors": [ + { + "name": "Team Rosa Mota", + "email": "rosamota-dev@kununu.com" + } + ], + "require": { + "php": ">=8.4", + "composer-plugin-api": "^2.0", + "composer/composer": "^2.8", + "friendsofphp/php-cs-fixer": "^3.93", + "phpat/phpat": "^0.11.4", + "phpstan/phpstan": "^2.1", + "rector/rector": "^2.0", + "squizlabs/php_codesniffer": "^3.10", + "symfony/console": "^6.4 || ^7.4", + "symfony/process": "^6.4 || ^7.4", + "symfony/yaml": "^6.4 || ^7.4" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.50", + "phpunit/phpunit": "^11.5", + "shipmonk/composer-dependency-analyser": "^1.8" + }, + "autoload": { + "psr-4": { + "Kununu\\": "Kununu/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "bin": [ + "bin/code-tools", + "bin/php-in-k8s" + ], + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true }, - "bin": [ - "bin/code-tools", - "bin/php-in-k8s" + "process-timeout": 900, + "sort-packages": true + }, + "extra": { + "class": "Kununu\\CsFixer\\CsFixerPlugin" + }, + "scripts": { + "ci-checks": [ + "@cs-fixer-check", + "@cs-check", + "@stan", + "@rector", + "@test-unit" ], - "config": { - "sort-packages": true, - "process-timeout": 900 - }, - "extra": { - "class": "Kununu\\CsFixer\\CsFixerPlugin" - }, - "scripts": { - "test-unit": "phpunit", - "cs-fixer-check": "php-cs-fixer check --config=php-cs-fixer.php", - "cs-fixer-fix": "php-cs-fixer fix --config=php-cs-fixer.php", - "cs-check": "phpcs --standard=phpcs.xml Kununu/ tests/", - "cs-fix": "phpcbf --standard=phpcs.xml Kununu/ tests/", - "stan": "phpstan analyze", - "rector": "rector process --dry-run Kununu/ tests/ -vvv", - "rector-fix": "rector process Kununu/ tests/", - "ci-checks": [ - "@cs-fixer-check", - "@cs-check", - "@stan", - "@rector", - "@test-unit" - ] - } + "cs-check": "phpcs --standard=phpcs.xml Kununu/ tests/", + "cs-fix": "phpcbf --standard=phpcs.xml Kununu/ tests/", + "cs-fixer-check": "php-cs-fixer check --config=php-cs-fixer.php", + "cs-fixer-fix": "php-cs-fixer fix --config=php-cs-fixer.php", + "rector": "rector process --dry-run Kununu/ tests/ -vvv", + "rector-fix": "rector process Kununu/ tests/", + "stan": "phpstan analyze", + "test-unit": "phpunit" + } } diff --git a/qodana.yaml b/qodana.yaml deleted file mode 100644 index b78eaf2..0000000 --- a/qodana.yaml +++ /dev/null @@ -1,17 +0,0 @@ -version: "1.0" -linter: jetbrains/qodana-php:2025.2 -profile: - name: qodana.recommended -exclude: - - name: All - paths: - - rector.php - - name: PhpDisabledQualityToolComposerInspection - - name: DuplicatedCode - paths: - - Kununu/Sniffs -failureConditions: - severityThresholds: - critical: 0 - high: 0 - moderate: 0 diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..b17bf22 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,28 @@ +# ###################################################################################################################### +# Project configuration +# ###################################################################################################################### +sonar.projectKey=kununu_code-tools +sonar.organization=kununu +sonar.projectName=code-tools +sonar.projectVersion=1.0 +sonar.sourceEncoding=UTF-8 + +# ###################################################################################################################### +# Directories +# ###################################################################################################################### +sonar.sources=Kununu +sonar.tests=tests +sonar.php.coverage.reportPaths=tests/.results/tests-clover.xml +sonar.php.tests.reportPath=tests/.results/tests-junit.xml + +# ###################################################################################################################### +# Code coverage exclusions +# ###################################################################################################################### +sonar.coverage.exclusions=\ + tests/**,\ + +# ###################################################################################################################### +# Code duplication detections exclusions +# ###################################################################################################################### +sonar.cpd.exclusions=\ + tests/**,\ diff --git a/tests/Unit/Kununu/CsFixer/Command/CsFixerCommandTest.php b/tests/Unit/Kununu/CsFixer/Command/CsFixerCommandTest.php index 0c6ef34..f883037 100644 --- a/tests/Unit/Kununu/CsFixer/Command/CsFixerCommandTest.php +++ b/tests/Unit/Kununu/CsFixer/Command/CsFixerCommandTest.php @@ -22,7 +22,10 @@ public function testCsFixerCommand(string $before, string $after): void } $application = new Application(); - $application->add(new CsFixerCommand()); + $command = new CsFixerCommand(); + method_exists($application, 'addCommand') + ? $application->addCommand($command) + : $application->add($command); $command = $application->find('kununu:cs-fixer'); $tester = new CommandTester($command); diff --git a/tests/Unit/Kununu/CsFixer/Command/CsFixerGitHookCommandTest.php b/tests/Unit/Kununu/CsFixer/Command/CsFixerGitHookCommandTest.php index aa6f179..9a2b069 100644 --- a/tests/Unit/Kununu/CsFixer/Command/CsFixerGitHookCommandTest.php +++ b/tests/Unit/Kununu/CsFixer/Command/CsFixerGitHookCommandTest.php @@ -17,7 +17,10 @@ final class CsFixerGitHookCommandTest extends TestCase public function testFailsWhenNotAGitRepo(): void { $app = new Application(); - $app->add(new CsFixerGitHookCommand()); + $command = new CsFixerGitHookCommand(); + method_exists($app, 'addCommand') + ? $app->addCommand($command) + : $app->add($command); $command = $app->find('kununu:cs-fixer-git-hook'); $tester = new CommandTester($command); @@ -51,7 +54,10 @@ public function testInstallsHookSuccessfully(): void @chmod($binDir . '/php-cs-fixer', 0755); $app = new Application(); - $app->add(new CsFixerGitHookCommand()); + $command = new CsFixerGitHookCommand(); + method_exists($app, 'addCommand') + ? $app->addCommand($command) + : $app->add($command); $command = $app->find('kununu:cs-fixer-git-hook'); $tester = new CommandTester($command);