From 72b9be586570f967812a88a93541257bd90edf6b Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 19 May 2022 13:25:28 +0000 Subject: [PATCH 1/3] Switch to CodeIgniter DevKit --- .github/workflows/psalm.yml | 75 ++++++++++++++++++++++++++++++++ composer.json | 55 +++++++++++------------- psalm.xml | 4 +- rector.php | 85 ++++++++++++++++--------------------- 4 files changed, 138 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/psalm.yml diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 000000000..03eb1cd76 --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,75 @@ +name: Psalm + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'psalm*' + - '.github/workflows/psalm.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'psalm*' + - '.github/workflows/psalm.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Psalm Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpstan, phpunit + extensions: intl, json, mbstring, xml + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create Psalm cache directory + run: mkdir -p build/psalm + + - name: Cache Psalm results + uses: actions/cache@v3 + with: + path: build/psalm + key: ${{ runner.os }}-psalm-${{ github.sha }} + restore-keys: ${{ runner.os }}-psalm- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Run Psalm analysis + run: vendor/bin/psalm diff --git a/composer.json b/composer.json index ba89a06ca..344fbff91 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,14 @@ { "name": "codeigniter4/shield", - "type": "library", "description": "Authentication and Authorization for CodeIgniter 4", + "license": "MIT", + "type": "library", "keywords": [ "codeigniter", "codeigniter4", "authentication", "authorization" ], - "homepage": "https://github.com/codeigniter4/shield", - "license": "MIT", "authors": [ { "name": "Lonnie Ezell", @@ -17,31 +16,28 @@ "role": "Developer" } ], + "homepage": "https://github.com/codeigniter4/shield", "require": { "php": "^7.4 || ^8.0", "codeigniter4/settings": "^2.0" }, - "provide": { - "codeigniter4/authentication-implementation": "1.0" - }, "require-dev": { - "codeigniter/coding-standard": "^1.1", + "codeigniter4/devkit": "^1.0", "codeigniter4/framework": "^4.1", - "fakerphp/faker": "^1.9", - "friendsofphp/php-cs-fixer": "^3.0", "mockery/mockery": "^1.0", - "nexusphp/cs-config": "^3.1", - "nexusphp/tachycardia": "^1.0", - "php-coveralls/php-coveralls": "^2.4", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^9.1", "vimeo/psalm": "^4.22" }, - "config": { - "allow-plugins": { - "phpstan/extension-installer": true - } + "provide": { + "codeigniter4/authentication-implementation": "1.0" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/codeigniter4/CodeIgniter4" + } + ], + "minimum-stability": "dev", + "prefer-stable": true, "autoload": { "psr-4": { "CodeIgniter\\Shield\\": "src" @@ -56,23 +52,16 @@ "Tests\\Support\\": "tests/_support" } }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/codeigniter4/CodeIgniter4" + "config": { + "allow-plugins": { + "phpstan/extension-installer": true } - ], - "minimum-stability": "dev", - "prefer-stable": true, + }, "scripts": { "post-update-cmd": [ "bash admin/setup.sh" ], "analyze": "phpstan analyze", - "sa": [ - "@analyze", - "psalm" - ], "ci": [ "Composer\\Config::disableProcessTimeout", "@deduplicate", @@ -82,11 +71,15 @@ "rector process", "@style" ], + "cs-fix": "@style", "deduplicate": "phpcpd app/ src/", "inspect": "deptrac analyze --cache-file=build/deptrac.cache", "mutate": "infection --threads=2 --skip-initial-tests --coverage=build/phpunit", - "style": "php-cs-fixer fix --ansi --verbose --diff", - "cs-fix": "@style", + "sa": [ + "phpstan analyze", + "psalm" + ], + "style": "php-cs-fixer fix --verbose --ansi --using-cache=no", "test": "phpunit" } } diff --git a/psalm.xml b/psalm.xml index e94600546..28656c022 100644 --- a/psalm.xml +++ b/psalm.xml @@ -6,9 +6,11 @@ xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" autoloader="psalm_autoload.php" + cacheDirectory="build/psalm/" > - + + diff --git a/rector.php b/rector.php index 7d81cb1d7..271e727c9 100644 --- a/rector.php +++ b/rector.php @@ -1,5 +1,6 @@ import(SetList::DEAD_CODE); - $containerConfigurator->import(LevelSetList::UP_TO_PHP_74); - $containerConfigurator->import(PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD); - $containerConfigurator->import(PHPUnitSetList::PHPUNIT_80); - - $parameters = $containerConfigurator->parameters(); - - $parameters->set(Option::PARALLEL, true); +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->sets([SetList::DEAD_CODE, LevelSetList::UP_TO_PHP_74, PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD, PHPUnitSetList::PHPUNIT_80]); + $rectorConfig->parallel(); // The paths to refactor (can also be supplied with CLI arguments) - $parameters->set(Option::PATHS, [ + $rectorConfig->paths([ __DIR__ . '/src/', __DIR__ . '/tests/', ]); // Include Composer's autoload - required for global execution, remove if running locally - $parameters->set(Option::AUTOLOAD_PATHS, [ + $rectorConfig->autoloadPaths([ __DIR__ . '/vendor/autoload.php', ]); // Do you need to include constants, class aliases, or a custom autoloader? - $parameters->set(Option::BOOTSTRAP_FILES, [ + $rectorConfig->bootstrapFiles([ realpath(getcwd()) . '/vendor/codeigniter4/framework/system/Test/bootstrap.php', ]); if (is_file(__DIR__ . '/phpstan.neon.dist')) { - $parameters->set(Option::PHPSTAN_FOR_RECTOR_PATH, __DIR__ . '/phpstan.neon.dist'); + $rectorConfig->phpstanConfig(__DIR__ . '/phpstan.neon.dist'); } // Set the target version for refactoring - $parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_74); + $rectorConfig->phpVersion(PhpVersion::PHP_74); // Auto-import fully qualified class names - $parameters->set(Option::AUTO_IMPORT_NAMES, true); + $rectorConfig->importNames(); // Are there files or rules you need to skip? - $parameters->set(Option::SKIP, [ - __DIR__ . '/src/Config/Auth.php', + $rectorConfig->skip([ __DIR__ . '/src/Views', JsonThrowOnErrorRector::class, @@ -91,7 +82,6 @@ // Ignore files that should not be namespaced NormalizeNamespaceByPSR4ComposerAutoloadRector::class => [ __DIR__ . '/src/Helpers', - __DIR__ . '/tests/_support', ], // May load view files directly when detecting classes @@ -100,33 +90,30 @@ // May be uninitialized on purpose AddDefaultValueForUndefinedVariableRector::class, ]); - - // Additional rules to apply - $services = $containerConfigurator->services(); - $services->set(SimplifyUselessVariableRector::class); - $services->set(RemoveAlwaysElseRector::class); - $services->set(CountArrayToEmptyArrayComparisonRector::class); - $services->set(ForToForeachRector::class); - $services->set(ChangeNestedForeachIfsToEarlyContinueRector::class); - $services->set(ChangeIfElseValueAssignToEarlyReturnRector::class); - $services->set(SimplifyStrposLowerRector::class); - $services->set(CombineIfRector::class); - $services->set(SimplifyIfReturnBoolRector::class); - $services->set(InlineIfToExplicitIfRector::class); - $services->set(PreparedValueToEarlyReturnRector::class); - $services->set(ShortenElseIfRector::class); - $services->set(SimplifyIfElseToTernaryRector::class); - $services->set(UnusedForeachValueToArrayKeysRector::class); - $services->set(ChangeArrayPushToArrayAssignRector::class); - $services->set(UnnecessaryTernaryExpressionRector::class); - $services->set(AddPregQuoteDelimiterRector::class); - $services->set(SimplifyRegexPatternRector::class); - $services->set(FuncGetArgsToVariadicParamRector::class); - $services->set(MakeInheritedMethodVisibilitySameAsParentRector::class); - $services->set(SimplifyEmptyArrayCheckRector::class); - $services->set(NormalizeNamespaceByPSR4ComposerAutoloadRector::class); - $services->set(TypedPropertyRector::class) - ->configure([ - TypedPropertyRector::INLINE_PUBLIC => true, + $rectorConfig->rule(SimplifyUselessVariableRector::class); + $rectorConfig->rule(RemoveAlwaysElseRector::class); + $rectorConfig->rule(CountArrayToEmptyArrayComparisonRector::class); + $rectorConfig->rule(ForToForeachRector::class); + $rectorConfig->rule(ChangeNestedForeachIfsToEarlyContinueRector::class); + $rectorConfig->rule(ChangeIfElseValueAssignToEarlyReturnRector::class); + $rectorConfig->rule(SimplifyStrposLowerRector::class); + $rectorConfig->rule(CombineIfRector::class); + $rectorConfig->rule(SimplifyIfReturnBoolRector::class); + $rectorConfig->rule(InlineIfToExplicitIfRector::class); + $rectorConfig->rule(PreparedValueToEarlyReturnRector::class); + $rectorConfig->rule(ShortenElseIfRector::class); + $rectorConfig->rule(SimplifyIfElseToTernaryRector::class); + $rectorConfig->rule(UnusedForeachValueToArrayKeysRector::class); + $rectorConfig->rule(ChangeArrayPushToArrayAssignRector::class); + $rectorConfig->rule(UnnecessaryTernaryExpressionRector::class); + $rectorConfig->rule(AddPregQuoteDelimiterRector::class); + $rectorConfig->rule(SimplifyRegexPatternRector::class); + $rectorConfig->rule(FuncGetArgsToVariadicParamRector::class); + $rectorConfig->rule(MakeInheritedMethodVisibilitySameAsParentRector::class); + $rectorConfig->rule(SimplifyEmptyArrayCheckRector::class); + $rectorConfig->rule(NormalizeNamespaceByPSR4ComposerAutoloadRector::class); + $rectorConfig + ->ruleWithConfiguration(TypedPropertyRector::class, [ + TypedPropertyRector::INLINE_PUBLIC => false, ]); }; From 5d7ad53a702609147ed705c67fbcf6f5d49ebf6f Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 19 May 2022 13:25:44 +0000 Subject: [PATCH 2/3] Disable Infection Action --- .github/workflows/infection.yml | 72 --------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 .github/workflows/infection.yml diff --git a/.github/workflows/infection.yml b/.github/workflows/infection.yml deleted file mode 100644 index 0d39d5867..000000000 --- a/.github/workflows/infection.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Infection - -on: - pull_request: - branches: - - develop - paths: - - '**.php' - - 'composer.*' - - 'phpunit*' - - '.github/workflows/infection.yml' - push: - branches: - - develop - paths: - - '**.php' - - 'composer.*' - - 'phpunit*' - - '.github/workflows/infection.yml' - -jobs: - main: - name: Mutation Testing - runs-on: ubuntu-latest - if: "!contains(github.event.head_commit.message, '[ci skip]')" - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - tools: infection, phpunit - extensions: intl, json, mbstring, gd, xml, sqlite3 - coverage: xdebug - env: - COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Configure matchers - uses: mheap/phpunit-matcher-action@v1 - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: | - if [ -f composer.lock ]; then - composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader - else - composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader - fi - - - name: Test with PHPUnit - run: vendor/bin/phpunit --teamcity - - - name: Mutate with Infection - run: | - git fetch --depth=1 origin $GITHUB_BASE_REF - infection --threads=2 --skip-initial-tests --coverage=build/phpunit --git-diff-base=origin/$GITHUB_BASE_REF --git-diff-filter=AM --logger-github --ignore-msi-with-no-mutations From 78745028b223fb489342190073883f9f9ff45790 Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 19 May 2022 13:33:28 +0000 Subject: [PATCH 3/3] Apply static analysis fixes --- rector.php | 3 ++- src/Config/Auth.php | 4 ++-- tests/Authentication/HasAccessTokensTest.php | 1 + tests/Unit/UserTest.php | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/rector.php b/rector.php index 271e727c9..92da2f5a3 100644 --- a/rector.php +++ b/rector.php @@ -79,9 +79,10 @@ __DIR__ . '/tests', ], - // Ignore files that should not be namespaced + // Ignore files that should not be namespaced to their folder NormalizeNamespaceByPSR4ComposerAutoloadRector::class => [ __DIR__ . '/src/Helpers', + __DIR__ . '/tests/_support', ], // May load view files directly when detecting classes diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 46c08fc3f..9a710bc6c 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -8,6 +8,7 @@ use CodeIgniter\Shield\Authentication\Authenticators\AccessTokens; use CodeIgniter\Shield\Authentication\Authenticators\Session; use CodeIgniter\Shield\Authentication\Passwords\ValidatorInterface; +use CodeIgniter\Shield\Models\UserModel; class Auth extends BaseConfig { @@ -324,7 +325,6 @@ class Auth extends BaseConfig * OTHER SETTINGS * //////////////////////////////////////////////////////////////////// */ - /** * -------------------------------------------------------------------- * User Provider @@ -335,7 +335,7 @@ class Auth extends BaseConfig * You can change it as long as they adhere to the * CodeIgniter\Shield\Models\UserModel. * - * @var class-string<\CodeIgniter\Shield\Models\UserModel> + * @var class-string */ public string $userProvider = 'CodeIgniter\Shield\Models\UserModel'; diff --git a/tests/Authentication/HasAccessTokensTest.php b/tests/Authentication/HasAccessTokensTest.php index 07fab5b43..0ea8c2437 100644 --- a/tests/Authentication/HasAccessTokensTest.php +++ b/tests/Authentication/HasAccessTokensTest.php @@ -55,6 +55,7 @@ public function testAccessTokens() ['user_id' => $this->user->id, 'type' => 'access_token', 'secret' => 'secretToken2'] ); + /** @var AccessToken[] $tokens */ $tokens = $this->user->accessTokens(); $this->assertCount(2, $tokens); diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index b9469cf02..f27de075e 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -87,7 +87,7 @@ public function testLastLogin() $last = $this->user->lastLogin(); - $this->assertInstanceOf(Login::class, $last); + $this->assertInstanceOf(Login::class, $last); // @phpstan-ignore-line $this->assertSame($login->id, $last->id); $this->assertInstanceOf(Time::class, $last->date); }