Problem/Motivation
Drupal 9 requires Guzzle 6. Guzzle 6 now is in security support only. In particular, they are not adding compliance with PHP 8.1 to Guzzle 6, which creates issues for Drupal 9's own PHP 8.1 compatibility.
Guzzle 7 includes breaking changes from Guzzle 6, so we should not force sites to update to Guzzle 7 until the next major release (D10). However, we could also allow sites that want to use Guzzle 7 and PHP 8.1 to do so.
Even though we've managed to make Drupal 9 not trigger any deprecations from Guzzle 6 or skip some, there are other deprecations that Guzzle 6 will trigger when it's used by contrib projects. Such deprecations are not user deprecations but they are language level deprecations. For example:
Return type of GuzzleHttp\Command\Command::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice
Sites exposing this error cannot update to PHP 8.1, so they cannot prepare for Drupal 10.
Proposed resolution
- Consider changing our Guzzle constraint to:
"guzzlehttp/guzzle": "^6.5.2 || ^7.4.1" -
Keep
core-recommendedand thecomposer.lockfor tarballs pinned to the Guzzle 6 version.
Ensure HEAD remains compatible with Guzzle 7 with #3104353: Upgrade to Guzzle 7.
Remaining tasks
User interface changes
N/A
API changes
Not in core itself.
Data model changes
N/A
Release notes snippet
Sites are able to install Guzzle 7 due to a widening of Drupal core's composer constraints. This allows for more complete PHP 8.1 support.
| Comment | File | Size | Author |
|---|---|---|---|
| #86 | suppress-deprecation-using-php-8.patch | 510 bytes | gabesullice |
Issue fork drupal-3225966
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:
- 3225966-constraint-only
changes, plain diff MR !2275
- 3225966-guzzle7
changes, plain diff MR !1899
Comments
Comment #2
xjmComment #3
xjmComment #4
alexpottIf we going to do this to fix PHP 8.1 then we'd need to enable some way of updating to Guzzle 7 while testing on PHP 8.1. Also this will be the first time the tarball won't be compatible with all supported versions of PHP so we going to need to do something about that. Also for composer users core-recommend won't be fully compatible with PHP 8.1 either. Perhaps we should return to https://github.com/guzzle/guzzle/pull/2918 - maybe trying again with the point about if something is security supported then being fully compatible with all supported PHP versions. This might then mean that they make Guzzle 6 incompatible with PHP 8.1 which means we'll need to do something to make core-recommend installable on PHP 8.1.... I think this is all going to turn out to be very tricky. The lock file and core-recommended are going to get in the way.
OTOH, Guzzle 6 is not broken by PHP 8.1 - it emits lots of E_DEPRECATED so could consider making such deprecations skippable for the purposes of testing. And then we can proceed here with the plan in issue summary for people that want to use Guzzle 7. If this is what we do we'll have to hope Guzzle 6 is not marked as incompatible with PHP 8.1.
Comment #5
xjmWe have code in D8 that updates to PHPUnit 7 if the PHP version is greater than PHP 7.0, so I assumed we could do something similar. This would be the first time we allow two major versions for production deps, but we've had strong reason to want to do so in the past for e.g. Twig, Symfony, etc. so it's potentially worth solving the general problem space so we can address other dependency major version stuff when it comes up.
That said, skipping the deprecations is probably the simplest and least potentially disruptive solution. We could probably even make it conditionally skip the deprecations depending on whether they're being triggered in Guzzle or not. The issue with that though is that when PHP 8.2 comes out in 2022, D9 will be actually broken on that PHP version, even though it should be supported for another full year after that. Maybe that's okay -- Drupal 8.9 does not support PHP 8.0 either now, and D10 will be available by then 🤞 for people who do use PHP 8.2.
Comment #6
longwave> The issue with that though is that when PHP 8.2 comes out in 2022, D9 will be actually broken on that PHP version
Why do you think this? As far as I can see, PHP will be following semver and the new deprecations introduced in PHP 8.1 will not become hard failures until PHP 9, which has no known release date yet. For reference please see the examples at https://wiki.php.net/rfc/internal_method_return_types which explicitly mention PHP 9.
Comment #7
xjmOh! Thanks @longwave. (I had made wrong assumptions about why new PHP versions remain so disruptive.) So I guess it is probably fine to go the "silence deprecations" route if we can do so in a way that detects whether the deprecation was triggered by Guzzle.
Comment #8
xjmComment #9
xjmComment #13
alexpottI think we should consider doing this. Even though we've managed to make Drupal 9 not trigger any deprecations from Guzzle 6 or skip some - there are other deprecations that Guzzle 6 will trigger when it's used by contrib projects. For example:
It's hard to skip these messages because they are not user deprecations but they are language level deprecations.
Comment #14
claudiu.cristea@alexpott, true, I'm hitting exactly that error in one of our projects at European Commission while trying to run on PHP 8.1 (and prepare for D10)
Comment #15
claudiu.cristea@alexpott, ref #4
Seems that this is not doable from Drupal core code but needs a pipeline change (?)
Not sure I get this.
Comment #16
claudiu.cristeaI've temporary updated
composer.lockjust to see the tests on PHP 8.1Comment #17
claudiu.cristeaWe should decide what to do with the tarball & core-recommend (see #4)
Comment #18
claudiu.cristeaMore IS updates.
Comment #19
claudiu.cristeaTagging with
PHP 8.1Comment #20
claudiu.cristeaFixing title
Comment #21
xjmThis still has the problem that we have no min-max testing for core. Until we do I don't see how we can support two major versions of anything.
Comment #22
claudiu.cristea@xjm but this MR allows tests with both Guzzle 6 and 7. Keeping the constraint to only allow Guzzle 6 effectively blocks many sites to run on PHP 8.1 and, as an effect, they cannot prepare for Drupal 10
Comment #23
xjmIt tests Guzzle 7 on PHP 8.1, but it does not test Guzzle 7 on other PHP versions. So we could easily regress Guzzle 7 support on PHP 8.0 or whatever as it stands. Or we could further regress Guzzle 6 support on PHP 8.1. We need min/max testing.
Comment #24
xjmJust fixing unclosed markup in the IS.
Comment #25
xjmI think the tarballs will need to include Guzzle 6 regardless. (Aside: We should really start deprecating tarballs.)
Is there a way
core-recommendedcould be conditional based on the platform PHP version? (We still need min/max testing, which would also let us deprecatecore-recommendedand solve that problem too.)Comment #26
claudiu.cristeaShould we mark this as Critical?
Comment #27
xjmYeah, let's. I'd consider solving this somehow at least a should-have for tagging 10.0.0-beta1 because of its impact on the D9 to D10 upgrade path.
Comment #28
xjmComment #29
catchSo this is true but it seems most likely that Guzzle 6 or 7 regressions on the respective PHP versions will be due to changes in either PHP or Guzzle, which for Guzzle 6 won't be fixed, and for Guzzle 7 it's probably better than it not being possible to use it with 9.4 at all. Without min/max testing, it seems the least worst option (vs. forcing everyone onto guzzle 7 or keeping everyone stuck on guzzle 6).
Core recommended I can't think of anything that doesn't require min/max testing but it would be worth an explicit follow-up.
Comment #30
xjmComment #31
xjmI started to tag this for a followup for
core-recommended, but then I reflected that this MR is highly likely to create unresolvable update conflicts oncore-recommendedfor PHP 8.1. Trying to think of how to test that manually without a core release... local path repository maybe?Comment #32
xjmNM on #31, the current MR is only forcing Guzzle 7 on PHP 8.1 for Drupal CI.
So this still means that all
core-recommendedsites will get Guzzle 6, even on PHP 8.1, and thereforecore-recommendedon PHP 8.1 is no longer receiving real test coverage with the change in this MR, substantively undercutting the entire purpose ofcore-recommended. (Edit: and tarballs.)Comment #33
xjmOn re-read, I am not sure how this is true:
Everything above says it is only deprecation notices for theoretical contrib. I am not sure why we would break the contract of
core-recommendedinstead of just having contrib introduce their own forward-compatibility fixes.Comment #34
berdir> Everything above says it is only deprecation notices for theoretical contrib
Yes, but it's non-suppressed PHP deprecation notices, which by default fail tests and are AFAIK also logged?
I'm not sure I have an opinion on this issue, it's similar to discussions we had around allowing newer twig/symfony major versions. I see the problems with both options.
As for core-recommends, I'm not sure how much work it would be to have a drupal/core-recommends-81 package, I'm assuming not trivial? That said, using of core-recommends is optional (we don't use it atm), so *if* we'd *not* use a newer guzzle for testing then it would kind of make sense to say that drupal-composer is locked to the older version, but you can use drupal/core or use a version alias? Of course the first would result in those that already use drupal/core to switch.
An option could be to add guzzle 6 explicitly to https://github.com/drupal/recommended-project/blob/9.4.x/composer.json (would only help new projects) and a change record/release note that tells existing sites to add that requirement to their projects if they experience problems with guzzle 7?
Comment #35
xjmThanks @Berdir. A separate metapackage is an interesting idea and actually I don't think it'd be that much work from the core perspective; basically some copy-and-paste and maybe some 1-3 additions to callers. I can't speak to the infra side of the implementation, but my best guess is that it would be fairly easy there as well since it's also just repeating whatever it already does for the currrent metapackage.
However, making Guzzle a top-level dependency of
core-recommendedsounds even simpler and totally legit from an architecture perspective. Maybe we need to consider potential drawbacks but I can't think of any off the top of my head.We still need test coverage, though. I keep thinking about hacking core's
drupalci.ymlto just run the test suites twice on PHP 8.1 (one for the Guzzle 6 pinned version and one for the Guzzle 7 update). Like PHP 8.1 is fast enough that test runs are down to like 40 min with it, so doubling that is 80 min, so maybe it'd finish before the timeout? 🙄Or we could just ask the DA for help. Even if we could just get a hardcoded daily job that runs the Guzzle 6/PHP 8.1 version of the tests on MySQL, that would mitigate my concern. (But we still need min-max testing.)
Comment #36
xjmIt might be helpful to link the contrib project(s) that give the deprecation error in the IS (or, even better, those contrib projects' bug reports for this issue), so that we could investigate less disruptive workarounds.
Restoring original scope because it's problematic for this issue to go forward as-is.
Comment #37
neclimdulJust this issue I was looking for. Thanks for working on this.
Ran into a contrib use case trying to use upgrade_status in my local dev environment and wanted to document. Since we emit errors in dev environments, this deprecation is breaking json responses when trying to run a scan.
This may not be a critical use case but it does make creating a bullet proof environment for testing upgrades a bit harder since PHP 8.1 isn't fully supported here.
Comment #38
neclimdulI posted a possible work around for upgrade_status but I think its still worth considering loosening. Core isn't the only thing using guzzle, I also have internal libraries using it, marketing libraries that use it, etc. It would be much easier to be testing all of these things at once on Guzzle 7 and PHP 8.1 in 9.4 before upgrading.
Comment #39
MixologicWe have added 4 new environments to drupalci that run a `composer update --with-all-dependencies` after it installs instead of using the lock file. We can adjust the command if necessary, but thats what we've got right now.
The names in the environments list are using mysql 5.7, php 7.3/7.4/8.0 and 8.1 and have the term "updated deps".
Comment #41
xjmThanks @Mixologic!
There are a bunch of things in HEAD that are not working with the environments in HEAD: https://dispatcher.drupalci.org/job/drupal8_core_regression_tests/54582/
(That's without any changes from this issue).
So I think we need one or more blocking issues to either address those fails if they have bad expectations, or make sure the update isn't doing something we don't expect.
Meanwhile, I added an MR we can use for this once we've resolved the blocking failures.
Comment #42
MixologicI think these are probably failing because it upgraded phpunit along with everything else.
This error probably gives us the proper clue:
Im not sure what I should be upgrading, or what it is we want to ensure works, exactly.. is it *just* guzzle? if so I can reduce the breadth of the update.
Comment #43
effulgentsia commentedI think we should only exclude PHPUnit from the
composer update, because that's handled separately bydrupal-phpunit-upgradeanyway. So I think that would mean something like:composer update --with-all-dependencies --with phpunit/phpunit:^8? However, that^8would need to be different for Drupal 10 than for Drupal 9; is there a way to do it without having to hard-code that (e.g., read it from the root composer.json)?Comment #44
Mixologic--with phpunit/phpunit:8^doesnt seem to work, but I think theres a better option. Going to try--no-devwhich will not upgrade our dev dependencies.Comment #46
MixologicTurns out that
--no-devreally just means "Upgrade the dev dependencies, but dont install them" so that didnt work either.ButI figured out some nice hackery sprinkles to put on top of the hacky ice cream cone to make this work.
composer update --with-all-dependencies --with phpunit/phpunit:$(composer show -i |grep phpunit\/phpunit |awk '{print $2}')This will upgrade everything, except keep phpunit/phpunit in whatever version it was in before. As a bonus it doesnt actually change anything regarding phpunit, so the upgradephpunit script that runs on php8.1 still works.
Theres two jobs running now, and tests are happening.
Comment #48
xjmSweet! The jobs pass now:
https://www.drupal.org/pift-ci-job/2384902
Here's a segment from the console output:
It works! So this is unblocked now. I closed the old MR -- it won't do the trick because we do still need min testing.
We'll set these jobs up to run daily, so we'll know when Guzzle 7 regresses with any of our supported PHP versions and dependencies.
I made the MR so I can't RTBC this, but we could use review/+1 from someone else.
Comment #49
claudiu.cristeaNice. Maybe still needs a CR to let projects know that they can update Guzzle?
Comment #50
claudiu.cristeaSorry, there’s already a CR
Comment #51
neclimdulHeck yeah. I was so confused as to what was going on but glad its sorted out XD.
+1 to RTBC, looks right and sounds like we've got a way to test it now.
Comment #52
xjmTagging "Needs followup" for solutions or mitigations for core-recomemnded and for tarballs.
Comment #53
claudiu.cristea@xjm. as projects are on 9.3 and will update soon on 9.4 wouldn't be OK to merge this in 9.4.x, or even 9.3.x? The reason is that sites should make the conversion to PHP 8.1 and shouldn't wait for 9.5.0 for this
Comment #55
catchCommitted/pushed to 9.5.x and 9.4.x, thanks!
@claudiu.cristea the intention with this one has always been to get it into 9.4.x (or 9.3.x if it had been ready by 9.3 beta). It's late enough in the 9.3 cycle that I reckon anyone upgrading to 8.1 and blocked on this would just start testing with 9.4 at this point in a dev branch or wait a couple more weeks.
Comment #56
claudiu.cristeaYay
Comment #57
claudiu.cristeaOh, actually it’s 9.4
Comment #58
claudiu.cristea@catch, doesn't seem to be committed in 9.4.x https://git.drupalcode.org/project/drupal/-/blob/9.4.x/core/composer.json
Comment #60
catchThanks, pushed failed. Did it again.
Comment #61
tedbow@xjm asked me to create the 2 follow ups
#3281666: Tarball sites:will use Guzzle 6 which has deprecation warnings in PHP 8.1
#3281667: Come up with a way to allow core-recommended (and tarballs?) to install Guzzle 7 for PHP 8.1 compatibility and Laminas-feed 2.19 for PHP 8.2 compatibility
Right now they are pretty much just place holders. I will read this issue and add any of the idea you folks have come up with. Or feel free to update the issues yourselves. thanks
Comment #62
wim leersThis already has a release note snippet, but was not yet tagged for the 9.4 release notes, doing so now!
Comment #63
xjmA consequence of this change is that u pdating Guzzle for 9.4.x or 9.5.x core will result in Guzzle being updated to Guzzle 7. The solution appears to be:
core/composer.jsonwith the new constraint if appropriate.composer require guzzlehttp/guzzle:6.5.6COMPOSER_ROOT_VERSION=9.4.x-dev composer update drupal/core guzzlehttp/guzzlecomposer.jsonto remove the Guzzle requirement.@alexpott identified that
--within recent Composer releases might also address this in the future, although it doesn't seem to work yet for this usecase:https://github.com/composer/composer/issues/10436
Comment #64
xjmI added a new section to the handbook page:
https://www.drupal.org/about/core/policies/core-dependency-policies/mana...
We will also need to be careful of that when we update stuff again prior to the 9.5 beta.
Comment #65
quietone commented@xjm, Thanks, good to have that recorded.
Comment #67
xem8vfdh commentedkeeping core-recommended pinned to a specific version leaves us all in the possition we are in today. CVE-2022-31043 is a new guzzle vulnerability that requires updating to 6.5.7, but core-recommended is pinned to 6.5.6:
So now I cannot simply fix the vulnerability with "composer update", I have to wait for core to publish a release. This is crazy. It should be changed to:
EDIT: https://www.drupal.org/project/drupal/issues/3285157
Comment #68
cilefen commented@xeM8VfDh I appreciate your energy, but:
Comment #69
xem8vfdh commentedI am on the latest 9.3.15 and composer update does not bump my guzzle due to what I mentioned. Is this fix not deployed, or am I missing something? I am using Pantheon, so I didn't explicitly include core-recommended... maybe this is a Pantheon issue?
Even if I am missing something, core-recommended needs to be updated to fix the CVE. Additionally, I don't see why on earth we would pin to a specific version number as opposed to a minor release ('6.5.6' instead of, say, '^6.5'). That seems do go againt versioning best practices, no?
Comment #70
xjm@xeM8VfDh, you will want to follow the instructions for switching from
drupal/core-recommendedtodrupal/core.Comment #71
xem8vfdh commented@xjm, I am using both drupal/core and drupal/core-recommended, is that wrong?
Comment #72
cmlara#3198340: Strict constraints in drupal/core-recommended make it harder for Composer-managed sites to apply their own security updates when a core update is not available is probably the better issue for the discussion on pinning of core-recommended.
Comment #73
xem8vfdh commentedmaybe this is the issue:
EDIT: but then again, I think the solution isn't dropping core-recommended, but rather pinning to a specific minor release in order to get security updates. Maybe even pin to a major release. Whatever the case, core-recommended needs to be updated to pin 6.5.7 at the very least, but should probably pin ^6.5 or ^6
Comment #74
xem8vfdh commentedthanks @cmlara for pointing that issue out, I've commented there.
Comment #75
cilefen commented@xeM8VfDh This will be in 9.4.0 which is out soon. We close issues here when the commits occur not when the code releases.
Comment #76
xem8vfdh commentedMaybe am missing something. I see two commits here, neither of which address drupal/core-recommended, which is currently pinned to an explicit version of guzzle thats associated with a CVE vulnerability. Am I missing a commit somewhere?
Comment #77
cilefen commented#70, #75
Comment #78
xem8vfdh commentedThe commits touch the composer.json in drupal/core. My issue is related to drupal/core-recommended. That's a separate repo and composer.json, no?
I see you recommended getting off of core-recommended, but I can't because Pantheon controlls that. What I am saying, is that core-recommended is exposed to a vulnerability. Regardless of whether you think I should get off it or not, doesn't it need to be fixed for those that are using it?
Comment #79
cilefen commentedYes. Regrettably, we can't build releases instantly.
Comment #80
xem8vfdh commentedLol, I am not trying to be an ass here, I am just genuinely confused. I realize we don't have instant builds. That's fine. I am happy waiting until 9.4.0 but what I am trying to convey to you is my confusion as to whether the fix here actually fixes core-recommended. As far as I can tell, the commits only touch drupal/core. Isn't drupal/core-recommended a separate repo entirely? If so, I fail to see how the commits here fix the vulnerable pinned guzzle version in drupal/core-recommended.
Am I wrong? I'm happy to be wrong, all I am concerned about is that some upcoming release bumps the pinned guzzle version in drupal/core-recommended.
Comment #81
cilefen commentedYou are not wrong. This issue does nothing for core-recommended. If you want minor- and patch-release control over dependencies, do #70. If your hosting provider doesn't allow that you will have to make your own decisions.
#3198340: Strict constraints in drupal/core-recommended make it harder for Composer-managed sites to apply their own security updates when a core update is not available is the issue moving forward.
Comment #82
xjmOr, if you need to apply an update immediately, just depend on
drupal/coreinstead.Comment #83
cilefen commentedI keep saying that. But according to @xeM8VfDh Pantheon doesn’t allow that. It would be nice to see a doc citing that although I don’t think that affects this issue much for the time being.
Comment #84
greg.1.anderson commentedRegarding Pantheon and drupal/core-recommended, the current default upstream is not prescriptive about whether you use drupal/core or drupal/core-recommended, although the later is the default. Once you create your site, you are free to switch to drupal/core if you wish.
The Pantheon code shown in #73 is from an older version of the upstream. At one time, the require for drupal/core-recommended was in a place that individual sites could not modify. Sites using the older upstream may convert to the current upstream using the deprecated upstream migration guide.
Comment #85
xem8vfdh commentedThanks for the updated information @greg.1.anderson, I appreciate you pointing me in this direction
Comment #86
gabesulliceFor those unwilling to leave the warm embrace of
drupal/core-recommendedbut who would still like to use PHP 8, I've had success by usingcweagans/composer-patchesto patch Guzzle itself. I added the following values to mycomposer.jsonand committed the attached patch to my project:Comment #87
kieran.cott commentedThe above patch in #86 works for me using `drupal/core-recommended` version 9.5.11 on PHP 8.1.11, thanks.
Comment #88
bapi_22 commentedThe interesting part: when we remove the package "drupal/core-recommended", the site is running fine with out any issue with Guzzle 7.
As, the package drupal/core-composer-scaffold and drupal/core-project-message is having a dependency of drupal/core.
anyone think, there might be an issue when we remove the package "drupal/core-recommended" completely ?