- Issue created by @jrockowitz
- πΊπΈUnited States jrockowitz Brooklyn, NY
I'm opting to put my praise in the first comment. This is the only major issue I could find with recipes, and I am experimenting with some complex recipes and config actions. Understanding the public API took very little effort, and the internals of the Recipe and ConfigAction code are pristine. Outstanding and inspiring work!!!
I'm switching this issue's priority to 'major' because this could cause some unexpected issues/challenges as more contrib modules are included in recipes. At the same time, if people know about this problem and it is an accepted nuance, feel free to change it back to 'Normal.'
- πΊπΈUnited States jrockowitz Brooklyn, NY
I tried my best to find similar tickets before I created this ticket. Now, I am finding a few more related tickets to this ticket.
π Document responsibility for required extension-provided configuration Needs review provides background on how recipes install modules and configuration.
- πΊπΈUnited States jrockowitz Brooklyn, NY
I have worked with recipes and the install behavior for the past few days. A possible compromise could be to allow a recipe to declare modules as 'dependencies' and modules that will be 'installed' (and overridden).
# The modules below must be enabled before the recipe is applied. dependencies: - field - node - taxonomy - views # The modules below will be installed and overridden as a recipe is applied. install: - pathauto
I know I am weighing in on something that has been thought about and debated for a . I hope this feedback helps.
- π¬π§United Kingdom alexpott πͺπΊπ
Thanks for filing the issue and thanks for comment #2.
WRT to the issue summary - setting module weight should never be inside a config sync check - the use-case for someone else setting module weight and having it different in different environments is a recipe for production only bugs.
The way recipes install modules is different and yes we have had these discussion before. The way a recipe installs a module without it's configuration entities is I guess surprising but this is exactly what happens when a module is installed during a config sync so a module should support it. The ability to not install a module's provided configuration entities is key to recipe functionality and therefore the decisions made that underpin this are unlikely to be changed.
I guess the issue here is that this surprised you and therefore this points to the fact that we should make this clearer, perhaps in the recipe author guide - https://git.drupalcode.org/project/distributions_recipes/-/blob/1.0.x/do....
- πΊπΈUnited States jrockowitz Brooklyn, NY
I appreciate your explanation because I did not fully recognize how a module is installed via config sync and UI as two different situations a module maintainer needs to account for.
As a recipe author, I would want some modules installed as expected; for others, I want full control over how a module is installed.
For example, I want to know if the module (like paragraphs) is installed AS-IS so that I can create a new paragraph type. I don't want to worry about the default configuration entities related to the paragraph.
The ability to not install a module's provided configuration entities is key to recipe functionality and therefore the decisions made that underpin this are unlikely to be changed.
We should not change the current 'config sync install' workflow; I am suggesting offering the other 'default install' workflow.
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
If a recipe does not use `config.import.module: '*'`, a module could be updated to include a new config entity, but it would not be installed via the recipe. This issue is noted via #3311155: Exclude rather than include configuration
Just because a module is updated to include a new config entity doesn't mean the recipe author absolutely wants to include it if they did not use the * wildcard to import the config. It would be up to the recipe maintainer to decide to include it or not. Recipes are very declarative with that respect.
WRT the example module attached.
For clarity, I just want to point out that modules should not contain recipes. Recipes should be in their own packages and kept along side other recipes. We suggest in a recipes folder above webroot.
- πΊπΈUnited States jrockowitz Brooklyn, NY
Just because a module is updated to include a new config entity doesn't mean the recipe author absolutely wants to include it if they did not use the * wildcard to import the config.
I agree; yet, as a recipe author, for some modules, I want to know if the module is already installed or have it installed, and do not care about the installation configuration details. For other modules, I want to override and tweak the default installation configuration details.
π Error when installing a recipe that has configuration files already in the system, even if there is no difference Postponed: needs info feels like a related issue but is only addressing identical configuration files.
I will do my best to come up with other examples.
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
For other modules, I want to override and tweak the default installation configuration details.
That is what config actions are for.
π Recipes' imported config is validated too strictly by default Active was merged this morning. This will help out a lot making recipe application more lenient.
This issue above will help close a lot of issues, but you may find more discussions and similarities on our Roadmap, #3446089: [Meta] Recipes Phase 2 Roadmap β
- πΊπΈUnited States jrockowitz Brooklyn, NY
@thejimbirch I switched to 10.4, and π Recipes' imported config is validated too strictly by default Active solved most of my issues. Thank you.
I am still working through the issue in #6 where some modules are not installing as expected because a recipe installs a module via a 'config sync workflow" and not the UI/Drush 'install workflow'.
I will post more information as I work through the problem.
- π¬π§United Kingdom lstirk
We are also facing an issue with install hooks not running due to the $is_sync flag. We are wanting to create a recipe for the domain modules. The domain module install hook adds field to all content entity bundles. I don't think we can save that config into the recipe as each site may have different content types. Is there a way around this?
- πΊπΈUnited States jrockowitz Brooklyn, NY
I am currently experimenting with a not-great workaround: I am using a config action to trigger the install hook without $is_sync=TRUE.
I am sharing the workaround to help illustrate the problem; I do not feel this is a good solution.
Here is the SchemaDotOrgExecuteInstallHook config action and here is an example of it being used to trigger schemadotorg_taxonomy_install(FALSE);.
install: - schemadotorg_taxonomy config: strict: false import: schemadotorg_taxonomy: '*' actions: core.extension: executeInstallHook: - schemadotorg_taxonomy
@see https://git.drupalcode.org/sandbox/jrockowitz-3479651/-/blob/1.0.x/schem...
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
The domain module install hook adds field to all content entity bundles. I don't think we can save that config into the recipe as each site may have different content types. Is there a way around this?
First, create or import the field storage config(s)
Next, use the
addToAllBundles
config action to add that field storage to all the content types essentially creating the field instances.Lastly, use a wildcard on the form/display configs
core.entity_form_display.node.*.default:
That will hit the default form on all content types for example. You canHere is how I did it in the SEO recipe in Drupal CMS.
actions: # Add SEO fields to all content types that are installed. field.storage.node.field_seo_analysis: addToAllBundles: label: 'SEO Analysis' description: 'Pick the main keyword or phrase this page is about.' field.storage.node.field_seo_description: addToAllBundles: label: 'SEO Description' description: 'Write a description for search engines and social media sites.' field.storage.node.field_seo_image: addToAllBundles: label: 'SEO Image' description: 'Upload an image to be used when the page is shared on social media sites.' field.storage.node.field_seo_title: addToAllBundles: label: 'SEO Title' description: 'Use this field to overwrite the default HTML page title for SEO.' # Configure the fields on the edit forms. core.entity_form_display.node.*.default: # Configure field group. setThirdPartySettings: - module: field_group key: group_seo value: children: - field_seo_title - field_seo_description - field_seo_image - field_seo_analysis label: 'Search Engine Optimization (SEO) Information' region: content parent_name: '' weight: 50 format_type: details format_settings: classes: '' show_empty_fields: false id: group_seo label_as_html: false open: false description: '' required_fields: false setComponents: - name: field_seo_analysis options: type: yoast_seo_widget weight: 18 region: content settings: render_theme: olivero render_view_mode: default edit_title: 0 edit_description: 0 - name: field_seo_description options: type: string_textarea weight: 16 region: content settings: rows: 5 placeholder: '' - name: field_seo_image options: type: media_library_widget weight: 17 region: content settings: media_types: { } - name: field_seo_title options: type: string_textfield weight: 15 region: content settings: size: 60 placeholder: ''
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
Is there anything else that needs to be done here or can this issue be closed as works as designed?
- π¬π§United Kingdom alexpott πͺπΊπ
I think the biggest issue with the current approach that's been pointed out elsewhere by @Berdir is the language module and the locked entities: language.entity.und and language.entity.zxx. These entities need to be created during an install or else the module does not work as expected. The current recipes approach is built on the assumption that modules can work with 0 to n entities but this is not true of the language module - it requires these entities.
This prompts us to consider changing our approach to ensure that installing a module creates everything in the config/install folder BUT unfortunately much of what is config/install for some modules is not actually required at all - have a look at node module's config/install folder. I do not think recipes should have to work out how to undo this.
I'm not sure what the fix for language should be. We could create the locked entities during hook_install() but then we'd need to consider how to make the translatable strings in those config entities discoverable. Or we add something to the info.yml file to list recipe required config - which feels very very icky too.
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
If the recipe author includes the importing of
language.entity.und
andlanguage.entity.zxx
in their recipe, is that enough? Or does the language module not install correctly because the config entities are imported after the install? - π¬π§United Kingdom alexpott πͺπΊπ
The problem is caused by the entities not existing when \Drupal\language\ConfigurableLanguageManager::getLanguages() is triggered and then \Drupal\Core\Language\LanguageManager::getDefaultLockedLanguages() results in the locked languages having the wrong weight because they key of the default language weight. @berdir can probably provide a better explanation.
- π¨πSwitzerland berdir Switzerland
Yes, even installing the language module with all config doesn't help because it happens too late, *if* the recipe also adds a specific language. It works if not.
So my workaround is to install language with its config first in a separate recipe and then add the specific language.
I think recipes that add specific languages are fairly uncommon (my use case is setting up a demo site), I also argued against making that a recipe with input action in Drupal CMS, as we have a fairly obvious UI for adding languages that is IMHO clearer than having to re-apply a recipe. And adding languages typically kicks of a large and slow batch process to import translations, update config and what not.
But it's still a very ugly workaround.
I still also think that recipes should install non-optional configuration of modules, but then I also think that we might need another mechanism for modules for something like *recommended* configuration. So only things that are required for a module to function would be in config/install while optional things like admin views and so on would be in config/recommended. Which might actually already kind of work if we put it in config/optional.
- πΊπΈUnited States thejimbirch Cape Cod, Massachusetts
Moving to Drupal core into the Recipes system component.