Skip to content

Commit bd85f72

Browse files
committed
feature: add possibility to downgrade releases
1 parent a38bf93 commit bd85f72

8 files changed

+209
-6
lines changed

.gitattributes

+3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
*.php text eol=lf
22

33
.github/ export-ignore
4+
bin/ export-ignore
45
tests/ export-ignore
56
.editorconfig export-ignore
67
.gitattributes export-ignore
78
.gitignore export-ignore
89
.php-cs-fixer.dist.php export-ignore
10+
src/ComposerJsonRewriter.php export-ignore
911
src/ComposerScripts.php export-ignore
1012
phpunit.dist.xml export-ignore
1113
phpstan.neon.dist export-ignore
1214
phpstan-baseline.php export-ignore
15+
rector-downgrade.php export-ignore

.github/workflows/release.yml

+83-5
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,98 @@ on:
55
tags:
66
- '**'
77

8+
env:
9+
COMPOSER_ROOT_VERSION: '1.x-dev'
10+
DEFAULT_BRANCH: '1.x'
11+
TARGET_PHP_VERSION: '7.4'
12+
TARGET_PHP_VERSION_ID: 70400
13+
814
jobs:
915
build:
1016
name: Create a release
1117
runs-on: ubuntu-latest
18+
1219
steps:
1320
- name: Checkout code
1421
uses: actions/checkout@v4
1522

1623
- name: Create release
17-
uses: actions/create-release@latest
18-
env:
19-
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
24+
uses: crazy-max/ghaction-github-release@v2
2025
with:
21-
tag_name: ${{ github.ref }}
22-
release_name: ${{ github.ref }}
26+
token: ${{ secrets.RELEASE_TOKEN }}
2327
draft: true
2428
prerelease: false
29+
30+
build_downgraded_release:
31+
name: Build release for lower PHP version
32+
runs-on: ubuntu-latest
33+
needs: build
34+
timeout-minutes: 10
35+
36+
permissions:
37+
# Give the default GITHUB_TOKEN write permission to commit and push the
38+
# added or changed files to the repository.
39+
contents: write
40+
41+
steps:
42+
- name: Checkout code
43+
uses: actions/checkout@v4
44+
45+
- name: Setup PHP 8.1
46+
uses: shivammathur/setup-php@v2
47+
with:
48+
php-version: '8.1'
49+
coverage: none
50+
env:
51+
COMPOSER_TOKEN: ${{ secrets.RELEASE_TOKEN }}
52+
53+
- name: Get branch name
54+
id: branch_name
55+
run: echo "BRANCH=build-downgrade-to-${{ env.TARGET_PHP_VERSION_ID }}" >> $GITHUB_OUTPUT
56+
57+
- name: Install dependencies
58+
run: composer update --ansi
59+
60+
- name: Downgrade src
61+
run: php bin/transform-source ${{ env.TARGET_PHP_VERSION_ID }}
62+
63+
- name: Setup PHP ${{ env.TARGET_PHP_VERSION }}
64+
uses: shivammathur/setup-php@v2
65+
with:
66+
php-version: ${{ env.TARGET_PHP_VERSION }}
67+
coverage: none
68+
env:
69+
COMPOSER_TOKEN: ${{ secrets.RELEASE_TOKEN }}
70+
71+
- name: Get tag for downgraded release
72+
id: tag-downgraded
73+
run: echo "${{ format('DOWNGRADED_TAG={0}.{1}', github.ref_name, env.TARGET_PHP_VERSION_ID) }}" >> $GITHUB_OUTPUT
74+
75+
- name: Import GPG signing information
76+
uses: crazy-max/ghaction-import-gpg@v6
77+
with:
78+
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
79+
passphrase: ${{ secrets.PASSPHRASE }}
80+
git_config_global: true
81+
git_user_signingkey: true
82+
git_commit_gpgsign: true
83+
git_tag_gpgsign: true
84+
85+
- name: Commit and tag
86+
uses: stefanzweifel/git-auto-commit-action@v4
87+
env:
88+
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
89+
with:
90+
commit_message: 'Release PHPStan CodeIgniter to target PHP ${{ env.TARGET_PHP_VERSION }}'
91+
branch: ${{ steps.branch_name.outputs.BRANCH }}
92+
tagging_message: ${{ steps.tag-downgraded.outputs.DOWNGRADED_TAG }}
93+
commit_options: '--gpg-sign'
94+
commit_user_name: paulbalandan
95+
commit_user_email: [email protected]
96+
add_options: '-u'
97+
create_branch: true
98+
99+
- name: Delete branch
100+
run: |
101+
git switch ${{ env.DEFAULT_BRANCH }}
102+
git branch -D ${{ steps.branch_name.outputs.BRANCH }}

.php-cs-fixer.dist.php

+3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020
$finder = Finder::create()
2121
->files()
2222
->in([
23+
__DIR__ . '/bin',
2324
__DIR__ . '/src',
2425
__DIR__ . '/tests',
2526
])
2627
->append([
2728
__FILE__,
29+
__DIR__ . '/bin/parse-php-version',
30+
__DIR__ . '/bin/transform-source',
2831
]);
2932

