diff --git a/.github/workflows/test-autoreview.yml b/.github/workflows/test-autoreview.yml index dfe4892bdebe..21f885445b63 100644 --- a/.github/workflows/test-autoreview.yml +++ b/.github/workflows/test-autoreview.yml @@ -29,3 +29,79 @@ jobs: php-version: '8.1' job-id: auto-review-tests group-name: AutoReview + + composer-normalize-tests: + name: Check normalized composer.json + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + + - name: Install dependencies + run: composer update + + - name: Run on root composer.json + id: normalize-root-composer + if: ${{ always() }} + run: | + echo "ROOT_COMPOSER_RESULT<> $GITHUB_OUTPUT + echo "$(composer normalize)" >> $GITHUB_OUTPUT + echo "RCR" >> $GITHUB_OUTPUT + + - name: Run on framework composer.json + id: normalize-framework-composer + if: ${{ always() }} + working-directory: admin/framework + run: | + echo "FRAMEWORK_COMPOSER_RESULT<> $GITHUB_OUTPUT + echo "$(composer normalize)" >> $GITHUB_OUTPUT + echo "FCR" >> $GITHUB_OUTPUT + + - name: Run on starter composer.json + id: normalize-starter-composer + if: ${{ always() }} + working-directory: admin/starter + run: | + echo "STARTER_COMPOSER_RESULT<> $GITHUB_OUTPUT + echo "$(composer normalize)" >> $GITHUB_OUTPUT + echo "SCR" >> $GITHUB_OUTPUT + + - name: Analyse normalization results + run: | + if [[ '${{ steps.normalize-root-composer.conclusion }}' == 'failure' ]]; then + echo 'Normalization of root composer.json encountered a problem.'; + echo 'Please run it locally: `composer normalize`'; + exit 1; + fi + + if [[ ${{ contains(steps.normalize-root-composer.outputs.ROOT_COMPOSER_RESULT, 'Successfully normalized') }} == true ]]; then + echo 'Root composer.json is not yet normalized.'; + exit 1; + fi + + if [[ '${{ steps.normalize-framework-composer.conclusion }}' == 'failure' ]]; then + echo 'Normalization of framework composer.json encountered a problem.'; + echo 'Please run it locally: `composer normalize -d admin/framework`'; + exit 1; + fi + + if [[ ${{ contains(steps.normalize-framework-composer.outputs.FRAMEWORK_COMPOSER_RESULT, 'Successfully normalized') }} == true ]]; then + echo 'Framework composer.json is not yet normalized.'; + exit 1; + fi + + if [[ '${{ steps.normalize-starter-composer.conclusion }}' == 'failure' ]]; then + echo 'Normalization of starter composer.json encountered a problem.'; + echo 'Please run it locally: `composer normalize -d admin/starter`'; + exit 1; + fi + + if [[ ${{ contains(steps.normalize-starter-composer.outputs.STARTER_COMPOSER_RESULT, 'Successfully normalized') }} == true ]]; then + echo 'Starter composer.json is not yet normalized.'; + exit 1; + fi diff --git a/admin/framework/composer.json b/admin/framework/composer.json index 905e123cd89a..f93daa275b1d 100644 --- a/admin/framework/composer.json +++ b/admin/framework/composer.json @@ -1,9 +1,14 @@ { "name": "codeigniter4/framework", - "type": "project", "description": "The CodeIgniter framework v4", - "homepage": "https://codeigniter.com", "license": "MIT", + "type": "project", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + }, "require": { "php": "^7.4 || ^8.0", "ext-intl": "*", @@ -13,10 +18,10 @@ "psr/log": "^1.1" }, "require-dev": { - "kint-php/kint": "^5.0.4", "codeigniter/coding-standard": "^1.5", "fakerphp/faker": "^1.9", "friendsofphp/php-cs-fixer": "3.13.0", + "kint-php/kint": "^5.0.4", "mikey179/vfsstream": "^1.6", "nexusphp/cs-config": "^3.6", "phpunit/phpunit": "^9.1", @@ -24,28 +29,23 @@ }, "suggest": { "ext-curl": "If you use CURLRequest class", - "ext-imagick": "If you use Image class ImageMagickHandler", - "ext-gd": "If you use Image class GDHandler", + "ext-dom": "If you use TestResponse", "ext-exif": "If you run Image class tests", - "ext-simplexml": "If you format XML", + "ext-fileinfo": "Improves mime type detection for files", + "ext-gd": "If you use Image class GDHandler", + "ext-imagick": "If you use Image class ImageMagickHandler", + "ext-libxml": "If you use TestResponse", + "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", + "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", "ext-mysqli": "If you use MySQL", "ext-oci8": "If you use Oracle Database", "ext-pgsql": "If you use PostgreSQL", - "ext-sqlsrv": "If you use SQL Server", - "ext-sqlite3": "If you use SQLite3", - "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", - "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", + "ext-readline": "Improves CLI::input() usability", "ext-redis": "If you use Cache class RedisHandler", - "ext-dom": "If you use TestResponse", - "ext-libxml": "If you use TestResponse", - "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()", - "ext-fileinfo": "Improves mime type detection for files", - "ext-readline": "Improves CLI::input() usability" - }, - "config": { - "optimize-autoloader": true, - "preferred-install": "dist", - "sort-packages": true + "ext-simplexml": "If you format XML", + "ext-sqlite3": "If you use SQLite3", + "ext-sqlsrv": "If you use SQL Server", + "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()" }, "autoload": { "psr-4": { @@ -55,12 +55,12 @@ "**/Database/Migrations/**" ] }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + }, "scripts": { "test": "phpunit" - }, - "support": { - "forum": "https://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" } } diff --git a/admin/starter/composer.json b/admin/starter/composer.json index cec23ba1987e..082d7b648c25 100644 --- a/admin/starter/composer.json +++ b/admin/starter/composer.json @@ -1,9 +1,14 @@ { "name": "codeigniter4/appstarter", - "type": "project", "description": "CodeIgniter4 starter app", - "homepage": "https://codeigniter.com", "license": "MIT", + "type": "project", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + }, "require": { "php": "^7.4 || ^8.0", "codeigniter4/framework": "^4.0" @@ -13,11 +18,6 @@ "mikey179/vfsstream": "^1.6", "phpunit/phpunit": "^9.1" }, - "config": { - "optimize-autoloader": true, - "preferred-install": "dist", - "sort-packages": true - }, "autoload": { "exclude-from-classmap": [ "**/Database/Migrations/**" @@ -28,12 +28,12 @@ "Tests\\Support\\": "tests/_support" } }, + "config": { + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + }, "scripts": { "test": "phpunit" - }, - "support": { - "forum": "https://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" } } diff --git a/composer.json b/composer.json index 981db0694265..f06a8df04033 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,14 @@ { "name": "codeigniter4/codeigniter4", - "type": "project", "description": "The CodeIgniter framework v4", - "homepage": "https://codeigniter.com", "license": "MIT", + "type": "project", + "homepage": "https://codeigniter.com", + "support": { + "forum": "https://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + }, "require": { "php": "^7.4 || ^8.0", "ext-intl": "*", @@ -13,9 +18,10 @@ "psr/log": "^1.1" }, "require-dev": { - "kint-php/kint": "^5.0.4", "codeigniter/coding-standard": "^1.5", + "ergebnis/composer-normalize": "^2.28", "fakerphp/faker": "^1.9", + "kint-php/kint": "^5.0.4", "mikey179/vfsstream": "^1.6", "nexusphp/cs-config": "^3.6", "nexusphp/tachycardia": "^1.0", @@ -29,33 +35,23 @@ }, "suggest": { "ext-curl": "If you use CURLRequest class", - "ext-imagick": "If you use Image class ImageMagickHandler", - "ext-gd": "If you use Image class GDHandler", + "ext-dom": "If you use TestResponse", "ext-exif": "If you run Image class tests", - "ext-simplexml": "If you format XML", + "ext-fileinfo": "Improves mime type detection for files", + "ext-gd": "If you use Image class GDHandler", + "ext-imagick": "If you use Image class ImageMagickHandler", + "ext-libxml": "If you use TestResponse", + "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", + "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", "ext-mysqli": "If you use MySQL", "ext-oci8": "If you use Oracle Database", "ext-pgsql": "If you use PostgreSQL", - "ext-sqlsrv": "If you use SQL Server", - "ext-sqlite3": "If you use SQLite3", - "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", - "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", + "ext-readline": "Improves CLI::input() usability", "ext-redis": "If you use Cache class RedisHandler", - "ext-dom": "If you use TestResponse", - "ext-libxml": "If you use TestResponse", - "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()", - "ext-fileinfo": "Improves mime type detection for files", - "ext-readline": "Improves CLI::input() usability" - }, - "config": { - "optimize-autoloader": true, - "preferred-install": "dist", - "sort-packages": true - }, - "extra": { - "branch-alias": { - "dev-develop": "4.x-dev" - } + "ext-simplexml": "If you format XML", + "ext-sqlite3": "If you use SQLite3", + "ext-sqlsrv": "If you use SQL Server", + "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()" }, "autoload": { "psr-4": { @@ -71,6 +67,19 @@ "Utils\\": "utils/" } }, + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true + }, + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-develop": "4.x-dev" + } + }, "scripts": { "post-update-cmd": [ "CodeIgniter\\ComposerScripts::postUpdate", @@ -81,8 +90,6 @@ "bash -c \"XDEBUG_MODE=off phpstan analyse\"", "rector process --dry-run" ], - "sa": "@analyze", - "test": "phpunit", "cs": [ "Composer\\Config::disableProcessTimeout", "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php", @@ -95,17 +102,14 @@ "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.no-header.php", "php-cs-fixer fix --ansi --verbose --diff" ], - "style": "@cs-fix" + "sa": "@analyze", + "style": "@cs-fix", + "test": "phpunit" }, "scripts-descriptions": { "analyze": "Run static analysis", - "test": "Run unit tests", "cs": "Check the coding style", - "cs-fix": "Fix the coding style" - }, - "support": { - "forum": "https://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" + "cs-fix": "Fix the coding style", + "test": "Run unit tests" } } diff --git a/tests/system/AutoReview/ComposerJsonTest.php b/tests/system/AutoReview/ComposerJsonTest.php index dc9ad26b9ef8..ecc57c028cba 100644 --- a/tests/system/AutoReview/ComposerJsonTest.php +++ b/tests/system/AutoReview/ComposerJsonTest.php @@ -13,6 +13,7 @@ namespace CodeIgniter\AutoReview; +use InvalidArgumentException; use JsonException; use PHPUnit\Framework\TestCase; @@ -40,7 +41,7 @@ protected function setUp(): void public function testFrameworkRequireIsTheSameWithDevRequire(): void { - $this->checkFramework('require'); + $this->checkSection('require', 'framework'); } public function testFrameworkRequireDevIsTheSameWithDevRequireDev(): void @@ -68,35 +69,66 @@ public function testFrameworkRequireDevIsTheSameWithDevRequireDev(): void public function testFrameworkSuggestIsTheSameWithDevSuggest(): void { - $this->checkFramework('suggest'); + $this->checkSection('suggest', 'framework'); } public function testFrameworkConfigIsTheSameWithDevSuggest(): void { - $this->checkFramework('config'); + $this->checkConfig( + $this->devComposer['config'], + $this->frameworkComposer['config'], + 'framework' + ); } public function testStarterConfigIsTheSameWithDevSuggest(): void { - $this->checkStarter('config'); + $this->checkConfig( + $this->devComposer['config'], + $this->starterComposer['config'], + 'starter' + ); } - private function checkFramework(string $section): void + private function checkSection(string $section, string $component): void { + switch (strtolower($component)) { + case 'framework': + $sectionContent = $this->frameworkComposer[$section] ?? null; + break; + + case 'starter': + $sectionContent = $this->starterComposer[$section] ?? null; + break; + + default: + throw new InvalidArgumentException(sprintf('Unknown component: %s.', $component)); + } + $this->assertSame( $this->devComposer[$section], - $this->frameworkComposer[$section], - 'The framework\'s "' . $section . '" section is not updated with the main composer.json.' + $sectionContent, + sprintf('The %s\'s "%s" section is not updated with the main composer.json', strtolower($component), $section) ); } - private function checkStarter(string $section): void + private function checkConfig(array $fromMain, array $fromComponent, string $component): void { - $this->assertSame( - $this->devComposer[$section], - $this->starterComposer[$section], - 'The starter\'s "' . $section . '" section is not updated with the main composer.json.' - ); + foreach ($fromMain as $key => $expectedValue) { + if (! isset($fromComponent[$key])) { + $this->addToAssertionCount(1); + + continue; + } + + $actualValue = $fromComponent[$key]; + + $this->assertSame($expectedValue, $actualValue, sprintf( + '%s\'s value for config property "%s" is not same with the main composer.json\'s config.', + ucfirst($component), + $key + )); + } } private function getComposerJson(string $path): array