[scoped] Build PHP 7.0 repo to own repository to avoid breaking prefixed rector (#6223)

* [scoped] build PHP 7.0 repo to own repository to avoid breaking prefixed rector

* lint with PHP 7.0 files
This commit is contained in:
Tomas Votruba 2021-04-23 23:05:26 +02:00 committed by GitHub
parent 793dd3fd2e
commit a32055f317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 688 additions and 6 deletions

View File

@ -0,0 +1,94 @@
# builds the content of https://github.com/rectorphp/rector-prefixed
# inspiration from https://github.com/phpstan/phpstan-src/blob/master/.github/workflows/phar.yml
name: Build Scoped Rector PHP 7.0
on:
push:
branches:
- main
tags:
- '*'
env:
# see https://github.com/composer/composer/issues/9368#issuecomment-718112361
COMPOSER_ROOT_VERSION: "dev-main"
jobs:
build_scoped_rector_php70:
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v2
with:
fetch-depth: 0
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.3
coverage: none
# fixes https://github.com/rectorphp/rector/pull/4559/checks?check_run_id=1359814403, see https://github.com/shivammathur/setup-php#composer-github-oauth
env:
COMPOSER_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# install only prod dependencies - do not use ramsey, it uses cache including "dev", we want to avoid it here
- run: composer install --no-dev --ansi
# 1. copy files to $NESTED_DIRECTORY directory Exclude the scoped/nested directories to prevent rsync from copying in a loop
- run: rsync --exclude rector-build -av * rector-build --quiet
- run: rm -rf rector-build/packages-tests rector-build/rules-tests rector-build/tests
# 2. downgrade rector
- run: sh build/downgrade-rector.sh rector-build
# 3. prefix classes
- run: sh build/build-rector-scoped.sh rector-build rector-prefixed-downgraded
# 4. lint the code for PHP 7.0 - this must happen here, as setup-php allows only one PHP version switch: https://github.com/shivammathur/setup-php/issues/434
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.0
coverage: none
- run: composer create-project php-parallel-lint/php-parallel-lint php-parallel-lint --ansi
- run: php-parallel-lint/parallel-lint rector-prefixed-downgraded --exclude rector-prefixed-downgraded/stubs --exclude rector-prefixed-downgraded/vendor/symfony/error-handler/Resources --exclude rector-prefixed-downgraded/vendor/symfony/http-kernel/Resources --exclude rector-prefixed-downgraded/vendor/rector/rector-nette/tests --exclude rector-prefixed-downgraded/vendor/symfony/polyfill-mbstring/bootstrap80.php
# 5. copy repository meta files
- run: |
cp -R build/target-repository/. rector-prefixed-downgraded
cp -R templates rector-prefixed-downgraded/
# 6. clone remote repository, so we can push it
-
uses: "actions/checkout@v2"
with:
repository: rectorphp/rector-prefixed-php70
path: remote-repository
token: ${{ secrets.ACCESS_TOKEN }}
# remove remote files, to avoid piling up dead code in remote repository
- run: rm -rf remote-repository/config remote-repository/src remote-repository/rules remote-repository/packages remote-repository/vendor
- run: cp -a rector-prefixed-downgraded/. remote-repository
# 7. setup git
-
working-directory: remote-repository
run: |
git config user.email "tomas.vot@gmail.com"
git config user.name "Tomas Votruba"
# commit metadata
-
name: "Get Git log"
id: git-log
run: echo ::set-output name=log::$(git log ${{ github.event.before }}..${{ github.event.after }} --reverse --pretty='%H %s' | sed -e 's/^/https:\/\/github.com\/rectorphp\/rector\/commit\//')
-
name: "Commit Prefixed PHP 7.0 main"
working-directory: remote-repository
run: |
git add --all
git commit -m "Updated Rector to commit ${{ github.event.after }}" -m "${{ steps.git-log.outputs.log }}"
git push --quiet origin main

View File

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Core\Stubs\PHPStanStubLoader;
use Rector\DowngradePhp71\Rector\FunctionLike\DowngradeNullableTypeDeclarationRector;
use Rector\Set\ValueObject\DowngradeSetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
$phpStanStubLoader = new PHPStanStubLoader();
$phpStanStubLoader->loadStubs();
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$skip = array_merge(
DowngradeRectorConfig::DEPENDENCY_EXCLUDE_PATHS,
[
// should be skipped until phpstan is downgraded to avoid conflict like this https://github.com/rectorphp/rector-prefixed/runs/2422176105#step:4:4
DowngradeNullableTypeDeclarationRector::class
]
);
$parameters->set(Option::SKIP, $skip);
$parameters->set(Option::PHPSTAN_FOR_RECTOR_PATH, __DIR__ . '/phpstan-for-downgrade.neon');
$parameters->set(Option::SETS, [
DowngradeSetList::PHP_80,
DowngradeSetList::PHP_74,
DowngradeSetList::PHP_73,
DowngradeSetList::PHP_72,
DowngradeSetList::PHP_71,
]);
};
/**
* Configuration consts for the different rector.php config files
*/
final class DowngradeRectorConfig
{
/**
* Exclude paths when downgrading a dependency
*/
public const DEPENDENCY_EXCLUDE_PATHS = [
'*/tests/*',
// symfony test are parts of package
'*/Test/*',
// missing phpunit test case
'packages/Testing/PHPUnit/AbstractRectorTestCase.php',
'packages/Testing/PHPUnit/AbstractComposerRectorTestCase.php',
// only for dev
'packages/Testing/PhpConfigPrinter/*',
// Individual classes that can be excluded because
// they are not used by Rector, and they use classes
// loaded with "require-dev" so it'd throw an error
// use relative paths, so files are excluded on nested directory too
'vendor/symfony/http-kernel/HttpKernelBrowser.php',
'vendor/symfony/http-foundation/Session/*',
'vendor/symfony/string/Slugger/AsciiSlugger.php',
'vendor/symfony/cache/*',
'nette/caching/src/Bridges/*',
// This class has an issue for PHP 7.1:
// https://github.com/rectorphp/rector/issues/4816#issuecomment-743209526
// It doesn't happen often, and Rector doesn't use it, so then
// we simply skip downgrading this class
'vendor/symfony/dependency-injection/ExpressionLanguage.php',
'vendor/symfony/dependency-injection/ExpressionLanguageProvider.php',
'vendor/symfony/var-dumper/Caster/*',
];
}

