Problem/Motivation

Over in #3086824: SearchBlock plugins need to add in dependencies on the search page they submit to we discovered that if profile configuration in it's config/install directory depends on optional configuration provided by a module (or a theme) it'll fail with UnmetDependencies exception.

Proposed resolution

Install all optional configuration available before installing the install profile and then on subsequent module installs (such as the profile) install optional configuration alongside the the config/install configuration (as we do during regular module install outside of the Drupal installer).

Remaining tasks

User interface changes

None

API changes

None

Data model changes

None

Release notes snippet

The order optional configuration is installed during a site install has changed. If you maintain an install profile that creates content during your install profile's install hook. See Optional configuration from modules is installed before the install profile for more information.

Comments

alexpott created an issue. See original summary.

andypost’s picture

Status: Active » Needs review
StatusFileSize
new1.67 KB

Initial stub to test

alexpott’s picture

StatusFileSize
new6.05 KB
new7.17 KB

So here's the fix. What I don't understand at the moment is how the profile's optional configuration is being installed... we need to work that out before proceeding.

The last submitted patch, , failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 3: 3087130-2.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new1.57 KB

So this is still broken but now we're in interesting circular dependencies issues. The umami block has a dependency on content but that content is only created after the block in installed. With this it happens the other way around. It works in HEAD because optional config is installed after the profile but what umami is doing is only possible of the current code in install_install_profile and installing all optional configuration after the install profile.

We could do

  \Drupal::service('config.installer')->installOptionalConfig();
  \Drupal::service('module_installer')->install([$install_state['parameters']['profile']], FALSE);
  \Drupal::service('config.installer')->installOptionalConfig();

in install_install_profile() and that would be green. But the patch has a massive advantage in that this also fixes optional config install for modules installed after install_install_profile(). Distributions like Thunder have forms after profile installation that currently won't do a default config install. And in fact this happens in head with the option that enables the update module in the site configure form - the only reason we don't have a critical bug is that the Update module does not have any optional configuration.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

andypost’s picture

I recall there's config event to react on missing content for the config, but it looks like not quickfix, I used to explore it in #2849128: Add handling of ConfigEvent::IMPORT_MISSING_CONTENT
Also umami using migrations to import content so the content should go last

alexpott’s picture

What's interesting is that I tried to do

  // Enable the demo content module. This can't be specified as a dependency
  // in the demo_umami.info.yml file, as it requires configuration provided by
  // the profile (fields etc.).
  \Drupal::service('module_installer')->install(['demo_umami_content'], TRUE);

  // Resave the block to re-establish content dependencies.
  \Drupal::service('plugin.manager.block')->clearCachedDefinitions(); // or even drupal_flush_all_caches() so there must be some static cache that's getting in the way. Interesting.
  Block::load('umami_banner_home')->calculateDependencies()->save();

i.e. re-save the block to fix the dependencies after installing demo_umami_content and it didn't work.

alexpott’s picture

StatusFileSize
new2.39 KB
new10 KB

Ah I just didn't read carefully enough - resaving the block does fix the dependencies - there's more than one block that we need to do this for. Here's a hopefully green patch!

This patch will fix a hard to find bugfix in Thunder which installs all optional configuration at the end of the install to fix this bug - see https://github.com/BurdaMagazinOrg/thunder-distribution/blob/8.x-2.x/thu...

andypost’s picture

