Recipes: the Future of Drupal Site Building | GovCon 2024
mandclu
369 views
52 slides
Aug 14, 2024
Slide 1 of 52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
About This Presentation
Recipes are a new capability for Drupal, allowing sites to add robust features in just a few clicks. Learn about what we can use today, what's in progress, and how you can help!
Size: 8.45 MB
Language: en
Added: Aug 14, 2024
Slides: 52 pages
Slide Content
Recipes:
The Future of Drupal
Site Building
Martin Anderson-Clutz
Senior Solutions Engineer, Acquia
Agenda
Why recipes?1
The big news2
Anatomy of a recipe3
Applying recipes4
What we’re working on5
4
Live demo - let’s get cooking!6
Why recipes?
Distributions and
install profiles
have some issues
●They are difficult to keep updated
●They cannot be added after starting
your project
●They can't be mixed and matched with
other sets of functionality
●They are hard to discover before you
install Drupal
The problem:
6
Recipes
●A lightweight way to quickly add
configuration to your site
●They can install modules but do not
have any code of their own
●Composable from other Drupal recipes
●Applied to Drupal sites, they are not
installed
●Easy to share
●Do not lock sites in
The solution:
7
The
big
news
Phase 1 of the
roadmap is
complete!
The phase one goal was to create the ability
to apply an arbitrary recipe to a Drupal
install. Phase two is now on the works!
The Big Update
Released in Drupal
10.3 and 11 as an
experimental API
9
Anatomy of a recipe
10
●Recipe class to read recipe.yml and composer.json
●Enable a recipe to apply other recipes prior to by
applied itself
●Create recipe runner to process drupal-recipe
recipe.yml files to install listed drupal extensions
without their configuration entities
●Extend recipe runner to allow recipe.yml to select
configuration from installed modules
The roadmap - phase 1
●Extend recipe runner to create
configuration provided in the recipe's
/config folder
●Add the ability to define configuration
actions in recipes
●Extend recipe runner to create content
provided in the recipe's /content folder
●Add configuration actions API
Timeline of recipes
DrupalCon Portland 2022:
Dries presents the idea of
starter templates to help
ambitious site builders to quickly
and easily build out solutions
DrupalCon Prague 2022:
Alex Pott demonstrates a
proof of concept that
harnesses yml files to extend
what we already have in
config to create a recipe
2024:
After months of work and QA
by many contributors, the
Standard Drupal Profile as a
recipe is completed
May 2022 Aug 2024
2022 to 2024:
The Config Actions API is added
in order to allow us to
manipulate config in various
ways and has been evolving
continuously
2024:
Config validation is
introduced, allowing us to
roll back the recipe if the
configuration doesn’t
validate properly.
11
2024:
Phase 1 is completed and
the MR is created to add
Recipes to core
Phase 2 begins
2024:
Minimal and Umami
profiles are also
converted into recipes
2024:
Drupal 11 is released,
containing many more
configuration actions
Anatomy of
a recipe
config
content
composer.json
recipes
install
config:import
config:actions
Anatomy of a recipe
13
recipe.yml
●recipes
●install
●config:import
●config:actions
{…}
14
●Set type as drupal-recipe
●Add module, recipe, or theme
dependencies
●Suggest recipes that users
might want to apply
Anatomy of a recipe
15
{
"name": "fourkitchens/sous-paragraphs" ,
"description": "A collection of recipes and
configuration for Sous with Paragraphs." ,
"keywords": ["recipe", "Drupal recipes",
"drupal recipe"],
"type": "drupal-recipe",
"require": {
"fourkitchens/sous-content-types" : "dev-main",
"fourkitchens/sous-paragraph-types" : "dev-main",
"drupal/paragraphs_features" : "^2.0@beta"
},
"suggest": {
"fourkitchens/editorial" : "A default editorial
workflow."
}
}
composer.json
name
description (optional)
type (optional)
●Groups related Drupal
recipes together.
recipes (optional)
●List other recipes to be
installed with it.
Anatomy of a recipe
16
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types
recipe.yml
install (optional)
●List modules or themes
to install, if they are not
already
●During the install, simple
configuration from the
new modules are
imported
Anatomy of a recipe
17
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types
install:
- paragraphs_ee
- paragraphs_features
recipe.yml
config:import
●Import all available config
from a module: “*”
●Specify which
configuration you want to
import
●If you don’t include
instructions here, only
simple config will be
imported
Anatomy of a recipe
18
name: 'Sous Paragraphs'
description: 'A collection of recipes and configuration
for Sous with Paragraphs.'
type: 'Site'
recipes:
- sous-content-types
install:
- paragraphs_ee
- paragraphs_features
An action has 3 parts:
1.Configuration entity id
2.The action: must be one that's
declared for the entity type of
the configuration entity
3.Action arguments, depending on:
a.number of arguments that
the action takes, and
b.whether the action is in the
singular or plural form
Anatomy of a recipe
19
name: 'Sous Emulsify'
description: 'A recipe that installs Emulsify
dependencies and sets Emulsify as the default
theme.'
type: 'Site'
install:
- components
- emulsify
- emulsify_tools
config:
actions:
system.theme:
simpleConfigUpdate:
default: emulsify
recipe.yml
#[ConfigAction(
id: 'permissions_per_bundle ',
entity_types: ['user_role'],
deriver: PermissionsPerBundleDeriver::class ,
)]
final class PermissionsPerBundle implements
ConfigActionPluginInterface,
ContainerFactoryPluginInterface {
// Class properties and methods.
}
Config actions API
There are two sets of actions currently
supported by the API:
1.Actions that can be applied to
configuration of any configuration
entity type
2.Actions declared for methods of
specific configuration entity types
○Created by adding PHP attributes
to a method declaration
Anatomy of a recipe
20
simpleConfigUpdate
●It can be used to make updates to any
configuration value
createIfNotExists
●It can be used to conditionally create a
config entity
setComponent
●Add a component (e.g. field) to a
configuration entity
Anatomy of a recipe
21
create
●It can be used to create a config entity.
setThirdPartySetting
●Allows the recipe author to set third-party
settings values for any config entity that can
have third-party settings
●Helpful for modules like Layout Builder and
Scheduler that use these settings to provide or
change functionality.
Globally applicable entity actions
And more!
grantPermissions
Config entity type: role
●Allows you to grant permissions to a role
addNodeTypes, addTaxonomyVocabularies
Config entity type: workflows
●Allows you to add bundles into your
content moderation workflow
Anatomy of a recipe
22
addToAllBundles
Config entity type: field
●Allows you to add a field to all content types
●If the field already exists on a content type, it will
skip that content type
addItemToToolbar
Config entity type: editor
●Allows you to add a button to a CKEditor5
toolbar
Config entity actions
And many more!
Add the same permission(s) to all user roles
actions:
user.role.*:
grantPermissions:
- 'access content'
Affect every view display of every content type
actions:
core.entity_view_display.node.*.*:
setComponent:
name: field_tags
options:
type: entity_reference_label
…
Anatomy of a recipe
23
Change settings on every instance of a field
actions:
field.field.media.*.field_tags:
simpleConfigUpdate:
foo: bar
Create a view display (i.e., enabling a view
mode) for every content type
actions:
core.entity_view_display.node.*.foo:
createIfNotExists:
# The contents of the view display here...
Config entity wildcards
Idempotency
You should be able to reapply a recipe to the
same site an unlimited number of times
●Some config should be provided using
config actions like createIfNotExists
●Will probably need testing
Anatomy of a recipe
24
Keep granular
Better to have a collection of recipes
●Apply other recipes that are dependencies
Publish!
Directly to Packagist, or to drupal.org as a general
project
Recipe best practices
Anatomy of a recipe
25
●A Drupal recipe can have a content
directory. All content in this directory will be
created after the configuration is installed.
●For this, functionality has been taken from
the default_content module and added
to core. Specifically, the functionality that
imports the content files is being added to
core. Currently if you want to generate the
content files as YAML that are needed to
make this work, you need to use the
default_content module.
Content
image?
Anatomy of a recipe
26
●Export content as YAML from a Drupal
project using the default_content module
●Add those YAML files to the /content
folder in the structure that
default_content generates
●The content will be validated and
imported when the recipe is applied
Add content
to a recipe
image?
Recipe runner
order
1.Apply other recipes
2.Install modules and themes
3.Import specified configuration
4.Import provided configuration
5.Apply configuration actions
6.Import content
Applying recipes
31
RECIPES in core
Recipes are conceived as
composable, with any
given recipe often
requiring a chain of other
recipes. But there's little
practical sense as yet of
just how this would work,
or of what recommended
patterns might be.
32
Core install
profiles as sets
of recipes
The process of converting the standard,
minimal, and umami install profiles to recipes
allowed us to discover how a set of recipes
can be composed to give us a specific result.
CLI install of Drupal
using recipes
Drupal can now be installed from a recipe
without the need for an install profile!
RECIPES in core
if a site that used
Minimal initially
applies any given
recipe from Standard,
it should end up with
something new that is
ready to use.
● article_content_type
● page_content_type
● feedback_contact_form
● basic_html_format_editor
● full_html_format_editor
● editorial_workflow
● image_media_type
● document_media_type
[and more]
34
What recipes make up
Standard-the-Recipe?
Umami install profile
as a set of recipes
●Converting Umami was similar to
converting Standard
●Because Umami is a lot more specialized
than standard, it is expected to yield
fewer building block recipes than
Standard did, and will be less
composable
●It is intended to be a self-contained
demo rather than a set of reusable parts
RECIPES in core
35
New sets of recipes
should build on
core recipes
You can require a core recipe into a new
recipe simply by listing it in the recipes
section of recipe.yml.
RECIPES in core
… pretty much every
conceivable set of
recipes should build on
the recipes in core. Doing
so is the best and easiest
way to make sure your
recipes integrate well
with others
36
What we’re
working on
Unpacking
recipes
●Recipes might require dependencies to
be installed.
●If a recipe is removed, its dependencies
will be also removed.
●Unpacking recipes’ dependencies solves
this issue.
Applying recipes
38
Config
validation
●When applying a recipe, there was no
real promise that it would work.
●Even if a recipe don’t blow up while
being applied, it would just leave a mess.
●This is now solved with validating
validatable configuration.
●Creating config storage checkpoint
before applying a recipe.
What we’re working on
39
Making config
actions more
dynamic
When you used to create recipes and needed
to apply a certain action to multiple bundles,
you’d have to create multiple lines of the same
action to the list of bundles. Now, thanks to the
community, we are able to run more dynamic
config actions to support wildcards.
What we’re working on
40
user.role.*:
grantPermissions:
- 'access content'
field.field.media.*.field_tags:
setSettings:
auto_create: false
user.role.media_creator:
grantPermissionsPerMediaType:
- 'create %bundle media'
- 'edit own %bundle media'
- 'delete own %bundle media'
field.storage.node.field_tags:
instantiateOnAllBundles:
label: Tags
description: 'Add some tags here.
What we’re working on
41
●Building UI for applying recipes
●Hosting recipes on Drupal.org
●Recipe discovery
●Drupal recipe testing
The roadmap - phase 2
●Recipe unpacking in Core
●Ensure that recipes cannot be applied in
parallel
●Allow for user input before applying
e.g. Google Maps API key
placeBlockInDefaultTheme,
placeBlockInAdminTheme
Config entity type: block
●Theme name determined
programmatically
●Pass an array of regions
with a fallback
●Use ‘first’ or ‘last’ keywords
for placements within
region
Anatomy of a recipe
42
Actions for
blocks
config:
actions:
block.block.powered_first_default:
placeBlockInDefaultTheme:
id: powered_first
# The region accepts an array keyed by theme name.
region:
bootstrap: footer
gesso: page_bottom
olivero: footer_top
# Fallback if no match found in the region array.
default_region: content
# Place before any blocks already in the region.
position: first
plugin: system_powered_by_block
Recipe maintainer
and end user
documentation
●Documentation currently lives in gitlab.
●There is a lot of work to be done to get
the documentation ready for
maintainers and end users.
●This is a great way to start contributing
to recipes
What we’re working on
43
Graphic here?
Recipes
Cookbook
The Recipes Cookbook is a collection of
contributed recipes. Get ideas and share
ideas for:
Stupendous
Date Tricks
Tomorrow at 11:00am
Mobomo Room
Expanded Demo
47
Join the
initiative
Get involved!
●Recipe maintainer and end user
documentation needed
●Developers and testers wanted
○test coverage
●Recipes wanted
●#recipes in Drupal Slack
●Join us in Slack meetings every other
Tuesday at 1600 UTC
●Join us at contrib day at DrupalCon
Join the initiative
48
49
Special
thanks to
@alexpott, @wimleers,
@phenaproxima, @thejimbirch
@bircher, @smustgrave, @narendraR…