View File

@ -30,7 +30,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
DowngradeSetList::PHP_74,
DowngradeSetList::PHP_73,
DowngradeSetList::PHP_72,
DowngradeSetList::PHP_71,
]);
};

View File

@ -20,7 +20,7 @@ BUILD_DIRECTORY=$1
echo "[NOTE] Running downgrade in '$BUILD_DIRECTORY' directory\n";
# 3. provide directories to downgrade; includes the rector dirs
directories=$(php -d memory_limit=-1 bin/rector downgrade-paths 7.0 --config build/config/config-downgrade.php --working-dir $BUILD_DIRECTORY --ansi)
directories=$(php -d memory_limit=-1 bin/rector downgrade-paths 7.1 --config build/config/config-downgrade.php --working-dir $BUILD_DIRECTORY --ansi)
# split array see https://stackoverflow.com/a/1407098/1348344
export IFS=";"

View File

@ -0,0 +1,27 @@
name: Bare Run
on:
pull_request: null
push:
branches:
- main
jobs:
bare_run:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v2
-
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
- run: php bin/rector list --ansi

View File

@ -0,0 +1,60 @@
name: Rector Run
on:
pull_request: null
push:
branches:
- main
jobs:
rector_run:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.0', 7.1', '7.2', '7.3', '7.4', '8.0']
commands:
-
name: 'Finalize Entity'
install: composer require doctrine/orm
run: vendor/bin/rector process ../tests/fixture-finalize --config ../ci/rector-finalize.php --ansi
-
name: 'Composer Dependency'
install: composer require symfony/console 2.8
run: vendor/bin/rector list --debug --ansi
-
name: 'Along PHPStan'
install: composer require phpstan/phpstan --dev --ansi
run: |
vendor/bin/rector list --ansi
vendor/bin/phpstan -h --ansi
name: "PHP ${{ matrix.php_version }}"
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
- run: |
mkdir standalone
cd standalone
# wait for deploy to packagist
sleep 70
- run: |
cd standalone
# run
composer require rector/rector-prefixed:dev-main --dev --ansi
${{ matrix.commands.install }}
-
run: |
cd standalone
${{ matrix.commands.run }}