Status: Needs review » Needs work
+++ b/core/modules/media_library/src/Form/AddFormBase.php
@@ -699,12 +701,20 @@ public function updateLibrary(array &$form, FormStateInterface $form_state) {
+    $response->addCommand(new MessageCommand($announcement, '#media-library-file-messages'));
...
+    $response->addCommand(new AnnounceCommand($announcement, 'assertive'));

+++ b/core/modules/media_library/src/Form/FileUploadForm.php
@@ -175,6 +175,12 @@ protected function buildInputElement(array $form, FormStateInterface $form_state
+      '#id' => 'media-library-file-messages',

looks like other's patch changes

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new2.04 KB
new7.51 KB

Removed extraneous code.

Status: Needs review » Needs work

The last submitted patch, 12: 3087130-12.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review

Unrelated random fail.

andypost’s picture

Other then follow-up for dependencies it looks like RTBC... but needs other pair of eyes

+++ b/core/profiles/demo_umami/demo_umami.install
@@ -64,4 +65,10 @@ function demo_umami_install() {
+  // Recalculate dependencies to get out of circular dependencies between config
+  // and content.
+  foreach (Block::loadMultiple(['umami_banner_home', 'umami_banner_recipes', 'umami_disclaimer', 'umami_footer_promo']) as $block) {
+    $block->save();

I bet it needs todo and follow-up to debug why dependencies require resave

alexpott’s picture

I bet it needs todo and follow-up to debug why dependencies require resave

I don't think a follow-up is needed. This is plain chicken and egg. Config installation occurs during a module install before it's hook_install is done. So when demo_umami_content is installed during the profile's install hook. We create the optional block config but the content does not yet exist. Therefore the block dependencies cannot be correctly calculated. But content dependencies are "soft" so we allow them to be removed with no other changes to the block. Then after demo_umami_content's hook_install has fired the content exists so if we re-save them the dependencies are fixed. There's no simple way to fix this unless we can think of a way to create the content before the configuration.

alexpott’s picture

StatusFileSize
new1.87 KB
new7.51 KB

So #16 opens an interesting fix for this. Modules can listen to their own preinstallation so we can import content then and then we have a better flow without having to re-save the blocks.

alexpott’s picture

Issue summary: View changes
rensingh99’s picture

Assigned: Unassigned » rensingh99
alexpott’s picture

Assigned: rensingh99 » Unassigned

@rensingh99 if you assign yourself an issue it'd be great if your comment says why. Going to unassign for now - if there are things you think the issue needs done it'd be great if you can add that to your comment.

rensingh99’s picture

Hi Alex,

The task status is `Needs Review`. I have some time which I can dedicate to review.
Hence I assigned it to myself. Please advise if i made a mistake.

Thanks
Ren

alexpott’s picture

Hi @rensingh99 normally people assign issues to themselves to state something like "I'm going to roll a new patch here so talk to me before doing the same thing" - it case of doing a review many people can do that at the same time so assigning yourself an issue is not necessary. The key thing is when assigning yourself an issue is to state what you're going to do otherwise assigning yourself an issue might stop someone else from doing a review or doing other needed work.

rensingh99’s picture

Status: Needs review » Reviewed & tested by the community

Hi,

I have created a custom profile and I have added all config install files for one content type except one dependent install file into profile_name/config/install.

That dependent config file I have added into module. And added that module in profile.info.yml in the list of install-module.

At the time of installing the module, I have gotten below error.

But after applying the patch. I have not got this error.

So, this patch is working great.

Thanks,
Ren

chr.fritsch’s picture

I also tested this patch with our Thunder distribution and I can confirm that it works. We can now get rid of some config install weirdness from the distribution.

If possible, I would also vote for a backport to 8.8.x

rensingh99’s picture

Issue summary: View changes
StatusFileSize
new44.19 KB

I had posted this image in comment no#23. But somehow it was disappeared. So I was trying to place into comment #23.

chr.fritsch’s picture

@rensingh99 Could you please explain your screenshot. Just posting some random screenshot without any explanation is not useful.

Do you get this error when you apply the patch to your project? If so, could you please provide some steps for how we can reproduce your problem.

chr.fritsch’s picture

Ah sorry, @rensingh99. Your screenshot belongs to your comment 2 weeks ago. Now I get it. My fault 🤦🏻‍♂️

So I assume the screenshot shows the problem you had before applying the patch.

rensingh99’s picture

@chr.fritsch Yes Thank you

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

No longer applies?

aleevas’s picture

Status: Needs work » Needs review
StatusFileSize
new7.43 KB
new5.35 KB

17 was re-rolled

alexpott’s picture

StatusFileSize
new683 bytes
new7.47 KB

We need the test module to be Drupal 9 compat too.

Status: Needs review » Needs work

The last submitted patch, 31: 3087130-2-31.patch, failed testing. View results

alexpott’s picture

Status: Needs work » Needs review

Ah we need #3096609: Allow contrib test modules to not need a core or core_version_requirement key because we copy the module out of the core directory in \Drupal\Tests\config\Functional\ConfigInstallProfileUnmetDependenciesTest - or we can add core_version_requirement: '*' but let's hope that issue lands.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

#3096609: Allow contrib test modules to not need a core or core_version_requirement key landed so we're back to rtbc as the re-roll has been completed.

hchonov’s picture

Do we have a test ensuring that if an optional configuration is overridden in the profile then it will be still installed correctly?

alexpott’s picture

@hchonov check out ConfigInstallProfileOverrideTest - much overriding of all the thing going on there!

Percy101’s picture

Issue tags: -Needs reroll

Patch applied cleanly

adam-delaney’s picture

Patch #31 fails to apply for Drupal 8.8.2

alexpott’s picture

@adam-delaney you could safely ignore the changes to core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install but this patch is targeting 8.9.x and 9.0.x and applies there just fine.

catch’s picture

+++ b/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install
@@ -8,10 +8,12 @@
 
 /**
- * Implements hook_install().
+ * Implements hook_module_preinstall().
  */
-function demo_umami_content_install($is_syncing) {
-  if (!$is_syncing) {
+function demo_umami_content_module_preinstall($module) {
+  if ($module === 'demo_umami_content' && !\Drupal::service('config.installer')->isSyncing()) {
+    // Run before importing config so blocks are created with the correct
+    // dependencies.
     \Drupal::classResolver(InstallHelper::class)->importContent();
   }

This makes me wary about an 8.9.x backport.

Patch looks good for 9.0.x though.

danielveza’s picture

Slightly unrelated, if we're having to call \Drupal::service('config.installer')->isSyncing() inside hook_module_preinstall, wouoldn't it make sense to add the $is_syncing param as we do for hook_install etc?

Happy to open a seperate issue for this.

alexpott’s picture

@DanielVeza good idea. All the install and uninstall hooks should have this param and document the considerations.

alexpott’s picture

@catch thanks for review this. Re #40 - i think it is okay to put this in 9.0.x only but I think the benefits of putting this in 8.9.x outweigh the negatives. Just this is a tiny bit disruptive for profiles that have a module that installs default content where that default content is depended on by configuration it provides (i.e content block placements). But I think that this situation is extremely rare. Unlike the situation of profile configuration depending on optional configuration provided by modules it depends on. However I'd be happy if this fix makes it into any branch :)

catch’s picture

We need to document #44 in a change record and release note, regardless of whether this gets backported.

alexpott’s picture

Added a change record: https://www.drupal.org/node/3118908 and a release note.

  • catch committed aeae01b on 9.0.x
    Issue #3087130 by alexpott, aleevas, rensingh99, andypost, chr.fritsch,...
catch’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

Committed aeae01b and pushed to 9.0.x. Thanks!

Moving to 8.9.x, I'm still not sure what I think about that.

xjm’s picture

Issue summary: View changes
chr.fritsch’s picture

Do we have any chance to get this into D8.9?

neslee canil pinto’s picture

StatusFileSize
new7.47 KB

Patch for 8.9.x

alexpott’s picture

@Neslee Canil Pinto the patch in #31 applies to 8.9.x and has been tested against it.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

xjm’s picture

Version: 9.1.x-dev » 9.0.x-dev

Well it definitely doesn't belong against 9.1.x., so marking back to fixed against 9.0.x.

xjm’s picture

Status: Patch (to be ported) » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.