EE-282: Support Symfony 7.4 - #10
Conversation
Symfony 7 declares getConfigTreeBuilder(): TreeBuilder on ConfigurationInterface, so the untyped Configuration::getConfigTreeBuilder() is a fatal error there. A class return type parses on PHP 7.0, so the PHP requirement stays as it is. symfony/framework-bundle allows ^7.4. The bundle's code uses symfony/config, symfony/dependency-injection and symfony/http-kernel without requiring them; they are now required at the framework-bundle constraint, because framework-bundle 7.4 accepts the Symfony 8 versions of all three. The test-only symfony/yaml follows the same lines. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With Symfony's DebugClassLoader on (an application's dev environment, symfony/phpunit-bridge), Symfony 6.4 and 7.4 report two notices against this bundle: ExtensionInterface::load() "might add void as a native return type" in PayseraNormalizationExtension, and, on 7.4, that the HttpKernel Extension it extends is internal since Symfony 7.1 (deprecated in 8.1). The extension now extends Symfony\Component\DependencyInjection\Extension\Extension, the parent of the HttpKernel class, which it already used for everything (the HttpKernel class adds only the annotated-classes cache this extension never fills), and load() documents its void return the way 1.3.1 did for the bundle's build(). The native void type waits for Symfony 8, where it would also require PHP 7.1. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… install again The matrix gains Symfony 7.* on PHP 8.2 to 8.4; Symfony 7.4 needs PHP 8.2, so the older PHP lines exclude it. Composer 2.10, which setup-php installs for PHP 7.2 and later, refuses packages with security advisories, and every symfony/cache release of Symfony 3.4 and 4.4 has one, so those jobs failed at install. The step paysera/lib-api-bundle#18 added turns the blocking off for this test install only; PHP 7.0 and 7.1 get Composer 2.2, which neither blocks advisories nor knows the setting, so the step skips them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On Symfony 6.4 one of the two notices is about getConfigTreeBuilder(), which the return type removes, not the extension change; the entry now credits both. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the bundle The suite did not assert what the previous commits are for: with the HttpKernel parent put back or the @return void docblock removed, all 13 tests stayed green. The new test loads the bundle's three classes in a separate process with Symfony's DebugClassLoader enabled and fails on any deprecation notice that names them. Against the pre-change code it fails on Symfony 6.4 (load() "might add void", getConfigTreeBuilder() "might add TreeBuilder") and on 7.4 (the internal HttpKernel parent, load()); it is skipped below Symfony 4.4, where symfony/error-handler does not exist. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… step is needed - CHANGELOG: the breaking note now covers both classes (the extension's subclasses lose the HttpKernel class-cache methods too) and says why this is still a minor: neither class is in the public API the README defines. It also says that Symfony 7.4's notice about XML service definitions remains. - load() documents its $configs element type, as ExtensionInterface does. - The workflow comment names every job the advisories step is for, including Symfony 6.0 on PHP 8.0 and PHPUnit 6.5 on PHP 7.2, and the Composer version that started blocking (2.9). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On PHP 8.4, compiling Symfony 4.4's DebugClassLoader raises an "implicitly nullable parameter" notice. The test loaded that class before installing its error handler, so the notice reached the separate process's output and PHPUnit failed the test (workflow job PHP 8.4 x Symfony 4.*). The handler now goes in first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s, wording made exact - The deprecation test now asserts that the bundle's classes are not loaded before the debug class loader is enabled and that they load inside it. Without that, dropping `@preserveGlobalState disabled` let the child process re-include classes the parent had loaded, and the test passed with the fix reverted. - The test's closures are typed. - load()'s `$configs` may hold null entries: on Symfony 3.4 and 4.4 a `paysera_normalization: ~` block arrives as null. - The workflow comment no longer lists four packages where more are affected, and says the setting it writes exists from Composer 2.10. - CHANGELOG: the notices removed are reported from Symfony 5.4 on, not only on 6.4 and 7.4; the class-cache methods are named per Symfony line, and an override of their getter is ignored as well. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Following your note on lib-dependency-injection#8, every job here also runs with lowest dependencies where that combination can run (dabe1ef): 55 jobs, the 38 highest plus 17 lowest. I ran all 38 lowest combinations locally with the workflow's own commands. 17 pass. The other 21 fail inside
Unlike #8, this workflow turns Composer's advisory blocking off, so its lowest jobs install the real floors. One consequence: the Symfony 7.4.0 floor isn't tested at lowest. Raising the floors ( |
The matrix gains dependency-versions lowest next to highest, and the single PHP 7.0 lowest entry became one of those jobs. Six exclude entries take out the 21 lowest combinations whose oldest allowed dependencies cannot run on PHP 8: Symfony 3.4.26 and 4.4.9 on PHP 8.0 and later (libxml deprecation), lib-object-wrapper 0.3.0 on PHP 8.1 and later (ArrayAccess return types), and PHPUnit 9.3.0 on PHP 8.4. The 17 lowest jobs that remain pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Before your review I applied here the points you raised on lib-lock-bundle#13, lib-pagination#18, lib-serializer#14 and lib-dependency-injection#8 (b6f8902, aabd352):
CI: 70 of 70 jobs pass, 17 tests each (https://github.com/paysera/lib-normalization-bundle/actions/runs/36607653494). The description is updated with the details. |
mSprunskas
left a comment
There was a problem hiding this comment.
The deprecation test hides warnings and notices while the bundle classes load
- Location: tests/Functional/FunctionalDeprecationNoticesTest.php:23-29
- Problem: The error handler records only E_USER_DEPRECATED and E_DEPRECATED. It returns true for all error types. It has no $error_levels mask, so it also catches E_WARNING, E_NOTICE and E_USER_WARNING, and then discards
them.
- Impact: phpunit.xml.dist sets convertWarningsToExceptions="true" and convertNoticesToExceptions="true". While DebugClassLoader loads the three bundle classes, this handler replaces the PHPUnit handler. If a class load
causes a warning or a notice, the test passes and gives no signal. The effect is limited to this test.
- Fix: Return false for error types that are not deprecations, so that the error goes to the standard handler. Another option is to give set_error_handler() the mask E_DEPRECATED | E_USER_DEPRECATED.
The test's error handler took every error type and returned true, so a warning or a notice raised while the bundle's classes load was discarded and the test passed. It now handles E_USER_DEPRECATED and E_DEPRECATED only. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Fixed in 1df96f0: the handler now takes only I checked it by raising an CI: 70 of 70 jobs pass, 17 tests each (https://github.com/paysera/lib-normalization-bundle/actions/runs/36686126909). |
Summary
This lets the bundle install and work on Symfony 7.4. It also removes the deprecation notices Symfony 5.4 and later report for the bundle's classes, and the one Symfony 7.4 reports for its XML service files. The workflow step that gets the Symfony 3 and 4 jobs installing again came in separately through #11, which is merged. I propose releasing it as 1.4.0. It needed paysera/lib-dependency-injection 1.5.0 (paysera/lib-dependency-injection#8), because this bundle requires that library and its earlier versions stop at Symfony 6. 1.5.0 is now released, so I have taken this out of draft.
Why
symfony/framework-bundlestops at 6.x, so no Symfony 7 application can install the bundle.ConfigurationInterfacedeclaresgetConfigTreeBuilder(): TreeBuilder, andConfigurationoverrides it untyped.symfony/config,symfony/dependency-injectionandsymfony/http-kernelwithout requiring them.symfony/framework-bundle7.4 accepts their 8.x versions, so on PHP 8.4 Composer takeshttp-kernel8.0.load()andgetConfigTreeBuilder()"might add a native return type", and the parentHttpKernel\DependencyInjection\Extensionis internal since 7.1.Changes
composer.json:symfony/framework-bundlegains^7.4and moves torequire-dev: nothing insrc/uses it, only the test application.symfony/config,symfony/dependency-injectionandsymfony/http-kernel, which the code uses, are required at the same versions.paysera/lib-normalizationstarts at 1.3.1. In earlier releasesDateTimeNormalizerfails on PHP 8.2 and later, wheredate_get_last_errors()returnsfalse.symfony/yamlgains^6.0|^7.4. Devphpunit/phpunit9 starts at 9.6.33: 9.6.21 is the first to handle PHP 8.4'sE_STRICTdeprecation, and 9.6.33 the first outside CVE-2026-24765.^7.0 || ^8.0.Configuration::getConfigTreeBuilder(): TreeBuilder. A class return type parses on PHP 7.0.DependencyInjection\Extension\Extension, the parent of the HttpKernel class.load()gets a@return voiddocblock, as 1.3.1 did forbuild().Resources/config/services.xmlandResources/config/services/date_time_normalizer.xml, which are removed, as on EE-288: Add Symfony 7.4 support lib-lock-bundle#13. Their ids, classes, arguments, factory, lazy flags, tags and aliases are unchanged: they compare identical to the XML-loaded ones on Symfony 3.4, 4.4, 6.4 and 7.4. A new test pins whatload()registers, with and without the date_time normalizers, and another checks that loading raises no deprecation.loader is enabled.
and one that reached the child process's output would fail the test whatever it said.
E_DEPRECATED | E_USER_DEPRECATED), so a warning or a notice raisedwhile the classes load goes to PHP's standard handler, and PHPUnit fails the test on it.
7.*on PHP 8.2–8.4. The advisories step went in through EE-282: Let the Symfony 3 and 4 jobs install with current Composer #11.lib-normalization1.3.1 fixes the one real failure. PHP 7.0 with Symfony 4, 5 and 6 is now excluded: those versions need PHP 7.1.3 or later, and because Flex does not install on PHP 7.0, those jobs were running Symfony 3.4.CHANGELOG.mdentry.Backward compatibility
getConfigTreeBuilder()override needs: TreeBuilder. It fails on Symfony 7 anyway;paysera/lib-normalization1.3.1 is the new minimum. An application locked below it updates the two together (composer update paysera/lib-normalization-bundle -w). 26 of our 56 applications that use the bundle are below 1.3.1.symfony/framework-bundle. Every Symfony application requires it itself; none of our 56 gets it only through this bundle.Test plan
Configuration's fallback for Symfony below 4.2. Against 1.3.1, the debug-class-loader test fails on 5.4, 6.0 and 6.4, and 7.4 is a fatal error. Against the XML version, the no-deprecation test fails on 7.4 with two notices, one per file.lib-normalization1.3.1.🤖 Generated with Claude Code