Problem/Motivation
The dependency system in drupal is lacking certain features that we need going forward to support several desired use cases.
Current dependency management is handled in two ways:
- There is a 'core' key in the info.yml files that expresses whether or not an extension should be able to be used on an existing drupal core installation.
- There are 'dependency' keys in info.yml files that expresses whether or not an extension has all of its required dependencies in order to be installed.
We would like to be able to support the following use cases:
- A drupal 8 extension, that is not using any deprecated code, should be able to be used with both drupal 8 and 9. (or 10/11 etc)
- An extension should be able to express specifically which version of core it requires. i.e. A module taking advantage of an API introduced in Drupal 8.7.0, and bugfixed in 8.7.2, should be able to say it requires *at least* drupal 8.7.2.
- An extension maintainer should be able to use semantic versioning for their modules, and should be able to express dependencies on other modules using semver constraint syntax.
- Drupal should prevent users from installing modules that do not have all of their dependencies available, including 3rd party Composer libraries.
Proposed resolution
There are several issues in the queue attempting to tackle these problems somewhat independently, but they are all interlinked, and an overall strategy has emerged.
Option 1. ❌
Deprecate dependency management inside of .info.yml files, and move dependency related functionality to composer.json. The core key, dependencies, and test-dependencies would all move to composer.json. All other keys would stay in the .info.yml files. Deprecate in 8.8.x and remove before 9.0.0.
Much work and discussion has happened here:
- #1398772: Replace .info.yml with composer.json for extensions
- #3005229: Provide optional support for using composer.json for dependency metadata
Option 2. ❌
Enhance what our .info.yml files are capable of so that they can support multiple core versions, as well as allow the dependency specifications to use semver so that contrib maintainers can start using semver.
Many issues. Much work:
- #2313917: Core version key in module's .info.yml doesn't respect core semantic versioning
- #2641658: Module version dependency in .info.yml is ineffective for patch releases
- #3004459: [PP-1] Fold in dependency parsing wisdom from project_composer
- #2807145: [policy, no patch] Allow contrib projects to specify multiple major core branches
- #3001344: ModuleHandler::parseDependency() can deal with beta1 but not beta
- #1322890: Add a property to .info files to allow modules to specify required php extensions
- #92233: Modules in conflict - conflicts[], breaks[], brokenby[] field in modules .info file
- #328932: Modules and partial dependencies - enhances[] and enhancedby[] field in modules' .info.yml files
Option 3. ✅ (per @catch in #6, @tedbow in #8, @larowlan in #9, @Mixologic in #11 and strategy call with @catch/@xjm/@larowlan/@Gábor Hojtsy/@tedbow/@Mixologic in #14)
Enhance .info.yml files to allow for multiple versions of core, and add *optional* support for composer.json
Allowing for multiple versions of core:
And take most of the work from the following issue, and adapt it to work in parallel with the existing system.
In various discussions with release managers and other core contributors, the was a general sense that the deprecating dependency management in .info.yml files in favor of composer.json seemed unlikely to happen before Drupal 9, and is a fundamentally structural change that affects all existing Drupal 8 modules. Option 1 seemed unlikely and/or risky.
The second option has several limitations, and essentially duplicates a lot of the functionality that we get with composer by default, and still cannot solve some other longstanding issues like "should a user be able to enable a module if its 3rd party dependencies are not there"
The third option emerged as a potential best possible scenario, given the timing and goals.
We would enhance our core key in .info.yml files to allow maintainers to have their modules work with both drupal 8 and 9, with very little effort on their part. At the same time, we would add in *optional* support for using a composer.json as the source of dependency metadata.
This would allow users to continue to do what they were doing before, however, if they needed any of the more advanced features of dependency management (semver requirements, third party libs, conflicts, ~/^ operators etc) then they would be able to use the more feature-rich option of having a composer.json.
Remaining tasks
Confirm with release mangers and other stakeholders preferences for this path.
Comments
Comment #2
MixologicComment #3
MixologicComment #4
gábor hojtsyComment #5
MixologicComment #6
catchSo I think option #3 is a good plan. Ideally we'd land #2313917: Core version key in module's .info.yml doesn't respect core semantic versioning asap so that as soon as the 9.x branch opens, contrib modules can start testing against it. We can then continue to work on the other issues but it might just mean deprecation for Drupal 10 instead of for Drupal 9.
Comment #7
MixologicComment #8
tedbow+1 for option 3.
re
I think #3005229: Provide optional support for using composer.json for dependency metadata actually does allow it to work in parallel already it would just be matter of deprecating in 9 instead of 8.
It seems like we would have to introduce the support for using composer.json to replace the core and dependencies keys in info.yml in the 8.x branch though even if we weren't going to stop support those until 10.x.
Otherwise it really takes away the benefit of #2807145: [policy, no patch] Allow contrib projects to specify multiple major core branches(now covered by #3005229) because you would still need different versions of your module for 8 & 9 if you wanted to use only composer.json for dependencies in 9(unless you just duplicated in both info.yml and composer.json but then what is the point?)
It would probably be simpler though if we could wait till 9.x to do #3005229(also because there so much else to do) but then we would probably have to advice people to keep using core and dependencies in .info.yml if they want there module to compatible with both 8 & 9.
Additionally if we don't do #3005229 in 8.x then modules won't be able to set module dependency constraints once #3054391: [META] Support semantic versioning on drupal.org for contributed projects once is implemented unless we just did #2641658: Module version dependency in .info.yml is ineffective for patch releases(the last patch there simplifies this)
Comment #9
larowlan+1 for option 3 too
Comment #10
tedbowI think one thing we should consider doing before 9.0 is deprecating own Drupal specific constraint string format.
So not remove version constraints in .info.yml
dependenciesbut rather just deprecate support for handling of formats that won't to valid composer formats. and keep our current- 'drupal:[module] ([constraint])'pattern.
So
- "drupal:weform (>=2.0)or
- "drupal:weform (2.x)Would still be valid.
What would not be valid is
- "drupal:weform (>=2.x)Composer semver doesn't allow and operator with a range.
For composer semver
2.xgets parsed as[>= 2.0.0.0-dev < 3.0.0.0-dev]which is the same thing it means to our constraints.
Of course this would also mean anything that started with
8.x-would also not be valid unless we put logic in just to strip that as there is now.The latest patch in #2641658-50: Module version dependency in .info.yml is ineffective for patch releases solves that problem by using
\Composer\Semver\Semver::satisfies()directly when possible(no exception) and only falling back to our current logic when it can't. So basically in Drupal 9 we would just use\Composer\Semver\Semver::satisfies()directly always.I think this would 3 benefits
\Composer\Semver\VersionParserwhich\Composer\Semver\Semver::satisfies()uses. And we won't have edge case in our current format when converting to composer.json.corekey for info.yml files. If we also use composer constraints independenciesin would be much simpler to document(which really don't describe in detail now.). Otherwise we have to explain use composer constraint format forcoreand this drupal specific one which overlaps almost completely but not quite fordependencies.Comment #11
Mixologic#2641658: Module version dependency in .info.yml is ineffective for patch releases is very much option 2, and is essentially blocked on drupal.org. The dependency keys are more than just "can we enable this extension".
This is a weird case of "the strings and their formats in the dependencies key are a defacto API that packages.drupal.org depends on, please don't change whats possible there".
If we start adding new things to .info.yml, we'll need to adjust the project_composer/drupal.org to expect any/all of these new possibilities and handle them all properly, without a clear indicator as to which .info.yml's are in the deprecated format and which ones should be just passed through. It may be easy or hard to handle those changes. But any change at all on that side carries a different risk calculus.
If, we do like option 3 suggests and do nothing to the .info.yml files, and move all new functionality to composer.json, then we get that version string deprecation as a side effect, because the composer compliant versions are all thats allowed in your composer.json files.
So we don't really gain anything in complexity reduction by adding to the number of possible constraints/versions we allow developers to put in their .info.yml - if anything It becomes more complex, and the complexity gets pushed to drupal.org, and the users don't end up with something as powerful as composer.json files. Additionally we lose on the opportunity to encourage maintainers to convert composer.json files, which is also a goal here. I don't want to both tell maintainers that "you can use semver in .info.yml depencencies" and then turn around and say "now that's deprecated, you should use composer.json from now on for dependencies."
The update script in https://www.drupal.org/project/drupal/issues/3005229 isn't altogether essential, and is really just a nice to have to help maintainers transfer data from one metadata format to another. Im almost go so far as to say we shouldn't even include it so that if/when maintainers add a composer.json, they have an opportunity to learn what its for, and what features they now have so they can add one going forward.
The timing of drupal.org related changes required for semver arent really blocked on either solution, it's really just been a preference to delay until core handled semver before we offered it. But we already offer semver, just only for core itself at this point. So, we're not really blocked on waiting if we know that something is going to enhance core to support this feature.
Comment #12
tedbow@Mixologic thanks for the extra info.
I added a comment to #2641658-51: Module version dependency in .info.yml is ineffective for patch releases and mentioning the options now that we know should be super careful not to introduce any new capabilities such as
~/^support accidentally.Also related to here
Related, I wanted to see how many contrib
dependenciesconstraints actually would throw an error if used with `\Composer\Semver\VersionParser::parseConstraints()`. So I made https://github.com/tedbow/drupal_contrib_dependencies. tldr, 99% don't throw an error.Comment #13
MixologicLooking at what we've already got in project_composer, I believe that I had anticipated a change like this already, and as such, it is probably already compatible based off the test cases that currently pass: https://git.drupalcode.org/project/project_composer/blob/7.x-1.x/project..., so the blocked on drupal.org part isn't actually true.
Comment #14
MixologicStrategy per call with @catch/@xjm/@larowlan/@Gábor Hojtsy/@tedbow/@Mixologic
1. Changes to #2313917: Core version key in module's .info.yml doesn't respect core semantic versioning
Then contrib maintainers can, at will, use
^8 | ^9to express that they are compatible with 8 and 9, and not have to worry about an 8.7/8.6 breaking issue where somebody on a security supported site cant get a security update for a module.2. Refactor #3005229: Provide optional support for using composer.json for dependency metadata such that if an .info.yml file exists, and has a core: key, use the existing logic in core. If there is a composer.json, and no keys for core/deps/test_deps in .info.yml, use composer.json as the source of truth. The goal here is to not intermix the two options. Using .info.yml will not be deprecated until drupal 10. Having a composer.json alongside your modules will be the preferred method if you need/want ~/^ operators, as well as patch level dependency specifications. This will also enable an eventual 'subtree split' for modules (though the module/projectname collisions need additional thought).
3. Close/wont fix #3004459: [PP-1] Fold in dependency parsing wisdom from project_composer because if we can avoid manipulating the existing parsing thats better. If we still want this code for a potential, optional conversion script, we could leverage it for that.
4. Mark #2641658: Module version dependency in .info.yml is ineffective for patch releases: as a duplicate of #2313917: Core version key in module's .info.yml doesn't respect core semantic versioning because we'll get the core key functionality as a result of #2313917: Core version key in module's .info.yml doesn't respect core semantic versioning, and we can hold off on the contrib semver part until #3005229: Provide optional support for using composer.json for dependency metadata.
5. Harden test deps for existing code. #3066448: Harden test coverage for dependency Constraint class There can never be too many tests.
Comment #15
wim leersFirst: thanks to everyone involved with creating this issue and discussing it. This issue brings clarity in a cluster of seemingly overlapping issues that were hard to make sense of (at least for me). The options listed in the "proposed resolution" section in the issue summary made it crystal clear. 👏👍
@tedbow was kind enough to walk me through the discussion and thought process. He pointed out one very interesting aspect of the first and second option that I had not considered yet (it may be obvious to some of you, it was not to me) that I don't see listed in the issue summary yet: even though it seems unlikely that we'd break something along the way, if we get something wrong, it may break the Drupal 8 to 9 upgrade process in a subtle way that we will only discover when it is too late. This is what convinced me beyond doubt that the risk in options one and two is unacceptable.
@Mixologic in #13: wow, impressive foresight! 😲
The plan that came out of a meeting with key people that is documented in #14 is crystal clear. 👍The only clarification that I think would be helpful there is
Does this mean we want to do #3005229 only in Drupal 9, not in Drupal 8? (#3005229 is currently marked for
8.8.x-dev.)Comment #16
MixologicThe wording there is a little bit unclear.
There was a general feeling that adding semver support by adding optional support for composer.json files was going to be 'bigger' or 'more complex'. The 'hold off' part was really "lets not manipulate the existing system, and simply add the optional support in a different code path". The other thing that means is that since we do not plan on deprecating using .info.yml files for dependency resolution until drupal 10, then essentially, we can add that new option 'as soon as we can get it in' which might be possible in 8.8.x, but, may also require that we wait until the 9.1 cycle, based on timing/workload other factors.
Some of the 'bigger/more complex' parts is that when we get into the extension system, we definitely trip over weird vestigal things that are awkward or hard to work with, and need a refresh, aka #3053832: Refactor ModuleListForm. Those are the kinds of things where we find that maybe the original stuff wasn't tested very well, or has built in assumptions about how it works that arent documented etc.
Anyhow I think we want to do #3005229: Provide optional support for using composer.json for dependency metadata as soon as we can, but the window for 'soon' is rapidly shrinking. However it may be something we *have* to make happen because we've needed semver for contrib for quite a long time now.
Comment #17
wim leersThat's crystal clear. Thanks, @Mixologic!
Comment #18
xjmComment #19
xjmComment #20
tedbowRelating #3074998: Add explicit information about core compatibility to update data because currently information in the update XML doesn't explicitly specify which core version and update is compatible with.
Comment #21
wim leersUpdated the issue summary to make it clear we chose option #3.
Comment #22
wim leersSo, how are we executing our detailed strategy from #14?
Comment #23
wim leers🤦♂️
Comment #24
gogowitsch commentedI only updated the grammar of the issue description.
Comment #26
dwwNot sure if this is the right place to mention this, or if I should spin off a child issue, or what, but...
#3116581: Use core_version_requirement, not a version dependency on drupal:views
VBO made a 8.x-3.5 release with bold text on the release notes saying "this version of VBO will require Drupal core >= 8.8. If for some reason 8.7 or lower is used on your project - don't update."
However, it defines this requirement via:
Not:
So none of our tooling knows about it. :(
Do we care? Should we do anything to try to handle this case, or do we punt and say: "that way of defining core requirements is deprecated, go fish."?
Oh, except I searched and couldn't find any issue where we actually "deprecate" using
dependencies:to define a specific version of a core module you need. So what VBO did is actually totally fine, and I don't believe that's been deprecated at all. :( Seems like a big gap in this whole plan, and I don't see it mentioned in this issue. In #10 @tedbow wants to deprecate the Drupal-specific range operators independencies:, but there's no talk of using dependencies to refer to core. I don't think we can deprecate this behavior, since not all core module are required, and contrib needs to be able to have dependencies on optional core modules. So I think we've got to keep supporting that. But maybe we can deprecate defining a core version that way?Can the project_dependencies world notice this kind of thing and make sure that the
<core_compatibility>in the release history XML feeds takes these sorts of core compatibility constraints into account, too? Basically, define<core_compatibility>as the most restrictive requirements from all ofcore,core_version_requirementanddependencies?Also, does anything stop contrib authors from getting this totally wrong and doing things like:
? Not sure where we can/should try to notice that and prevent them from doing it. It'd sorta be nice to notice before they try to make a broken release, but I don't think that's possible. I know we've got code that makes sure you don't do
core_version_requirement: ^8.5or something, since 8.5.x core didn't support that key. But I don't think we've got anything that tries to notice conflicts / incompatibilities betweencore_version_requirementanddependencies.Thoughts?
Thanks/sorry,
-Derek
Comment #28
xjmClarifying that this is about downstream modules and themes, not upstream dependencies.