Closed (fixed)
Project:
Drupal core
Version:
11.x-dev
Component:
extension system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
20 Mar 2024 at 10:09 UTC
Updated:
12 Nov 2025 at 13:31 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #3
wim leersDraft MR created.
Comment #4
wim leersComment #6
wim leersClosed #3432196: Improve core.extension:profile validation as a duplicate. Crediting @alexpott.
Comment #7
wim leers#1170362: Install profile is disabled for lots of different reasons and core doesn't allow for that is in!
Comment #8
wim leersComment #9
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. 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 #11
kunal.sachdev commentedMost tests are failing because in
TestBasesetup()we doand in
ThemeInstallerwe havewhich also tries to validate the config and it breaks for
ExtensionExistsContraintwith error message 'Theme stark is not installed', which is true. I think we could add a check inThemeInstallerbefore saving the key in the config, something like this-, but I am not really sure about this.
Comment #12
kunal.sachdev commentedExtensionExistsconstraint doesn't make a ton of sense forcore.extensionsee (3441503-#18) for more details.ExtensionExistsconstraint forcore.extensionthenExtensionExistsConstraintValidatorshould be completely refactored and use theModuleExtensionListandThemeExtensionList, which can report on existing-but-not-yet-installed things.Comment #15
yash.rode commentedTests are passing now
Comment #16
borisson_This is a difficult question. In my opinion ExtensionExists/ExtensionInstalled makes sense, but renaming this and after that reusing the name for the other meaning is difficult. Can we use ExtensionPresent to indicate that should be present on the file system?
Comment #17
smustgrave commentedBelieve this needs work for the feedback mentioned in #16? Also is MR 7107 needed anymore?
Comment #18
bbralaModuleHandler already uses exists to check for installed. So the naming is kinda consistent.
If we need to seperate why not;
ExtentionAvailable, which would be consistent with things like; 'update available' or perhaps 'moduel available to install'. Doesn't feel that weird to me.
Comment #19
borisson_ExtentionAvailablemakes a lot of sense to me.Comment #20
bbralaExtracted the validator so naming makes sense. Split tests also and did a rebase so we run the right tests.
Comment #21
smustgrave commentedLatest MR appears to have pipeline issues. Can 1 MR be closed or hidden also to make it super clear what should be reviewed
Comment #22
bbralaOops, thanks, juggling a lot of issues, will cycle back.
Comment #24
bbralaClosed MR, and fixed phpstan issue.
Comment #25
smustgrave commentedLeft 1 question and 1 comment on the MR.
Comment #26
bbralaDid all the promotions, time to go home :)
Comment #27
bbralaall failures unrelated.
Comment #28
smustgrave commentedUsing config inspector I see we are at 100% now.
Believe all feedback has been addressed
Comment #29
bbralarebased, only to see if the unrelated failures have been fixed.
Comment #30
alexpottThe big issue left is the new constraint - left a big comment on the MR.
Comment #31
bbralaStruggling with the datadefiniotion to test. Giving up for now. :)
Comment #32
bbralaThat took a while, this typed data is a rollercoaster :x
Think i have working tests now prooving stuff works. Yay!
Comment #33
bbralaComment #34
bbralaNext up, see if it can be rewritten to use the
Compositeconstraint.Comment #35
bbralaNot sure who made ExtensionNameConstraint but that message is useless. "The value is not valid.". That could easily be something more sane :x
Comment #36
bbralaTest are running, but im quite confident they will end up green.
Added
__clonetoExecutionContextsince that makes it possible to collect messages and then combine them in the original context (see #3461720: Create AtLeastOneOf constraint where that is also used forAtLeastOneOf)Comment #37
godotislateBuild has PHPCS issue. Also added some comments to the MR.
Comment #38
bbralaThan you so much for the review :)
Comment #39
bbralaWent through your (thorough) review, this made the a few things way better. I have a response to two of your suggestions which i think might have issues if we do that.
Comment #40
bbralaI think i adressed the last comment and made it quite a bit simpler code.
Comment #41
bbralaComment #42
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 #43
bbralaComment #44
borisson_2 additional remarks.
Comment #45
bbralaThink i addressed all feedback
Comment #46
bbralaComment #47
borisson_Looks great!
Comment #48
alexpottWe need to address the comment I've just added to the MR... there's a very very awkward thing with profiles. In fact the comment does not quite cover the complexity here. I think we need to detect if the profile is changing and if it is we need to rebuild the module and theme validators as this alters what modules and themes can be discovered.
Comment #49
alexpottChanging the install profile on an existing site is a little fraught. Things have change so that you can uninstall an install profile if you are not using any themes or modules that only exist in the install profile - see \Drupal\Core\Extension\InstallProfileUninstallValidator.
We could consider changing an install profile to another install profile to be an invalid change and only allow it to be cleared. Hmmm. Not sure.
Comment #50
borisson_Asked for more clarification in the MR comment (and now posted here as well, so that this issue goes back to unread).
Comment #51
bbralaLets start by saying, i dont know much about the systems in play here ;)
Hmm, so my first thought would be that it should do discovery without any cache, but ending up at that not being really a thing. Lets see if i understand correctly.
We need to validate the extention, BUT, since profile is also changed it might have different modules available. So even if we say; when the profile changes, we reload the list or rescan for available modules. BUT this validation is before the changes have persisted. So it gets worse, in the fact that it needs to scan for the future situation.
In my head i have a few options;
Comment #52
alexpottRe profile changes - we already only really allow the profile to be set by the installer and unset though module uninstallation after checking the modules - see \Drupal\Core\Extension\InstallProfileUninstallValidator. In any real way we don't actually support making changes to core.extension directly via config tools. So the test that I've commented on is pretty funky. I do think that 1 is probably the best solution for module and theme validation. I.e if the profile has changed use a fresh discovery object. Wrt. to enforcing install profile change rules... I'm not sure. I guess we can leave it alone until it causes us problems.
Comment #53
bbrala"I'm not sure. I guess we can leave it alone until it causes us problems."
Not sure what you mean with leaving it alone. Ignore the weird test case where profile is changed and module is changed?
Comment #54
alexpottRe
What I mean is we can ignore trying to validate profile beyond a profiles existence for now. I think we should not be changing that test in this issue. The fact we are shows we've got stuff to fix.
Comment #55
bbralaThink i might've found a way by adding special case for core.extension. Lets see how tests go.
Comment #56
bbralaForm slack
Comment #57
bbralaLets see how this works when we forcefully reinstantiate the discovery mechanisms.
Comment #58
bbralaIf this works, i think i will split it into a seperate constraint maybe. Since then we could just instantiate the new ExtentionList classes every time instead of doing the check. Which would also mean i can just inject the services in the create method with having loads of extra services in the ExtensionAvailableValidator
Comment #59
bbralaThose services were a little involved to instantiate. Pulling in a lot of stuff from the container. I could then remove the test changes, but i did need to update a theme test that was loading a module from a profile that is not installed.
Think this is working as expected now thanks to the guidance of alex.
Note: testfailure is unrealated and does pass locally.
Comment #60
borisson_Does this signal the need for an upgrade path, or is this because we do weird things with the testing profile?
Comment #61
bbralaThis signals the test is trying to set a module from outside its installed profile. Should be a weirdness with the teatsetup as talked about with alex
Comment #62
borisson_Comment #63
alexpottThe current approach is not going to work unfortunately. Because the ExtensionList objects interact with state and cache so we're in danger of affected the live running of a site if we validate a core.extension object prior to it being changed. I think we have to follow InstallProfileUninstallValidator's example and use a lower level ExtensionDiscovery object to determine if modules and themes exist if the profile has changed.
Comment #64
bbralaOk fair enough.
Comment #65
bbralaUpdated to propere extension discovery.
Had to add a testing env check because there are different rules there what modules you can install :(
All good now i think (and green tests)
Comment #66
alexpottThere's a little bit more we need to cope with.
We need to test what happens when the profile is NULL - that’s the starting state. And when it is complete removed - that’s what happens when the install profile is uninstalled.
In the case that the profile is not set I think we'll need to set the directories to something that cannot exist - like we do in \Drupal\Core\Extension\InstallProfileUninstallValidator::getExtensionDiscovery
Also I think that \Drupal\Core\Extension\Plugin\Validation\Constraint\ExtensionAvailableConstraintValidator::$extensionDiscovery should be an array of extension discoveries keyed by profile as this is easy to reason about.
!in_array($profile, $this->extensionDiscovery->getProfileDirectories())looks interesting and fragile.Comment #67
bbralaComment #68
bbralaAdded tests for different situations and verfied install_proffile parameter is all types we discussed. Unfortunately i couldnt get unit tests working, so ended up added an extra method to disable the fact it is inside a test.
Comment #69
smustgrave commentedApplying MR and using configuration inspector went from 5% to fully validated. Amazing!
There's 1 thread open but overall believe this is good to go.
Comment #70
alexpottA recent core release has shown how dangerous mixing private self and protected statics with self:: is. Let's not repeat the mistake...
Comment #71
alexpottAddressed my own MR comment.
Comment #72
borisson_Back to rtbc.
Since this is not a final class I guess the use of a private function was not really appropriate to start with?
Comment #73
bbralaSome good improvements, thanks alex.
Comment #76
dcam commentedI'm checking all RTBC issues to ensure their new tests use attributes. Because these changes are minor and the tests are passing I'm going to leave the issue at RTBC.
Comment #77
nicxvan commentedThank you for this! I think this might belong in the extension system queue.
I'm not quite sure i want to pull this out of rtbc yet, but I do have several questions.
1. Most important, what happens if we get this wrong? This feels particularly gnarly and looks like it could break things spectacularly if we don't do this correctly.
I ask because this is dealing with extension discovery and that is very complicated and very crucial.
2. Is there a write up on why we want to make everything fully validateable? I would like to understand better the goals. I think it's #3427641: [meta] Config validation for a more reliable Drupal + reliable Recipes from the start
3. If someone has invalid config now what happens? Can they do anything before fixing it? Will their site break? Does it interfere with config export and import?
4. For this config in particular, is there a way to do it like a deprecation with messaging instead of a hard constraint right away?
I remember invalid permissions being a particularly tricky config issue to solve for some sites, since this is install and uninstall time i think the total is even higher.
I think I've asked enough questions that I've convinced myself to pull this from rtbc.
Finally there are a few threads on the MR that have not been addressed since it read at to rtbc.
Sorry I didn't see this sooner.
Comment #78
wim leers@borisson_ pointed me to this issue — so, writing this, live from the Acquia booth 🤣🤓
core.extensionthat is incorrect/nonsensical/lying? 😅 What if I have 50 modules listed and 49 of them don't actually exist on disk? Wouldn't you want to be warned while developing, to prevent it being deployed to production?Thanks to #2625212: Add ConfigSchemaChecker to development.services.yml, everybody who's developing Drupal sites using
development.services.yml(many/most people), will already get exactly what you're advocating for: it usesLenientConfigSchemaCheckerwhich warns about invalid config. 😊Note that this MR is not making
core.extension:profilestrict, onlycore.extension:moduleandcore.extension:theme. And modules and themes should really exist on disk, which is all thatExtensionAvailableConstraintValidatoris checking and its test coverage seems solid? 🤓(@borisson_ shared in-person the anecdote that in his Drupal dayjob, they NEVER uninstall modules and remove it from the codebase in a single deployment for clients. Because that'd make it impossible to run the uninstall hooks!)
So: what scenario are you thinking of that could potentially break?
Comment #80
mondrakeJust rebased to see if the new deprecation for Kernel tests missing the
#[RunTestsInSeparateProcesses]attribute triggers as expected. #3546029: Ensure that #[RunTestsInSeparateProcesses] attribute is added to all Kernel testsSorry for the noise.
Comment #81
nicxvan commentedThanks!
For 1:
No, but don't we want to give people a chance to clean it up so why wouldn't we follow the normal deprecation pathway?
Yes, does the deprecation warning not show up?
Yes, but we rely on profile extension discovery here so if we got something wrong the validator will think an extension doesn't exist when the system actually knows about it. That is what concerns me here, there was a bit of churn around that point as far as I can see.
Neither do I in general, I've certainly seen it done unintentionally, and this would break more than just not running the uninstall hook right?
Since Drupal now thinks the module is installed, but it's not and config import can't run your site will blow up, right? So this makes the catch 22 break until you add the files back and run the import again. Where previously you just missed the uninstall hook which you could fix in the same way but your site would load at least.
For 2:
I'll read that issue in more depth when I have a moment.
For 3:
My concern is turning this on in a minor without deprecating for notice to give people a chance to resolve the issues.
Comment #82
borisson_I talked with @alexpott and @Wim Leers at drupalcon about this.
Config validation does not run during normal operation of a site. And these checks are also replicated in the installer.
When using a normal workflow to do imports and exports of config, the importer already has several special checks for the core.extensions and it will already yell if a file is invalid.
This is replicating a lot of that logic (but not all).
If you can point us to a place where the validation happens during import/normal runtime that affects this - please set this back to needs work. I think all the other points in this MR have been answered so putting it back in rtbc.
Comment #83
alexpottThis is not quite correct - they are replicated in the ConfigImporter - see all the code in \Drupal\Core\EventSubscriber\ConfigImportSubscriber
Comment #84
nicxvan commentedOk I think I was able to test this in a way that helps me answer my concern.
Here is what I did to set up a config database and config for testing:
Test 1
Test 2
Test 3
Test 4
As far as I can tell the behavior I was concerned about does not happen and there seems to be no behavior difference between 11.x and this branch so we can remove my objection for that bit.
I also took a look through the validation pretty carefully and as far as I can tell that bit is correct too.
Comment #85
mondrakeThere are deprecation failures.
Comment #86
godotislateTried fixing the tests by adding
#[RunTestsInSeparateProcesses].There's one test failure remaining that is weird and is also happening on my local against HEAD, so it's likely unrelated.
Comment #87
bbralaBlockFilterTest seems unrelated, since it was annotation only i'm setting back to RTBC
Comment #88
godotislateWell BlockFilterTest passes now, so I guess it is just super flakey, even locally.
Comment #89
alexpottCommitted 690bbe4 and pushed to 11.x. Thanks!
Comment #94
berdirThis added a usage of the contact module which is being removed from core. I don't see contact mentioned here, so I assume we just picked a random module? See #3557138: Remove use of Contact from ExtensionAvailableConstraintValidatorTest
Comment #95
bbralaYeah was a random module.