Skip to content

IBX-12606: Replaced the Symfony deprecation thresholds with PHPUnit's native deprecation gate - #837

Merged
ViniTou merged 7 commits into
6.0from
phpunit-11-deprecation-gate
Sep 22, 2026
Merged

ViniTou merged 7 commits into
6.0from
phpunit-11-deprecation-gate

Conversation

@ViniTou

@ViniTou ViniTou commented Sep 17, 2026

Copy link
Copy Markdown
Contributor
Q A
🎫 Issue IBX-12606

Description:

phpunit.xml set SYMFONY_DEPRECATIONS_HELPER="max[self]=82&max[direct]=855&max[indirect]=14&verbose=0", but this is a no-op under PHPUnit ≥10: the Symfony bridge's bootstrap.php returns early when it detects the modern PHPUnit event system, and SymfonyExtension never registers a DeprecationErrorHandler. The three integration configs already carried SYMFONY_DEPRECATIONS_HELPER=disabled (one of them twice, duplicated), equally dead. composer unit was silently ignoring every deprecation regardless of threshold.

This PR replaces the dead bridge gate with PHPUnit 11's native deprecation handling on the unit suite:

  • failOnDeprecation="true" on <phpunit> — the suite now fails when an un-baselined deprecation is triggered.
  • displayDetailsOnTestsThatTriggerDeprecations="true" — prints the triggering test + message for every deprecation.
  • <source baseline="phpunit.baseline.xml" ignoreIndirectDeprecations="false" ignoreSuppressionOfDeprecations="true"><include><directory>src</directory></include></source>:
    • ignoreIndirectDeprecations="false" — a deprecation triggered entirely inside third-party code (vendor calling vendor) does not fail the build; only deprecations touched by our own src/ or tests/ code do. Measured empirically: toggling this flag made no difference on the current unit suite (no purely-indirect deprecations exist today), and was proven with a temporary synthetic probe (file outside src//tests/, so classified third-party-to-third-party) that failed the build with the flag off and passed with it on.
    • ignoreSuppressionOfDeprecations="true" — Symfony's trigger_deprecation() calls @trigger_error(E_USER_DEPRECATED); PHPUnit ignores @-silenced issues by default, so without this flag every BC-layer deprecation Ibexa ships would be invisible to the gate.
    • baseline="phpunit.baseline.xml" — the "fail on NEW deprecations only" requirement. Existing deprecations are frozen into the baseline (generated with vendor/bin/phpunit -c phpunit.xml --generate-baseline phpunit.baseline.xml) and ignored; anything not already in it fails the build.
  • Removed the dead SYMFONY_DEPRECATIONS_HELPER env line from phpunit.xml and the (duplicated) disabled env lines from phpunit-integration.xml, phpunit-integration-legacy.xml, and phpunit-integration-legacy-solr.xml (integration deprecation gating is out of scope here and stays disabled, just without the redundant lines).

Measured on tests/lib + tests/bundle/* (7544 tests):

  • Baseline (ignoreIndirectDeprecations=true, ignoreSuppressionOfDeprecations=true): 7 Deprecations (6 distinct messages), PHPUnit Deprecations: 2505 (unrelated — PHPUnit's own internal deprecations, mostly getMockForAbstractClass(), a separate topic).
  • Same but ignoreIndirectDeprecations=false: 7 — identical; no purely-indirect (third-party-calling-third-party) deprecations exist in this suite today.
  • ignoreSelfDeprecations=true (deprecation triggered by our own src/test code directly, not routed through a vendor helper): drops to 3 — the other 4 are "self" (e.g. ObjectStateGroup::$defaultLanguageCode, ObjectState::$defaultLanguageCode, ObjectStateLimitationType). Not applied in the final config — these should still gate.
  • Generated baseline (regenerated on PHP 8.4, the highest version in CI's matrix): 11 files, 17 <line> entries, 19 <issue> entries. 11 of the 19 issues are PHP-8.4-only (they don't fire under PHP 8.3): 9 are PHP-native league/flysystem "implicitly marking parameter as nullable" deprecations (UnableToDeleteFile.php:22, UnableToReadFile.php:22, UnableToRetrieveMetadata.php:27/32/37/42/47, LocalFilesystemAdapter.php:84/87, Filesystem.php:24), plus 1 new entry (tests/lib/MVC/Symfony/Security/UserWrappedTest.php:61, UserWrapped::eraseCredentials() is deprecated). Verified clean on both PHP 8.4 (19 issues were ignored by baseline, full 7544-test suite, exit 0) and PHP 8.3 (8 issues were ignored by baseline — only the pre-existing entries fire there, exit 0). A PHP 8.4 CLI's default memory_limit (128M) is too low for this suite and needs raising (e.g. -d memory_limit=4G) to avoid an unrelated OOM fatal error — not a code defect, just an environment default.

Baseline brittleness: each entry keys on (file, line, sha1-of-the-line-text, exact description string). A line-number shift anywhere above a baselined call site (an unrelated edit adding/removing lines earlier in the same file) moves the deprecation to a new line number and the entry stops matching — the deprecation reappears as "new" and fails the build until the baseline is regenerated. Same if the line's text changes without the line moving. This fails safe (a spurious "new deprecation" build failure, never a silently-swallowed one) but does mean routine refactors near a deprecated call site will occasionally require a baseline refresh.

Refreshing the baseline: vendor/bin/phpunit -c phpunit.xml --generate-baseline phpunit.baseline.xml, review the diff, commit it alongside the change that introduced the new deprecation(s).

.github/workflows/*.yml — none of the 7 workflow files reference SYMFONY_DEPRECATIONS_HELPER; nothing there needed changes.

Second commit, restored PHP notice/warning strictness (all four configs): before the PHPUnit 11 migration every config carried convertErrorsToExceptions, convertNoticesToExceptions and convertWarningsToExceptions set to true, so a PHP notice or warning inside a test failed the run. PHPUnit 10 removed those attributes and the migration dropped them; the PHPUnit 10+ equivalents failOnNotice and failOnWarning both default to false, so notices and warnings became non-failing issues. Only phpunit-integration.xml still had failOnWarning="true". This commit sets failOnWarning="true" failOnNotice="true" on phpunit.xml, phpunit-integration.xml, phpunit-integration-legacy.xml and phpunit-integration-legacy-solr.xml. Unit suite with all three gates active: 7545 tests, exit 0, 19 issues ignored by baseline. The same two attributes are rolled out to every other repo of the wave together with the deprecation gate.

Third commit, PHPUnit-native deprecation expectations: DownloadControllerTest and ContentDomainMapperTest used the bridge's ExpectDeprecationTrait::expectDeprecation(). Under PHPUnit 11 that method is inert: a probe with a deliberately wrong expected message still passed (exit 0, test flagged risky for having no assertions). Both call sites now use TestCase::expectUserDeprecationMessage(); the same probe fails (exit 1). The expected deprecation is reported to the gate as well, so phpunit.baseline.xml gained the one DownloadController entry (20 issues ignored by baseline, 7545 tests, exit 0). The bridge itself stays in require-dev: bootstrap.php and 6 test files use ClockMock, and SymfonyExtension remains registered for it.

For QA:

N/A

Documentation:

N/A

@ViniTou
ViniTou force-pushed the phpunit-11-deprecation-gate branch 2 times, most recently from b599ce9 to eb20cbe Compare September 17, 2026 16:28
Base automatically changed from phpunit-11 to 6.0 September 18, 2026 09:14
@ViniTou
ViniTou force-pushed the phpunit-11-deprecation-gate branch from eb20cbe to 2ad69a3 Compare September 18, 2026 12:43
@konradoboza
konradoboza requested a review from a team September 21, 2026 06:38
Comment thread phpunit.baseline.xml
@@ -0,0 +1,79 @@
<?xml version="1.0"?>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be in some different format than XML? Asking due to readability reasons.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, as everything in phpunit, xml only.

@bnowak bnowak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's weird, but don't we have any deprecations in integration test suites?

@ViniTou

ViniTou commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

Update: CI caught a real gap — 7c1fd5baeb's baselines were generated on local PHP 8.3, but this job's matrix only runs PHP 8.4. Three deprecations only fire on 8.4 (League\Flysystem\InMemory\InMemoryFilesystemAdapter nullable-param, and two symfony/var-exporter LazyGhostTrait/ProxyHelper::generateLazyGhost() ones — 8.4's native lazy objects make Symfony's own shim usage deprecated, which 8.3 can't trigger). Same thing the PR description already called out for the unit suite's own baseline; I just missed applying it to the integration one. Regenerated both baselines under real PHP 8.4 (via Docker) in 7d6249ace, rebased onto current 6.0, verified clean end to end.

The earlier back-and-forth in this thread about ignoreIndirectDeprecations and cross-run irreproducibility was a red herring caused by testing on the wrong PHP version locally, not the real issue. Keeping ignoreIndirectDeprecations="false" as previously agreed.

Baseline is single-file per suite, not per-PHP-version — this job's matrix is 8.4 only right now (checked backend-ci.yaml directly). If 8.3 or 8.5 gets added to the matrix later, the fix is to regenerate on that version and union the new entries into the same baseline file; a version-specific deprecation nobody's baselined yet will surface as a build failure the moment that version is added, not get silently missed.

@ViniTou
ViniTou force-pushed the phpunit-11-deprecation-gate branch from 7c1fd5b to 7d6249a Compare September 21, 2026 10:10
…ader() deprecation, triggered on MySQL/PostgreSQL but not the SQLite fixture
Comment thread phpunit-integration-legacy-solr.xml Outdated
@@ -1,17 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="bootstrap.php" processIsolation="false" beStrictAboutTestsThatDoNotTestAnything="false" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="bootstrap.php" processIsolation="false" beStrictAboutTestsThatDoNotTestAnything="false" colors="true" failOnWarning="true" failOnNotice="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get this in multiline instead?

It will be easier for readability/git operations.

@sonarqubecloud

Copy link
Copy Markdown

@ViniTou
ViniTou merged commit d62b2ea into 6.0 Sep 22, 2026
13 checks passed
@ViniTou
ViniTou deleted the phpunit-11-deprecation-gate branch September 22, 2026 07:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants