Problem/Motivation
The namespaces at the composer facade are derived from extension names inside of a project.
This issue is to discuss the possibilities of potentially re-architecting those namespaces to be a consistent, predictable namespace and not rely on heuristics to guess at the namespace for a dependency.
1. If a module namespace already exists, then a namespace is currently disabmiguated by using the project machine name followed by the module name.
contrived example: drupal/views-views_ui, where the views project contains a submodule named views_ui.
* Submodules can have dependencies that the entire project does not have. -> optional dependencies if you are using an optional submodule. Example: the drupal/cloud pro
* There are two types of packages advertised at the facade: Packages, and Metapackages.
* Sub modules become meta packages.
*meta packages are challenging for upgrades because composer treats like less like a 'redirect' and more like a versioned package.
Steps to reproduce
Proposed resolution
The proposal is that the project machine name is *always* the namespace, and that all modules in a project get a metapackage namespace of drupal/project_machine_name-extension_name
Remaining tasks
1. have to find out if any projects have drupal/extension_name in their composer.json files (using a namespace that will change)
2. need to know how many projects have info.yml files but no composer.json
3. need to know which projects have dependencies in their info.yml files that are *not* namespaced to the project.
Comments
Comment #2
moshe weitzman commentedI forget why our Composer needs to care about submodules.
Comment #3
wim leers#2: so one is able to e.g. do
composer require drupal/admin_toolbar_tools, without having to know that one would actually need to docomposer require drupal/admin_toolbar.Or:
drupal/metatag_viewsvsdrupal/metatag.Comment #4
wim leers+
This is the case that just came up while working on https://www.drupal.org/project/automatic_updates + https://www.drupal.org/project/project_browser.
The case of
admin_toolbar_toolsbeing a submodule ofadmin_toolbaris fine, because it only has a dependency on the "root" module.However, the case of
metatag_viewsbeing a submodule ofmetatagis not fine, because it has one additional dependency:… which is not reflected in the generated metapackage:
IOW: I would expect
drupal/views *in therequireslist too.Comment #5
wim leersAFAICT #3064900: Always or only respect disambiguated submodule names is tangentially related.
But more importantly, #3099771-2: Don't expose submodules in Drupal's packagist at all by @mixologic seemed to suggest #4 was already supported, but this issue summary makes clear it's not yet supported:
(I agree with that quote, just saying that the submodule's dependencies are currently missing.)
Comment #6
kopeboyAre we saying that since
composer require drupal/metatag_viewsis currently working, nobody can register ametatag_views(project/module machine name) on drupal.org nor have it working with composer? This is scary, as current maintainers could add a plethora of submodules kind of unoticed ..?Comment #7
jon pughI'm trying to fix a bunch of projects that got the double names here: https://www.drupal.org/project/infrastructure/issues/3371966#comment-151...
I'm thinking there could be a way in project_composer modules to handle this.
The user story I am thinking of:
drupal/$project_name, so they must remove the association between the originalproject_namecomponent_nameandproject_namespace.Perhaps we need a little UI for listing and updating a Project nodes Package Maps?
Comment #8
kingdutchThe request
I'm going to politely repeat my request from ~4 years ago in #3099771: Don't expose submodules in Drupal's packagist at all as I've been bitten by this in two different ways in the past few weeks, one of which I shared on Slack
Please treat the Drupal.org project equivalent as packages and stop shipping submodules as separate metapackages.
Previous Feedback
I'll start by addressing the feedback provided on the linked issue from back in the day, which I didn't do at the time because the issue was closed.
I feel this has now been in the coding standards for many years. I think it exactly solves the problem we have: we need a dependency, we need to know what project to pull it from. If our impediment here is "this is not something that Drupal enforces" then I don't think it's a big ask of Drupal core to start enforcing this in a major version (if we had done that 4 years ago we could now reap the benefits, but even if it takes til the Drupal 11 release, we can benefit in the future).
Having that format enforced can have advantages for static analysis tools too and if we're unwilling to at some point turn this suggestion into a requirement, and Drupal core does not use it, then we should probably instead stop suggesting it.
At runtime for Drupal I think you're right. At packaging we would have all the info to make this decision, but the only issue would be that a random dependency might hit multiple modules if multiple projects contain the same module. This could be solved by solving 2 (which is why this feedback is out of order).
I think this is debatable. Outside of Drupal, if I download something through composer it'll come with everything I need, even if I don't need all of it. If this would truly be a problem for the module then moving it to a new project might also be a good answer. Disk space is cheap? :D
That's fair, that's one of the two issues I now ran into again which I'll describe below. However, the problem would also go away if we treat a project as a single versioned package of code and stop trying to process what's inside of it. This problem might be alleviated by recipes, but it's going to be a few years before major distributions are going to be converted.
The problems I ran into
I'll describe the two issues that cause me to revisit this issue, the second one I ran into today which is caused by Open Social being a distribution, the first one prompted the Slack post 2 weeks ago.
In both cases the top of the project includes a
composer.jsonfile that already describes what it wants and ideally that would not be altered.A "submodule" depending on a parent module
Composer will now disallow updating the module from 1.x to 2.x with any of its update commands. The cause for this is that Composer 2's optimizations will exclude the 2.x version of activity_send_push/social_pwa because of this cyclical dependency.
This results in the lovely error of:
Historical reasons; a developer made an incorrect decision; the submodule implements an optional plugin for another system that it interacts with and we ship it as default implementation, but there might be scenarios where a user wants to use only the submodule and provides their own overarching system (the submodule does not depend on the parent).
However as mentioned in the reply to my previously created issue
There is no such thing as a submodule. So we really should be free to organize our code and dependencies as we wish, without this breaking composer installability.A module depending on a module in a distribution
It was already mentioned that there's currently no support for distributions. It was also mentioned that the
project:modulesyntax is ignored. However for the generation of thecomposer.jsonthe format does matter.In
social_geolocation2.4.0 I worked on Drupal 10 compatibility and as part of cleanup moved to the newproject:modulesyntax. I suddenly found myself unable to install that version because it depended onsocial_event,social_profileandsocial_groupwhich are modules in the Open Social distribution. This is covered by thegoalgorilla/open_socialdependency in thecomposer.jsonbut listing this separately will cause composer to complain about missing packages (or worse, install unexpected projects that override module names).Changing the names back to
module(removing the project: prefix) caused the Packagist to ignore those dependencies which solved the issue. This can be illustrated by looking at the composer info for the two versions.The project browser initiative
I'm not sure what the plans for the project browser are (I couldn't find anything concrete), but I think they'll always default to installing the top level project, since that's what has the metadata and a logo, etc.
So this might already be a good counter for the argument of having to promote all dependencies to the top level. In the flexiform instance, if the project itself does not include the rules dependency, then the flexiform_rules module might be installed through composer, but there's no control for that project over which version of rules it's compatible with. (Though I can see this is already a problem in the current implementation).
Comment #9
nterbogt commentedCross posting a possible solution from another issue discussing the same problem.
After doing some research into the composer schema, would it not be better to use
"abandoned": "drupal/[submodule]"in submodules, suggesting the main module? This would allow a user to find submodules through composer, but also guide them to installing the package correctly. And when a submodule is moved out, it can become a 'real' package and override the abandoned definition.And yes, I understand that the project isn't really abandoned, but it's functionally equivalent (and the only option in the schema that achieves the same outcome).
Comment #10
swirtI agree that we can't have it both ways. A submodule either needs to be treated like another package or not be treated like a separate package at all. Currently it is being treated somewhere in-between
Current Situation
composer require 'drupal/projectA_submoduleG'Results in The parent module being included using the parent module's composer.json. The submoduleG's composer.json is ignored. So the parent module must include all dependencies of both the parent and any optional submodules or there will be mayhem. A lack of efficiency is the result.Solution One
Composer has no full awareness of the submodules.
composer require 'drupal/projectA_submoduleG'would result in: Could not find drupal/projectA_submoduleG' did you mean drupal/projectA'Solution Two
Treat submodules like distinct packages.
composer require 'drupal/projectA_submoduleG'would result in: that parent module being downloaded and would utilize the composer.json within projectA_submoduleG and would also use the composer.json in projectA because it is a dependency of projectA_submoduleG.