From bd85f7208023c7289d5b3a019c15afa8388ab8f0 Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Mon, 11 Sep 2023 15:02:53 +0800 Subject: [PATCH] feature: add possibility to downgrade releases --- .gitattributes | 3 ++ .github/workflows/release.yml | 88 +++++++++++++++++++++++++++++++++-- .php-cs-fixer.dist.php | 3 ++ bin/rector-downgrade.php | 44 ++++++++++++++++++ bin/transform-source | 24 ++++++++++ composer.json | 3 +- phpstan.neon.dist | 1 + src/ComposerJsonRewriter.php | 49 +++++++++++++++++++ 8 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 bin/rector-downgrade.php create mode 100644 bin/transform-source create mode 100644 src/ComposerJsonRewriter.php diff --git a/.gitattributes b/.gitattributes index 9035739..dcc2486 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,12 +1,15 @@ *.php text eol=lf .github/ export-ignore +bin/ export-ignore tests/ export-ignore .editorconfig export-ignore .gitattributes export-ignore .gitignore export-ignore .php-cs-fixer.dist.php export-ignore +src/ComposerJsonRewriter.php export-ignore src/ComposerScripts.php export-ignore phpunit.dist.xml export-ignore phpstan.neon.dist export-ignore phpstan-baseline.php export-ignore +rector-downgrade.php export-ignore diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c2dcb9..e80f720 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,20 +5,98 @@ on: tags: - '**' +env: + COMPOSER_ROOT_VERSION: '1.x-dev' + DEFAULT_BRANCH: '1.x' + TARGET_PHP_VERSION: '7.4' + TARGET_PHP_VERSION_ID: 70400 + jobs: build: name: Create a release runs-on: ubuntu-latest + steps: - name: Checkout code uses: actions/checkout@v4 - name: Create release - uses: actions/create-release@latest - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} + uses: crazy-max/ghaction-github-release@v2 with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} + token: ${{ secrets.RELEASE_TOKEN }} draft: true prerelease: false + + build_downgraded_release: + name: Build release for lower PHP version + runs-on: ubuntu-latest + needs: build + timeout-minutes: 10 + + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP 8.1 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.RELEASE_TOKEN }} + + - name: Get branch name + id: branch_name + run: echo "BRANCH=build-downgrade-to-${{ env.TARGET_PHP_VERSION_ID }}" >> $GITHUB_OUTPUT + + - name: Install dependencies + run: composer update --ansi + + - name: Downgrade src + run: php bin/transform-source ${{ env.TARGET_PHP_VERSION_ID }} + + - name: Setup PHP ${{ env.TARGET_PHP_VERSION }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.TARGET_PHP_VERSION }} + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.RELEASE_TOKEN }} + + - name: Get tag for downgraded release + id: tag-downgraded + run: echo "${{ format('DOWNGRADED_TAG={0}.{1}', github.ref_name, env.TARGET_PHP_VERSION_ID) }}" >> $GITHUB_OUTPUT + + - name: Import GPG signing information + uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + git_config_global: true + git_user_signingkey: true + git_commit_gpgsign: true + git_tag_gpgsign: true + + - name: Commit and tag + uses: stefanzweifel/git-auto-commit-action@v4 + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} + with: + commit_message: 'Release PHPStan CodeIgniter to target PHP ${{ env.TARGET_PHP_VERSION }}' + branch: ${{ steps.branch_name.outputs.BRANCH }} + tagging_message: ${{ steps.tag-downgraded.outputs.DOWNGRADED_TAG }} + commit_options: '--gpg-sign' + commit_user_name: paulbalandan + commit_user_email: paulbalandan@gmail.com + add_options: '-u' + create_branch: true + + - name: Delete branch + run: | + git switch ${{ env.DEFAULT_BRANCH }} + git branch -D ${{ steps.branch_name.outputs.BRANCH }} diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 587517c..08940ec 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -20,11 +20,14 @@ $finder = Finder::create() ->files() ->in([ + __DIR__ . '/bin', __DIR__ . '/src', __DIR__ . '/tests', ]) ->append([ __FILE__, + __DIR__ . '/bin/parse-php-version', + __DIR__ . '/bin/transform-source', ]); $overrides = [ diff --git a/bin/rector-downgrade.php b/bin/rector-downgrade.php new file mode 100644 index 0000000..7e0e41c --- /dev/null +++ b/bin/rector-downgrade.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use Rector\Config\RectorConfig; +use Rector\DowngradePhp80\Rector\Catch_\DowngradeNonCapturingCatchesRector; +use Rector\DowngradePhp80\Rector\Class_\DowngradePropertyPromotionRector; +use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeTrailingCommasInParamUseRector; +use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeMixedTypeDeclarationRector; +use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeDeclarationRector; +use Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector; +use Rector\DowngradePhp81\Rector\FunctionLike\DowngradePureIntersectionTypeRector; +use Rector\DowngradePhp81\Rector\Property\DowngradeReadonlyPropertyRector; + +return static function (RectorConfig $config): void { + $targetPhpVersionId = (int) getenv('TARGET_PHP_VERSION_ID'); + + $config->paths([__DIR__ . '/../src']); + $config->phpVersion($targetPhpVersionId); + $config->disableParallel(); + + if ($targetPhpVersionId < 80100) { + $config->rule(DowngradePureIntersectionTypeRector::class); + $config->rule(DowngradeReadonlyPropertyRector::class); + } + + if ($targetPhpVersionId < 80000) { + $config->rule(DowngradeNonCapturingCatchesRector::class); + $config->rule(DowngradePropertyPromotionRector::class); + $config->rule(DowngradeTrailingCommasInParamUseRector::class); + $config->rule(DowngradeMixedTypeDeclarationRector::class); + $config->rule(DowngradeUnionTypeDeclarationRector::class); + $config->rule(DowngradeUnionTypeTypedPropertyRector::class); + } +}; diff --git a/bin/transform-source b/bin/transform-source new file mode 100644 index 0000000..1e95e12 --- /dev/null +++ b/bin/transform-source @@ -0,0 +1,24 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +require __DIR__ . '/../vendor/autoload.php'; + +use CodeIgniter\PHPStan\ComposerJsonRewriter; + +$targetPhpVersionId = (int) $argv[1]; + +putenv("TARGET_PHP_VERSION_ID={$targetPhpVersionId}"); +echo 'TARGET_PHP_VERSION_ID: ' . $targetPhpVersionId . PHP_EOL . PHP_EOL; + +(new ComposerJsonRewriter())->rewriteUsingPhp($targetPhpVersionId); +passthru('php vendor/bin/rector process -c bin/rector-downgrade.php --ansi --no-diffs'); +passthru('php vendor/bin/php-cs-fixer fix -v --ansi'); diff --git a/composer.json b/composer.json index 8d8e8c2..ed62c97 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.3", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "^10.2" + "phpunit/phpunit": "^10.2", + "rector/rector": "^0.18.2" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6a15363..380c680 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,6 +10,7 @@ parameters: - tests excludePaths: analyseAndScan: + - src/ComposerJsonRewriter.php - src/ComposerScripts.php - tests/Fixtures tmpDir: build/phpstan diff --git a/src/ComposerJsonRewriter.php b/src/ComposerJsonRewriter.php new file mode 100644 index 0000000..ea381ba --- /dev/null +++ b/src/ComposerJsonRewriter.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\PHPStan; + +use RuntimeException; + +/** + * @internal + */ +final class ComposerJsonRewriter +{ + private string $composerJson = __DIR__ . '/../composer.json'; + + /** + * @var array + */ + private array $replacements = [ + 70400 => '^7.4 || ^8.0', + 80000 => '^8.0', + ]; + + public function rewriteUsingPhp(int $targetPhpVersionId): void + { + if (! isset($this->replacements[$targetPhpVersionId])) { + throw new RuntimeException(sprintf('Rewriting composer.json to PHP_VERSION_ID %d is not supported.', $targetPhpVersionId)); + } + + $composerJson = json_decode((string) @file_get_contents($this->composerJson), true, 512, JSON_THROW_ON_ERROR); + + $composerJson['require']['php'] = $this->replacements[$targetPhpVersionId]; + + $composerJson = json_encode($composerJson, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES) . "\n"; + + if (file_put_contents($this->composerJson, $composerJson) === false) { + throw new RuntimeException('Rewriting to composer.json failed.'); + } + } +}