Problem/Motivation
We already decided in [another issue which I can't find right now] that 8.8.x is the last place where we'll deprecate code for removal in Drupal 9.
This means that new deprecations in 8.9.x will be removed in Drupal 10, but this raises some issues. We want modules to remove 8.x deprecations asap, and particularly in the next ~8 months in the run up to the 9.0.0 release, Drupal 10 deprecations on top of this mean extra work to get a module passing against 8.9.x/9.0.x that isn't necessary right now.
Proposed resolution
There are a handful of option each with their own drawbacks:
1. Add new deprecations in 8.9.x and 9.0.x to be removed in 10.0.0 and don't change anything else. Modules using this deprecated code will see warnings about them in test runs, phpstan reports, IDEs same as they would for deprecation messages.
Pros:
- no changes to our deprecation policy (except the version)
- Enforces that Drupal core will remove usages
- contrib doesn't start building up Drupal 9 technical debt before it's even released
Cons:
- noise for people who are just trying to do the minimum to get their modules compatible with 9.0.x
- modules that update for these deprecations won't be compatible with 8.8.x
2. Same as #1 except additionally suppress all 10.0.x deprecation messages in test runs
Pros:
- No changes in the deprecation code
- Contrib can pass against 8.9.x (and 9.0.x if we make the same change there) without fixing these deprecations
Cons:
- core test runs won't flag usages of suppressed deprecations
- deprecations will still show up in automated tools (phpstan might be adjustable to ignore them) and IDES (probably not adjustable).
3. Add the deprecations to 9.0.x as normal, but don't actually deprecate anything in 8.9.x - while adding the new code anyway.
Pros:
- Modules will be able to get clean runs of everything against 8.9.x without addressing these at all, but the new APIs will be available.
Cons:
- still warnings on 9.0.x
- potentially confusing for new developers since there will be duplicated APIs without a clear indication of which to use
- Requires two versions of patches.
4. Don't commit the patches to 8.9.x at all, leave them in 9.0.x
Pros:
- easy for modules to update to 8.9.x
Cons:
- Modules that update against 9.0.x will introduce incompatibilities with 8.9.x quicker
- divergence between 9.0.x and 8.9.x
5. Don't commit the patches to either 8.9.x or 9.0.x, hold them until 9.1.x
Pros:
- no noise or tooling changes
Cons:
- some critical or major bugs (or Drupal 9 readiness issues) will require new deprecations, what about them?
- accumulation of technical debt and RTBC/postponed issues.
6. Add the new code to 8.9.x and 9.0.x, without deprecating the old code. Post follow-ups to deprecate in 9.1.x
Pros:
- Modules will be able to get clean runs of everything against 8.9.x and 9.0.x without addressing these at all, but the new APIs will be available.
Cons:
- potentially confusing for new developers since there will be duplicated APIs without a clear indication of which to use
- Requires follow-up issues and patches against 9.1.x
7. Add the new code to 8.9.x and 9.0.x, without deprecating the old code. Deprecate immediately in 9.1.x
Pros: all the best bits of the above
Cons: more core branches to maintain than ever before in the history of Drupal
Remaining tasks
Pick one.
Comments
Comment #2
catchfwiw I think we should do either option #1 or option #2 here, but I don't have a strong preference between them.
Option #3 seems like a lot of process change and patch re-roll for not much advantage over #2, and option #4 I think we should rule out because it will cause far more problems than it solves (modules not working with 8.9.x, broken cherry-picks for bugfixes etc.).
Comment #3
catchComment #4
alexpottI think there are tradeoffs in all directions. I think potentially option 1 with a commitment to only do deprecations in 8.9.x and 9.0.x when the benefits are large.
For example I see little benefit at this point to emitting a deprecation in #3087975: Add deprecation to InfoParserDynamic::__construct() to require root path until 9.1.x or even later (other than having it done).
Comment #5
catchWell there's not much benefit, but also it will affect approximately zero modules, so there's not really any harm either.
http://grep.xnddx.ru/search?text=InfoParserDynamic&filename=
Where we're going to run into problems is if we commit dozens of deprecations that affect a handful of modules each, or a handful of deprecations that affect dozens/hundreds of modules each. But these are also likely to be the issues where there's actually a benefit to committing the patch.
One extra thing to note is that as long as we're on schedule, 8.9 and 9.0 beta will start in March, so we only really have 4-5 months of development instead of six, and also a longer run-up before those versions are released, and patches that we might want to delay until 9.1.x can start landing in March too when it's open. So in a way patches will naturally get deferred until 9.1.x due to lack of time, and the window for committing new deprecations for 8.9.x is shorter than usual too.
Comment #6
mikelutzI lean towards option 2 for the PMs sake, maybe with the caveat that when deprecating something you should post a patch with the suppression removed to prove you got them all, along with a RTBC issue similar to the vendor min max testing issues that runs with the suppression off to catch any accidental reintroduction of deprecated code.
Symfony 4 introduced a lot of deprecations that we can't fix in core until we are actually on symfony 4 that are currently suppressed. I would like to have the suppressions removed before 9.0 release, but that will likely mean having some bc layers in there triggering errors.
Comment #7
alexpottIt will affect contrib - see http://grep.xnddx.ru/search?text=InfoParser&filename= (InfoParser extends InfoParserDynamic)
Comment #8
xjmI think there's a couple missing options -- for example, don't commit any new deprecations until 9.1.x opens for development in a few months (maybe with
@todos for important deprecations now). The disadvantages of that are obvious, but it means way less noise in automated tests and static analysis tooling for the major version upgrade, no PHPStorm noise, no branch divergence, and a nice shiny and new 9.0.x. I'm still leaning toward that approach, if only for 8.9/9.0. We could potentially do something like option 2 for 9.4/10.0.Comment #9
xjmComment #10
catchComment #11
catchI've added options 5 and 6 to cover that.
Option 5 I don't think it will be possible to do that as a blanket rule, because it will end up blocking critical bugfixes and tasks which we need to get into 8.9.x/9.0.x.
Option 6 seems viable to me.
Comment #12
xjmFWIW I do think there's also some advantage in having some amount of restriction on what's committed for a few months. We've been at full-throttle new feature and API development for going on 5 years now. The criticals queue is out of control, etc. For me slowing that down a little and focusing on the stability of 8.9/9.0 for a few would be valuable. Obviously blocking major/critical bugfixes isn't in our interest though, so those would add technical debt and a task we would need to do for 9.1.x.
The cleanup task could be a single issue though, like:
Replaced with:
Edit: Fewer code snippet syntax errors.
Comment #13
catchI think something like #12 is a good option, to enable that this also means we'd do all the deprecated code usages in 8.9.x/9.0.x and only the comments change, which lessens how much technical debt we're adding.
Comment #14
mikelutzAs one of the many people involved in the gargantuan task of cleaning up after all the improperly deprecated things in the early D8 cycle, I can't say I'm a fan of doing commented out deprecation errors. Not only are @todo's and cleanup follow-ups notoriously never gotten around to, but during the time the error is commented out, it is quite possible to commit new code using the deprecated code path, that won't be caught until we go to try to uncomment the error. (I'm still suffering PTSD from format_string, and last I saw Berdir, he was curled up in the fetal position mumbling something about entity_manager)
I of course realize there are other considerations here, and 4 months of technical debt around deprecations is a far cry from 4 years. I wish we had a slightly different workflow that allowed us a master branch that we could push the final deprecation to at the same time we commit to 8.9/9.0 just to avoid all the @todos and postponed issues.
I also do agree that spending a release cycle on stability will be beneficial. Maybe trying for Symfony 5 compatibility when 9.0 is released isn't worth the disruption, maybe that should be targeted for 9.1.
Comment #15
alexpottI've made similar arguments before in discussion with @catch. The problem being that this increases the branch management workload on committers. It'd be a bit better it we used a merge workflow.
Comment #16
larowlanWith option 6 and 5, what's to stop us committing to 9.1 immediately, other than the workload of having 4 active branches (8.8, 8.9, 9.0, 9.1) and a fifth with security support (8.7)? Would that address your concerns @mikelutz
Comment #17
catchI've added that as option #7. Wondering if we can do something like hold 9.1.x until we have a handful of relatively disruptive deprecations we want to commit to make the window of that many branches slightly shorter (like open it in December or something), but it's only bringing forwards the situation we'll have in March anyway.
Comment #18
mikelutz#3074585: [Symfony 5] Replace app.root and site.path string services with container parameters is an example of a deprecation we will want to make in either 8.9 or 9.0 for removal in Drupal 10. The app.root and site.path services as strings are deprecated in Symfony 4, and while the deprecation errors are currently suppressed, it's generating a lot of them and is causing us to disable apcu during the Javascript Install test because of some conflict and bug in php. We will definitely want to have that test back using apcu and remove our use of the string services internally by 9.0-beta.
So if we go the 6 or 7 (or even 2) route, we would create the new services, stop using the old ones in 9.0, but one way or another not trigger deprecation errors on them until 9.1 (either next spring or immediately) The concern with #6 is that we could introduce new code using the old services and not catch it in a test. With #7 we could potentially catch it in a test against 9.1 assuming one gets queues, in the other ones we might not catch it until we do a followup.
There are definitely trade-offs any way we go. I'm just trying to give a concrete example we can think through.
Comment #19
xjmI marked #3073936: [policy, no patch] Policy for Drupal 10 deprecations as a duplicate of this issue.
Comment #20
catchOK we just discussed this in the committer meeting with @GaborHojtsy, @xjm, @lauriii and @alexpott.
Every option here has drawbacks:
- just adding the deprecations means noise for contrib modules, and creates tooling workload to remove it.
- commenting deprecations means we lose deprecation test coverage and have to come back to uncomment things in 9.1.x, it will also mean two versions of patches (one doing it properly to get a green result and one with the comments).
- opening 9.1.x means extra overhead cherry-picking for each commit, for every issue not just ones with new deprecations.
- moving to 9.1.x stalls progress on these patches until the branch is opened.
However, we agreed that for now, we will go with the last option. If a patch needs to add a Drupal 10 deprecation, we'll move it to 9.1.x (except critical bug fixes and critical 9.0.x tasks where we'll figure out how to handle things case by case).
We'll then keep an eye on how many issues are being moved to 9.1.x, and we can either revisit one of the other plans here, or just open the 9.1.x branch at that point if/when it becomes a real problem.
The advantage of this is we can modify it any time, whereas once we've started one of the other plans we're stuck with it. And it gets things out of limbo a bit.
Comment #21
effulgentsia commented+1 to #20 as a general policy. I'm wondering how to apply it in #3074585-46: [Symfony 5] Replace app.root and site.path string services with container parameters.
Comment #22
gábor hojtsyThis was announced in https://groups.drupal.org/node/535670, should we close the issue or keep it open for tracking / re-evaluation later?
Comment #23
catchWe now have the 9.1.x branch open. There are still some borderline issues (fixing old deprecations, deprecating things that are dangerous if they're used, whether upstream deprecations from Symfony etc. should be suppressed), but those are being dealt with case by case.