Problem/Motivation
We have many meta packages to help projects run with the right set of dependencies:
- drupal/core-recommended
- drupal/core-dev
- ..and an even more strict package: drupal/core-dev-pinned
These packages are released together and share the same versions.
Although these are independent packages, they are semantically and practically tied together. You might be able to use different versions of these packages (different minor, patch, but likely not a different major version), but usually, you encounter unexpected issues when these packages are not in sync.
For example, when creating a new project from drupal/recommended-project and you want to run tests, you are supposed to composer require drupal/core-dev. However, that package doesn't depend on core, so if you're not careful, you might end up with a different version of core-dev than the core version you are using, causing things to fall apart.
Moreover, even if the Updating Drupal core with Composer guide suggests running composer update "drupal/core-*" --with-all-dependencies to keep Drupal core and metapackages up to date on existing projects, this command does not guarantee that the versions of the installed metapackages will match. This command instructs Composer to try to update all matching packages, but conflicts and version constraints in other packages can prevent one or more matching packages from being updated. This issue is discussed in this Drupal Slack thread about failing PHPUnit tests due to an incorrect behat/mink version installed on projects after the Drupal 10.2.x to 10.3.x update.
Steps to reproduce
composer create-project 'drupal/recommended-project:^8.9' d8_9_composercd d8_9_composercomposer require drupal/core-dev
You would expect to get drupal/core-dev for 8.9.x and have a working testable site. Instead, you see this:
Using version ^9.0 for drupal/core-dev
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Conclusion: don't install drupal/core-dev 9.0.2
- Conclusion: don't install drupal/core-dev 9.0.1
- Conclusion: don't install drupal/core-dev 9.0.0
- Conclusion: don't install drupal/core-dev 9.0.0-rc1
- Conclusion: don't install drupal/core-dev 9.0.0-beta3
- Conclusion: don't install drupal/core-dev 9.0.0-beta2
- Conclusion: don't install drupal/core-dev 9.0.0-beta1
- Conclusion: don't install drupal/core-dev 9.0.0-alpha2
- Conclusion: don't install drupal/core-dev 9.0.0-alpha1
- Conclusion: don't install drupal/core-dev 9.1.x-dev
- Conclusion: remove masterminds/html5 2.3.0
- Installation request for drupal/core-dev ^9.0 -> satisfiable by drupal/core-dev[9.0.0, 9.0.0-alpha1, 9.0.0-alpha2, 9.0.0-beta1, 9.0.0-beta2, 9.0.0-beta3, 9.0.0-rc1, 9.0.1, 9.0.2, 9.0.x-dev, 9.1.x-dev].
For this to work, step #3 should be composer require 'drupal/core-dev:^8.9'.
Proposed resolution
As @stof suggested in this Composer discussion, we could use the self.version constraint to keep package versions in sync. Instead of using "drupal/core-recommended" : "self.version", we should use "drupal/core": "self.version" since both drupal/core-recommended and drupal/core-dev packages can and should depend on drupal/core.
Remaining tasks
Manual testing. Details are in comment #34
Create a change record
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Release notes snippet
N/A
| Comment | File | Size | Author |
|---|---|---|---|
| #40 | 3163114-nr-bot.txt | 90 bytes | needs-review-queue-bot |
| #29 | C392CHBEW-1720016380.610809.txt | 6.61 KB | mxr576 |
| #25 | 3163114-nr-bot.txt | 90 bytes | needs-review-queue-bot |
Issue fork drupal-3163114
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 #2
dwwNote that composer/Metapackage/PinnedDevDependencies/composer.json already includes:
So this is specifically for
composer/Generator/Builder/DrupalDevDependenciesBuilder.php. Not sure the right thing to put in there to refer to the same version of core as ourself.Comment #3
dwwProbably totally wrong, but here's a naive initial patch. ;)
I can't find anything about how these builder classes are run. Maybe that's core packaging custom stuff.
Comment #4
greg.1.anderson commentedPrior to the release of 8.8.0, there was much discussion on whether or not drupal/core-dev should depend on a specific version of drupal/core. We decided to not put in a relationship between the two in order to make it easier to update sites that used drupal/core-dev.
Maybe now that Drupal ^9 is available, we should put in a conflict so that the 8.x core-dev conflicts with drupal/core ^9, and the 9.x core-dev similarly conflicts with drupal/core ^8.
As you noted, users who wish to have strong version constraints can use the "pinned" version of the dev dependencies project.
Your patch looks like it should have the desired effect, but I am -1 on adding a dependency to drupal/core in drupal/core-dev.
Comment #6
dwwHah, it'd help if I used the right PHP function. ;)
Although I guess I shouldn't worry about the other test failure if @greg.1.anderson is opposed to this change...
Comment #7
greg.1.anderson commentedI'm not opposed to the concept; just use "conflict" instead of "require" and I'm +1.
Comment #8
dwwWhy is 'conflict' better? Seems hard to get that to scale appropriately. Don't we just always want core-dev to track the version of core you're using?
If we say 'conflict', we'd have to go back and retroactively update everything for each new core branch we add, right? If we just say: "requires drupal/core:$yourself" we're done, no?
Is there an issue about the discussion for why we don't want that?
Thanks,
-Derek
Comment #9
greg.1.anderson commentedThe reason that we don't want to require drupal/core with self.version is that it makes upgrading harder. If you want drupal/core:self.version, we have the pinned dev dependencies for that.
A conflict statement could be added like so:
Just use
\Drupal::VERSIONto calculate the major version. If you wanted, you could special-case<8and make it<8.8.Comment #15
bhanu951 commentedThis issue is still relevant on Drupal 9.5 and above We Might need to try to fix it as currently requiring `drupal/core-dev` it is installing `8.0@beta` version.
Comment #18
mxr576Comment #20
joachim commented> The reason that we don't want to require drupal/core with self.version is that it makes upgrading harder.
In what way?
We now recommend that upgrading core be done with "composer update drupal/core*" which updates both packages simultaneously. Won't the dependency work ok with that?
Comment #21
mxr576Made the patch hidden because it is for an older major version and does not implemented the suggested solution.
Comment #22
mxr576Comment #23
mxr576I was thinking about why Greg said this and what I saw in https://www.drupal.org/files/issues/2020-08-03/3163114-6.patch... so do we really expect and reality also confirms that within the same Drupal minor versions, these meta packages could be on different versions at any time and everything should work? Because if not, the current solution with
self.versionin the MR is the only way to move forward, if not, then we get back to patch 6 and only lock on major.minor.Comment #24
mxr576It occurred to me that Greg's comment is 4 years old and maybe it is from those days when core-recommended did not allow patch version update of dependencies. In those days the concerns he raised regarding
self.versionwas valid.The drupal/core-recommended package now allows patch-level updates (since 9.4.0)
Comment #25
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #26
mxr576Still mergable according to Gitlab.
Comment #27
greg.1.anderson commentedI believe I answered this question elsewhere recently, but I am not sure where, so I will re-post here for context.
During the development of Drupal 8.8.x,
composer update drupal/core*failed to update if drupal/core-recommended depended on a specific version of drupal/core (and with the same relationship between core and core-dev), because Composer became confused by the chained strong constraints. One might think that strong constraints would make the dependency graph easier to resolve, because it branches to fewer variations, but for whatever reason, it was harder for Composer in the past. If modern Composer deals with it well, then this change is an improvement.Comment #28
greg.1.anderson commentedIf I recall correctly, the conflict statement that I recommended worked better (e.g. #9 can be rewritten to allow only one patch version). I don't recall if there was any reason we didn't add it; maybe just never got to it. We certainly did not want to encourage folks to mix different core versions.
Comment #29
mxr576This was the Slack thread: https://drupal.slack.com/archives/C392CHBEW/p1720016380610809
I also dumped it via Slackdump before it gets lost, see attachment.
Thanks for looping back to this thread, I'll also do that early next week.
Comment #30
ressaThanks for saving the conversation before it was lost @mxr576!
As we talked about in #2952616-17: Adopt CommonMark spec for Markdown files, an automated Slack dumper service would be awesome, pulling down and saving all the great Drupal conversations. A daily drupal.org/project/drupal issue could work as a data repository, consolidating the text for inclusion when searching in Drupal core issues :-)
Comment #31
smustgrave commentedBesides a CR any next steps needed here?
Comment #32
mxr576Well, Greg expressed his opinion in the referenced Drupal Slack about why he would not rely on core-dev for running tests on downstream projects, but he did not mention that in #27.
I think we are on the an agreement regarding:
I do not think that enforcing this with
conflictorrequirewould make a difference in Composer 2.7+... if there are strong concerns we can try figure that out somehow... without that we can merge the current approach and switch to other after this proved to be problematic.Comment #33
mxr576Comment #34
greg.1.anderson commentedDon't worry about that old comment, it was unfounded. My point is that you shouldn't use core-dev unless you're using test classes packaged by Drupal to run tests on downstream projects, which is exactly what folks are doing.
My latest comments on moving forward, copied from slack:
Comment #35
mile23From the summary:
First: Why would you expect that? It's not how Composer works unless the other packages have declared tighter constraints. If you get the error message, you'll figure out that you need to specify a version. Speaking of tighter constraints....
Second: If it's a reasonable (or even just desired) expectation, then having
drupal/core-devdeclare that it conflicts with future (and maybe even past) versions ofdrupal/coreis the most reasonable solution to deliver that.So, we leave everything else alone, and then only change
drupal/core-dev(and-pinned) to conflict with future versions ofdrupal/core. We can do this because we always generate a newdrupal/core-devwith each release, even if all the dependencies are exactly the same.So
drupal/core-devrelease 11.0.0 would look like this:In this circumstance, Composer gets the version of
drupal/core, and then finds the version ofdrupal/core-devthat doesn't conflict, and then we're done. We can also tell people tocomposer require drupal/core-dev:@stable.Comment #36
mxr576At the very least, these packages should be tied together at the minor version level. Based on past experiences, it might even be beneficial to tie them at the patch level as well. For more details, see this Slack thread about how the 10.2 -> 10.3 upgrade broke tests because Composer installed incompatible versions of Drupal core packages: https://drupal.slack.com/archives/C223PR743/p1719331712444049
Drupal core is a monorepo that is only partially managed as such. If we could guarantee that split packages in the subpackage repositories are always compatible with each other, this problem wouldn't exist—but we can't.
The drupal/core-dev package defines the dependencies needed to run tests, while drupal/core contains the tests that might need adjustments as core-dev dependencies evolve... which is not a problem in a monorepo because update and adjustments could happen in the same MR.
However, the butterfly effect is more visible for downstream projects that require drupal/core-dev, and they often only realize changes are needed when a minor (or, in the worst-case scenario, a patch) update to drupal/core-dev breaks their test suite.
Comment #37
cmlaraI want to second the statements by @mxr576. I would expect
drupal/core-devto be tied todrupal/core. They are designed to work together and are linked where changes in one can require explicit changes in the other, especially since they are developed in the same repository. The same applies true todrupal/core-recommendedas we can very easily end up using releases of dependencies that have not been tested with a version of Core defeating the purpose of the packageI do not really care how this is implemented (require or conflict, in
drupal/core-devor ondrupal/core) however I would add this question that might help justify which makes more sense if done indrupal/core-dev: Is there ever a case where you would wantdrupal/core-devthat you would not also wantdrupal/core? If the answer is no, than require makes the most sense asdrupal/core-devshould also bring with itdrupal/core, if the answer is yes than conflict would be more logical.Either case testing should not be too hard, download https://repo.packagist.org/p2/drupal/core-dev.json (or whatever other package to modify), loop over the require/conflict section and add the desired constraint, place the resulting file into a local composer repo available on localhost and can easily see if any noticeable impact occurs as you use composer to require specific versions and constraints of packages.
Comment #38
quietone commentedUpdated the IS with a link to testing instructions and tagged.
Comment #39
mile23@cmlara: "I want to second the statements by @mxr576. I would expect drupal/core-dev to be tied to drupal/core."
Well,
drupal/core-devis tied to core. They have the same version number. You can currently saycomposer require --dev drupal/core-dev:[your core version constraints here]and it works.However, if you want to be able to not know your current core constraints and just say
composer require --dev drupal/core-dev, then we need to changedrupal/core-devas described in #35. We makedrupal/core-dev(and-pinned) conflict with versions ofdrupal/corewhich aren't the same, and then Composer will do the sorting for us.@mxr576: "At the very least, these packages should be tied together at the minor version level. Based on past experiences, it might even be beneficial to tie them at the patch level as well."
That's exactly what I proposed in the message you're responding to.
Comment #40
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.