The next-major lane has never run to completion, so nothing is known about this project on Drupal 12. The jobs are opted in and manual; played by hand they die in the composer step, before a single file is analyzed, and the phpstan and phpunit jobs behind it stay skipped. This makes it green, and reports what it found on the way.
Dependency resolution came first, and the fault was in this project's own CI file. _LENIENT_ALLOW_LIST named its projects with a drupal/ prefix, and the templates' own expand_composer_json.php prepends that prefix itself: every entry became drupal/drupal/webform, matched no package, and the lenient plugin printed the list back while relaxing nothing. Bare names fix it. Two of the entries have to be there transitively, which is not guessable from this project's own dependencies: easy_email pulls jquery_ui_resizable, which pulls jquery_ui, and both cap core at ^11. With that, core dev-main resolves.
Two projects left the list rather than joining it. orchestra and kessai declare ^11.3 || ^12 now and need no leniency. domain reaches Drupal 12 through its 4.x branch, so composer.json admits ^4.0 and its six test classes keep running on 12 instead of being skipped; 4.x carries no tagged release, so prefer-stable keeps every other lane on 3.x.
The declaration is load-bearing, not a claim to make afterwards. Holding core_version_requirement at ^11.3 until the lane went green cannot work: Drupal's own module installer reads it, so every test that installs a module through ModuleInstaller fails with "incompatible with this version of Drupal core" no matter what composer resolved. All 42 info.yml files and composer.json now say ^11.3 || ^12.
One test installed a table Drupal 12 deletes. installSchema('system', ['sequences']) throws on core 12, which ships system_update_12000() to drop that table and no longer defines its schema. Nothing here ever called nextId(), the only API it backed, and that method is gone from core 12 as well, so the line goes rather than being worked around.
webform is the one dependency that needs its tests standing down. Installing a project leniently only gets it past composer and the module installer; WebformHandlerManager::getGroupedDefinitions() is not compatible with the core 12 CategorizingPluginManagerInterface, so a test that boots it cannot run there. Six classes skip themselves through DependencyWithoutDrupal12Trait, which names the project and the reason: the two in yoyaku_webform, and four in yoyaku_orchestra_example, which reaches webform through its dependency on yoyaku_webform. grep skipWithoutDrupal12() lists them, and the entry comes out of the trait and the allow list together once webform declares Drupal 12. The pattern, the trait and the SYMFONY_DEPRECATIONS_HELPER handling below are all as the orchestra project settled them; the trait is copied rather than shared, because a test standing down over webform must not need orchestra installed to know how.
Core main runs --fail-on-deprecation unconditionally, and the templates set SYMFONY_DEPRECATIONS_HELPER, which core 11.5 deprecated using at all: one deprecation would then fail every test class with no assertion failure behind it. The next-major phpunit job unsets it and appends core's own ignore patterns, which is what core's CI does.
The lane then reported 37 deprecations, all of them core's DebugClassLoader asking an override to declare the return type core intends to add. Twenty-two came from one place, InterfaceLanguageUrlTrait::toUrl(), which every entity uses; the rest are three label(), five buildEntityQuery(), two create(), one createInstance() and one applyDefaultValue(). validateForm() cannot take one at all: core 12 declares it returning the entity, core 11's own implementation returns nothing, and a nullable type would widen what core 12 declares, which PHP refuses. Those two take the other remedy the deprecation offers, an explicit @return.
The last one was ours, and it is fixed here rather than deferred. Six startTransaction() sites committed by letting the Transaction go out of scope, deprecated in 11.5 and removed in drupal:13.0.0. They say commitOrRelease() now, which exists as far back as the 11.3 floor this module supports. Four already marked that commit point with an unset() and a comment about it, so those are the same statement said out loud; withRowLock() had no single commit point, since two returns inside its try relied on the variable's lifetime, and each commits now, the callback's after the callback so its writes stay inside the lock. Verified on MySQL as well as SQLite, because SQLite's driver drops FOR UPDATE and a green run there says nothing about this code.
What is left in .deprecation-ignore.txt is one line naming somebody else's class: the token module has not declared the return type core will add to Token::getInfo(), and every test that renders a resource form reaches it. A deprecation naming this project belongs fixed, which is why none is listed there.
PHPUnit 12 came with the lane. It leaves no mock without an expectation, so the stubs that only stand in are built with createStub(), and $this->any(), deprecated there, gives way to atLeastOnce(). The load scripts read $_SERVER['argv'] as well, since $argv exists only where register_argc_argv is on.
Three of the queries core 12 appeared to add were a missing module, not a regression. The testing profile brings dynamic_page_cache along on core 11 and does not on core 12, so the page under measurement was rebuilt per request and its availability recomputed. Both performance tests name it among their modules, and the same figures then hold on both cores.
The asset counts do differ, and both figures are asserted rather than tolerated. Core 12 groups its aggregates by library set and by category rather than into one bundle, and serves once.min.js on its own, so the same page arrives as four scripts and two stylesheets where core 11 sent one of each. A ceiling loose enough for both cores is the same as not asserting the counts at all, so each core is held to what it actually does and a page that grows an aggregate still fails on the core it grew on. The byte counts differ by well under the tolerance assertMetrics() already allows for them, so one figure covers both. One real difference is left: the click that puts a place in the basket costs one query fewer on core 12, and that too is stated per core.
Both lanes are green. Every job, including the two next-major phpunit jobs that run the whole suite against core dev-main, where the two performance classes pass rather than skip.
AI-Generated: Yes (Claude Code was used to diagnose the lane, write the changes and draft this summary. I reviewed all of it before posting.)
Issue fork yoyaku-3618644
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mably commentedComment #4
mably commentedComment #5
mably commentedComment #6
mably commentedComment #8
mably commented