3033
$overrides = [

bin/rector-downgrade.php

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) 2023 CodeIgniter Foundation <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
use Rector\Config\RectorConfig;
15+
use Rector\DowngradePhp80\Rector\Catch_\DowngradeNonCapturingCatchesRector;
16+
use Rector\DowngradePhp80\Rector\Class_\DowngradePropertyPromotionRector;
17+
use Rector\DowngradePhp80\Rector\ClassMethod\DowngradeTrailingCommasInParamUseRector;
18+
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeMixedTypeDeclarationRector;
19+
use Rector\DowngradePhp80\Rector\FunctionLike\DowngradeUnionTypeDeclarationRector;
20+
use Rector\DowngradePhp80\Rector\Property\DowngradeUnionTypeTypedPropertyRector;
21+
use Rector\DowngradePhp81\Rector\FunctionLike\DowngradePureIntersectionTypeRector;
22+
use Rector\DowngradePhp81\Rector\Property\DowngradeReadonlyPropertyRector;
23+
24+
return static function (RectorConfig $config): void {
25+
$targetPhpVersionId = (int) getenv('TARGET_PHP_VERSION_ID');
26+
27+
$config->paths([__DIR__ . '/../src']);
28+
$config->phpVersion($targetPhpVersionId);
29+
$config->disableParallel();
30+
31+
if ($targetPhpVersionId < 80100) {
32+
$config->rule(DowngradePureIntersectionTypeRector::class);
33+
$config->rule(DowngradeReadonlyPropertyRector::class);
34+
}
35+
36+
if ($targetPhpVersionId < 80000) {
37+
$config->rule(DowngradeNonCapturingCatchesRector::class);
38+
$config->rule(DowngradePropertyPromotionRector::class);
39+
$config->rule(DowngradeTrailingCommasInParamUseRector::class);
40+
$config->rule(DowngradeMixedTypeDeclarationRector::class);
41+
$config->rule(DowngradeUnionTypeDeclarationRector::class);
42+
$config->rule(DowngradeUnionTypeTypedPropertyRector::class);
43+
}
44+
};

bin/transform-source

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
/**
5+
* This file is part of CodeIgniter 4 framework.
6+
*
7+
* (c) 2023 CodeIgniter Foundation <[email protected]>
8+
*
9+
* For the full copyright and license information, please view
10+
* the LICENSE file that was distributed with this source code.
11+
*/
12+
13+
require __DIR__ . '/../vendor/autoload.php';
14+
15+
use CodeIgniter\PHPStan\ComposerJsonRewriter;
16+
17+
$targetPhpVersionId = (int) $argv[1];
18+
19+
putenv("TARGET_PHP_VERSION_ID={$targetPhpVersionId}");
20+
echo 'TARGET_PHP_VERSION_ID: ' . $targetPhpVersionId . PHP_EOL . PHP_EOL;
21+
22+
(new ComposerJsonRewriter())->rewriteUsingPhp($targetPhpVersionId);
23+
passthru('php vendor/bin/rector process -c bin/rector-downgrade.php --ansi --no-diffs');
24+
passthru('php vendor/bin/php-cs-fixer fix -v --ansi');

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"phpstan/phpstan-deprecation-rules": "^1.1",
3535
"phpstan/phpstan-phpunit": "^1.3",
3636
"phpstan/phpstan-strict-rules": "^1.5",
37-
"phpunit/phpunit": "^10.2"
37+
"phpunit/phpunit": "^10.2",
38+
"rector/rector": "^0.18.2"
3839
},
3940
"minimum-stability": "dev",
4041
"prefer-stable": true,

phpstan.neon.dist

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ parameters:
1010
- tests
1111
excludePaths:
1212
analyseAndScan:
13+
- src/ComposerJsonRewriter.php
1314
- src/ComposerScripts.php
1415
- tests/Fixtures
1516
tmpDir: build/phpstan

src/ComposerJsonRewriter.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) 2023 CodeIgniter Foundation <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\PHPStan;
15+
16+
use RuntimeException;
17+
18+
/**
19+
* @internal
20+
*/
21+
final class ComposerJsonRewriter
22+
{
23+
private string $composerJson = __DIR__ . '/../composer.json';
24+
25+
/**
26+
* @var array<int, string>
27+
*/
28+
private array $replacements = [
29+
70400 => '^7.4 || ^8.0',
30+
80000 => '^8.0',
31+
];
32+
33+
public function rewriteUsingPhp(int $targetPhpVersionId): void
34+
{
35+
if (! isset($this->replacements[$targetPhpVersionId])) {
36+
throw new RuntimeException(sprintf('Rewriting composer.json to PHP_VERSION_ID %d is not supported.', $targetPhpVersionId));
37+
}
38+
39+
$composerJson = json_decode((string) @file_get_contents($this->composerJson), true, 512, JSON_THROW_ON_ERROR);
40+
41+
$composerJson['require']['php'] = $this->replacements[$targetPhpVersionId];
42+
43+
$composerJson = json_encode($composerJson, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES) . "\n";
44+
45+
if (file_put_contents($this->composerJson, $composerJson) === false) {
46+
throw new RuntimeException('Rewriting to composer.json failed.');
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)