From e0567c6815aa5a4ce875f7134e5cf2f91a76de14 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Tue, 11 Aug 2026 09:00:31 +0000 Subject: [PATCH] fix CI pipeline workflows, resolve PHP 8.5 test deprecations, and upgrade PHPUnit schema --- .github/workflows/php.yml | 26 ++++++++++++++++--- composer.json | 4 ++- phpstan-baseline.neon | 16 ------------ phpunit.xml | 2 +- tests/src/Cas/Protocol/SamlValidateTest.php | 1 - tests/src/Controller/LoginControllerTest.php | 10 +++---- .../src/Ticket/FileSystemTicketStoreTest.php | 2 -- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index a55623af..9698d9c0 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -15,21 +15,39 @@ on: # yamllint disable-line rule:truthy jobs: phplinter: name: 'PHP-Linter' + runs-on: ubuntu-latest strategy: fail-fast: false matrix: php-version: ['8.3', '8.4', '8.5'] - uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_phplinter.yml@v2.0.1 - with: - php-version: ${{ matrix.php-version }} + steps: + - name: Checkout Code + uses: actions/checkout@v7 + + - name: Setup PHP runtime + uses: shivammathur/setup-php@v2 + with: + tools: phive + php-version: ${{ matrix.php-version }} + coverage: "none" + extensions: :redis + + - name: Install overtrue/phplint (latest) + run: phive install overtrue/phplint --force-accept-unsigned --target ./bin + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Lint PHP files + run: ./bin/phplint --no-cache --no-progress -v linter: name: 'Linter' strategy: fail-fast: false - uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_linter.yml@v2.0.1 + uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_linter.yml@v1.11.6 + secrets: inherit with: enable_eslinter: true enable_jsonlinter: true diff --git a/composer.json b/composer.json index adc4df32..251837f1 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,8 @@ "simplesamlphp/saml11": "~2.3" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "~1.11" + "simplesamlphp/simplesamlphp-test-framework": "~1.11", + "php-parallel-lint/php-parallel-lint": "^1.4" }, "support": { "issues": "https://github.com/simplesamlphp/simplesamlphp-module-casserver/issues", @@ -57,6 +58,7 @@ }, "scripts": { "verify": [ + "vendor/bin/parallel-lint --exclude vendor .", "vendor/bin/phpcs -p", "vendor/bin/phpunit --no-coverage --testdox", "vendor/bin/phpstan --memory-limit=256M analyze -c phpstan.neon", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 321f5977..05626276 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -276,17 +276,6 @@ parameters: count: 1 path: src/Cas/TicketValidator.php - - - message: '#^Property SimpleSAML\\Module\\casserver\\Controller\\Cas10Controller\:\:\$sspConfig is never read, only written\.$#' - identifier: property.onlyWritten - count: 1 - path: src/Controller/Cas10Controller.php - - - - message: '#^Property SimpleSAML\\Module\\casserver\\Controller\\Cas20Controller\:\:\$sspConfig is never read, only written\.$#' - identifier: property.onlyWritten - count: 1 - path: src/Controller/Cas20Controller.php - message: '#^Call to an undefined method SimpleSAML\\XML\\SerializableElementInterface\:\:getXML\(\)\.$#' @@ -294,11 +283,6 @@ parameters: count: 1 path: src/Controller/Cas30Controller.php - - - message: '#^Property SimpleSAML\\Module\\casserver\\Controller\\Cas30Controller\:\:\$sspConfig is never read, only written\.$#' - identifier: property.onlyWritten - count: 1 - path: src/Controller/Cas30Controller.php - message: '#^Cannot cast array to string\.$#' diff --git a/phpunit.xml b/phpunit.xml index 60deba46..8e3a6663 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -2,7 +2,7 @@ diff --git a/tests/src/Cas/Protocol/SamlValidateTest.php b/tests/src/Cas/Protocol/SamlValidateTest.php index 201fc423..5ea52653 100644 --- a/tests/src/Cas/Protocol/SamlValidateTest.php +++ b/tests/src/Cas/Protocol/SamlValidateTest.php @@ -28,7 +28,6 @@ public function testSamlValidateXmlGeneration(): void $p = xml_parser_create(); xml_parse_into_struct($p, \strval($xmlString), $vals, $index); - xml_parser_free($p); $this->assertEquals( $serviceUrl, diff --git a/tests/src/Controller/LoginControllerTest.php b/tests/src/Controller/LoginControllerTest.php index a0eafb2f..e9eedc19 100644 --- a/tests/src/Controller/LoginControllerTest.php +++ b/tests/src/Controller/LoginControllerTest.php @@ -342,7 +342,7 @@ public function testValidServiceUrl(string $serviceParam, string $redirectURL, b $this->authSimpleMock->expects($this->once())->method('getAuthDataArray')->willReturn($state); $controllerMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->authSimpleMock->expects($this->any())->method('isAuthenticated')->willReturn(true); + $this->authSimpleMock->expects($this->atLeastOnce())->method('isAuthenticated')->willReturn(true); $queryParameters = [$serviceParam => 'https://example.com/ssp/module.php/cas/linkback.php']; $loginRequest = Request::create( uri: Module::getModuleURL('casserver/login'), @@ -396,7 +396,7 @@ public function testAuthprocReceivesServiceAndIdpEntityIds(): void $sessionId = session_create_id(); $this->sessionMock->expects($this->exactly(2))->method('getSessionId')->willReturn($sessionId); $controllerMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->authSimpleMock->expects($this->any())->method('isAuthenticated')->willReturn(true); + $this->authSimpleMock->expects($this->atLeastOnce())->method('isAuthenticated')->willReturn(true); $this->authSimpleMock->expects($this->once())->method('getAuthData')->with('Expire')->willReturn(9999999999); $this->authSimpleMock->expects($this->once())->method('getAuthDataArray')->willReturn($state); @@ -451,7 +451,7 @@ public function testResumedAuthprocStateRejectsDifferentService(): void $sessionId = session_create_id(); $this->sessionMock->expects($this->exactly(2))->method('getSessionId')->willReturn($sessionId); $controllerMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->authSimpleMock->expects($this->any())->method('isAuthenticated')->willReturn(true); + $this->authSimpleMock->expects($this->atLeastOnce())->method('isAuthenticated')->willReturn(true); $this->authSimpleMock->expects($this->once())->method('getAuthData')->with('Expire')->willReturn(9999999999); // The user comes back from the authproc filter having swapped in a different legal service. @@ -497,7 +497,7 @@ public function testResumedAuthprocStateAcceptsMatchingService(): void $sessionId = session_create_id(); $this->sessionMock->expects($this->exactly(2))->method('getSessionId')->willReturn($sessionId); $controllerMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->authSimpleMock->expects($this->any())->method('isAuthenticated')->willReturn(true); + $this->authSimpleMock->expects($this->atLeastOnce())->method('isAuthenticated')->willReturn(true); $this->authSimpleMock->expects($this->once())->method('getAuthData')->with('Expire')->willReturn(9999999999); $queryParameters = [ @@ -735,7 +735,7 @@ public function testAuthenticatedPostSubmitsViaPostWithTicket(): void $this->sessionMock->expects($this->exactly(2))->method('getSessionId')->willReturn($sessionId); // Simulate authenticated state and required auth data - $this->authSimpleMock->expects($this->any())->method('isAuthenticated')->willReturn(true); + $this->authSimpleMock->expects($this->atLeastOnce())->method('isAuthenticated')->willReturn(true); $this->authSimpleMock->expects($this->once())->method('getAuthData')->with('Expire')->willReturn(9999999999); $this->authSimpleMock->expects($this->once())->method('getAuthDataArray')->willReturn([ 'Attributes' => [ diff --git a/tests/src/Ticket/FileSystemTicketStoreTest.php b/tests/src/Ticket/FileSystemTicketStoreTest.php index a4ccd8e5..cd657a97 100644 --- a/tests/src/Ticket/FileSystemTicketStoreTest.php +++ b/tests/src/Ticket/FileSystemTicketStoreTest.php @@ -96,7 +96,6 @@ public function testValidateTicketPathThrowsWhenTicketStorageDirectoryIsNotAcces $store = $this->createStore($this->ticketDir); $rp = new \ReflectionProperty($store, 'pathToTicketDirectory'); - $rp->setAccessible(true); $rp->setValue($store, $this->ticketDir . DIRECTORY_SEPARATOR . 'does-not-exist-' . bin2hex(random_bytes(4))); $this->expectException(Exception::class); @@ -135,7 +134,6 @@ private function createStore(string $ticketDir): FileSystemTicketStore private function invokeValidateTicketPath(FileSystemTicketStore $store, string $ticketId): string { $rm = new \ReflectionMethod($store, 'validateTicketPath'); - $rm->setAccessible(true); $result = $rm->invoke($store, $ticketId); self::assertIsString($result);