View File

@ -0,0 +1,21 @@
name: PHP 8 Attributes
on:
pull_request: null
push:
branches:
- main
jobs:
php8_attributes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
coverage: none
- run: bin/rector process tests/fixture-php8-attributes --config ci/rector-attributes.php --ansi

View File

@ -0,0 +1,22 @@
name: Simple Test
on:
pull_request: null
push:
branches:
- main
jobs:
simple_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none
- run: composer require phpunit/phpunit --dev
- run: vendor/bin/phpunit tests/Rector/RenameSimpleRectorTest.php

View File

@ -0,0 +1,25 @@
# Prefixed Rector
[![Build Status Github Actions](https://img.shields.io/github/workflow/status/rectorphp/rector-prefixed/Code_Checks?style=flat-square)](https://github.com/rectorphp/rector-prefixed/actions)
[![Downloads](https://img.shields.io/packagist/dt/rector/rector-prefixed.svg?style=flat-square)](https://packagist.org/packages/rector/rector-prefixed)
Do you have conflicts on Rector install? You're in the right place. Prefixed Rector can [be installed even on very old Symfony](https://getrector.org/blog/2020/01/20/how-to-install-rector-despite-composer-conflicts).
Do you have older PHP? Rector prefixed goes down to PHP 7.0, so you can install it even on older projects.
## Install
```bash
composer require rector/rector-prefixed --dev
```
```bash
# generate "rector.php" config
vendor/bin/rector init
# dry run
vendor/bin/rector process src --dry-run
# changing run
vendor/bin/rector process src
```

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Symfony\Set\SymfonySetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
// route class must exist and be loaded, as annotation parser uses dynamic reflection
require_once __DIR__ . '/../stubs/Symfony/Component/Routing/Annotation/Route.php';
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(SymfonySetList::SYMFONY_52);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_80);
};

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(FinalizeClassesWithoutChildrenRector::class);
};

View File

@ -0,0 +1,21 @@
{
"name": "rector/rector-prefixed",
"description": "Prefixed and PHP 7.0 downgraded version of rector/rector",
"license": "MIT",
"bin": [
"bin/rector"
],
"require": {
"php": "^7.0|^8.0",
"phpstan/phpstan": "^0.12.83"
},
"extra": {
"branch-alias": {
"dev-main": "0.10-dev"
}
},
"conflict": {
"phpstan/phpdoc-parser": "<=0.5.3",
"phpstan/phpstan": "<=0.12.82"
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<phpunit
bootstrap="tests/bootstrap.php"
colors="true"
verbose="true"
>
</phpunit>

View File

@ -0,0 +1,177 @@
<?php
/** @changelog https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Routing/Annotation/Route.php */
declare(strict_types=1);
namespace Symfony\Component\Routing\Annotation;
if (class_exists('Symfony\Component\Routing\Annotation\Route')) {
return;
}
/**
* @Annotation
* @Target({"CLASS", "METHOD"})
*/
class Route
{
private $path;
private $localizedPaths = [];
private $name;
private $requirements = [];
private $options = [];
private $defaults = [];
private $host;
private $methods = [];
private $schemes = [];
private $condition;
private $locale;
private $format;
private $utf8;
/**
* @param array $data An array of key/value parameters
*
* @throws \BadMethodCallException
*/
public function __construct(array $data)
{
if (isset($data['localized_paths'])) {
throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', \get_class($this)));
}
if (isset($data['value'])) {
$data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value'];
unset($data['value']);
}
if (isset($data['path']) && \is_array($data['path'])) {
$data['localized_paths'] = $data['path'];
unset($data['path']);
}
if (isset($data['locale'])) {
$data['defaults']['_locale'] = $data['locale'];
unset($data['locale']);
}
if (isset($data['format'])) {
$data['defaults']['_format'] = $data['format'];
unset($data['format']);
}
if (isset($data['utf8'])) {
$data['options']['utf8'] = filter_var($data['utf8'], FILTER_VALIDATE_BOOLEAN) ?: false;
unset($data['utf8']);
}
foreach ($data as $key => $value) {
$method = 'set'.str_replace('_', '', $key);
if (!method_exists($this, $method)) {
throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, \get_class($this)));
}
$this->$method($value);
}
}
public function setPath($path)
{
$this->path = $path;
}
public function getPath()
{
return $this->path;
}
public function setLocalizedPaths(array $localizedPaths)
{
$this->localizedPaths = $localizedPaths;
}
public function getLocalizedPaths(): array
{
return $this->localizedPaths;
}
public function setHost($pattern)
{
$this->host = $pattern;
}
public function getHost()
{
return $this->host;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setRequirements($requirements)
{
$this->requirements = $requirements;
}
public function getRequirements()
{
return $this->requirements;
}
public function setOptions($options)
{
$this->options = $options;
}
public function getOptions()
{
return $this->options;
}
public function setDefaults($defaults)
{
$this->defaults = $defaults;
}
public function getDefaults()
{
return $this->defaults;
}
public function setSchemes($schemes)
{
$this->schemes = \is_array($schemes) ? $schemes : [$schemes];
}
public function getSchemes()
{
return $this->schemes;
}
public function setMethods($methods)
{
$this->methods = \is_array($methods) ? $methods : [$methods];
}
public function getMethods()
{
return $this->methods;
}
public function setCondition($condition)
{
$this->condition = $condition;
}
public function getCondition()
{
return $this->condition;
}
}

View File

@ -0,0 +1,11 @@
<?php
$value = 1000;
?>
-----
<?php
$newValue = 1000;
?>

View File

@ -0,0 +1,34 @@
<?php
use PhpParser\Node;
use PhpParser\Node\Expr\Variable;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \RenameSimpleRectorTest
*/
final class RenameSimpleRector extends AbstractRector
{
/**
* @return array<class-string<\PhpParser\Node>>
*/
public function getNodeTypes(): array
{
return [Variable::class];
}
/**
* @param Variable $node
*/
public function refactor(Node $node): ?Node
{
$node->name = 'newValue';
return $node;
}
public function getRuleDefinition(): RuleDefinition
{
// ...
}
}

View File

@ -0,0 +1,28 @@
<?php
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RenameSimpleRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(RenameSimpleRector::class);
};

View File

@ -0,0 +1,4 @@
<?php
require_once __DIR__ . '/Rector/RenameSimpleRector.php';
require_once __DIR__ . '/Rector/RenameSimpleRectorTest.php';

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPrefixed\Tests;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SkipSomeEntity
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPrefixed\Tests;
class SomeClassWithoutChildren
{
}

View File

@ -0,0 +1,13 @@
<?php
use Symfony\Component\Routing\Annotation\Route;
class SomeController
{
/**
* @Route()
*/
public function someMethod()
{
}
}

View File

@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.0', '7.1', '7.2', '7.3', '7.4', '8.0']
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v2

View File

@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.0', 7.1', '7.2', '7.3', '7.4', '8.0']
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
commands:
-
name: 'Finalize Entity'

View File

@ -5,7 +5,7 @@
Do you have conflicts on Rector install? You're in the right place. Prefixed Rector can [be installed even on very old Symfony](https://getrector.org/blog/2020/01/20/how-to-install-rector-despite-composer-conflicts).
Do you have older PHP? Rector prefixed goes down to PHP 7.0, so you can install it even on older projects.
Do you have older PHP? Rector prefixed goes down to PHP 7.1, so you can install it even on older projects.
## Install

View File

@ -6,7 +6,7 @@
"bin/rector"
],
"require": {
"php": "^7.0|^8.0",
"php": "^7.1|^8.0",
"phpstan/phpstan": "^0.12.83"
},
"extra": {