Contributor Training: Advanced Add-On Techniques
![Add-on puzzle pieces](/img/blog/2024/07/add-on-puzzle-pieces.png)
Here’s our July 10, 2024 Contributor Training on Advanced DDEV Add-On Techniques:
The basics of creating a DDEV Add-on are super easy, you can click a button on the Add-on template and you’re off and running. There are more details in the Add-on Template, in the DDEV docs, and in the original add-on training.
Adding project (or global) custom commands
An add-on can easily add one or more project custom commands. People have made add-ons specifically to add just one project custom command. It seems like a waste, but it’s not. It gives your custom command(s) a home, an issue queue, and an upgrade path.
An example of a project that does lots of this is ddev-drupal-contrib
, which installs several specialized web custom commands, see install.yaml.
project_files:
- commands/web/eslint
- commands/web/expand-composer-json
- commands/web/nightwatch
- commands/web/phpcbf
- commands/web/phpcs
- commands/web/phpunit
- commands/web/poser
- commands/web/stylelint
- commands/web/symlink-project
You can add to the global_files
section in the same way, but it usually makes more sense to add commands to the project, since the add-on’s scope is project-level. ddev-platformsh
installs a helper command globally:
global_files:
- commands/web/platform
Adding a Dockerfile.<add-on-name>
If your install.yaml
needs to change basic ddev-webserver
characteristics, it can add a .ddev/web-build/Dockerfile.<add-on-name>
.
envsa/ddev-pnpm
does exactly this:
project_files:
- commands/web/pnpm
- web-build/Dockerfile.pnpm
Altering the behavior of ddev-webserver
with additional config.*.yaml
An add-on can deliver both project and global configuration, and can add to or replace almost anything. For example, the justafish/ddev-drupal-core-dev
add-on installs a config.ddev-drupal-core-dev.yaml
that does a few things, including:
webimage_extra_packages: ["chromium-driver"]
Altering the behavior of ddev-webserver
with docker-compose.*.yaml
Although the most common use of adding a docker-compose.*.yaml
is to add a new service (below) it is often used to change the behavior of the web service.
For example, ddev-proxy-support
sets arguments for the build
stage inside the web container.
Creating an additional service using a docker-compose.*.yaml
One of the most common add-on uses is to create a new service, like mongo
or elasticsearch
or solr
. You can look at many of the official add-ons to see how this is done.
Examples:
See the general docs on extra services.
Interacting with users during install.yaml
installs
Although unusual, it is sometimes useful to interact with the user during the ddev get
process. For example, ddev-platformsh
checks to make sure that the PLATFORMSH_CLI_TOKEN
has been properly configured, and, if not, requests it and configures it:
pre_install_actions:
# Get PLATFORMSH_CLI_TOKEN from user if we don't have it yet
- |
if ( {{ contains "PLATFORMSH_CLI_TOKEN" (list .DdevGlobalConfig.web_environment | toString) }} || {{ contains "PLATFORMSH_CLI_TOKEN" (list .DdevProjectConfig.web_environment | toString) }} ); then
echo "Using existing PLATFORMSH_CLI_TOKEN."
else
printf "\n\nPlease enter your platform.sh token: "
fi
- |
#ddev-description:Setting PLATFORMSH_CLI_TOKEN
if !( {{ contains "PLATFORMSH_CLI_TOKEN" (list .DdevGlobalConfig.web_environment | toString) }} || {{ contains "PLATFORMSH_CLI_TOKEN" (list .DdevProjectConfig.web_environment | toString) }} ); then
read token
# Put the token into the global web environment
ddev config global --web-environment-add PLATFORMSH_CLI_TOKEN=${token}
echo "PLATFORMSH_CLI_TOKEN set globally"
fi
Checking required version of DDEV
Some add-ons may require a specific version of DDEV.
- Add a
ddev_version_constraint
to theinstall.yaml
. This version constraint will be validated against the running DDEV executable and prevent add-on from being installed if it doesn’t validate. Available with DDEV v1.23.4+, and works only for DDEV v1.23.4+ binaries:
ddev_version_constraint: '>= v1.23.4'
- Check for the existence of a DDEV “capability” using
ddev debug capabilities
. For example:
pre_install_actions:
# Make sure we have a ddev version that can support what we do here
- |
#ddev-description:Checking DDEV version
(ddev debug capabilities | grep multiple-upload-dirs >/dev/null) || (echo "Please upgrade DDEV to v1.22+ for appropriate capabilities" && false)
- Add a
ddev_version_constraint
to aconfig.<add-on-name>.yaml
. This will only fail atddev start
time, so is less pleasant. But aconfig.<add-on-name>.yaml
might have:
ddev_version_constraint: ">=v1.23.0"
Reading and using YAML files, including config.yaml (yaml_read_files)
ddev get
can read the contents of arbitrary YAML files, see docs.
For example, in ddev-platformsh
the .platform.app.yaml
is read into the platformapp
variable, and other files are read as well, see install.yaml:
yaml_read_files:
platformapp: .platform.app.yaml
services: .platform/services.yaml
routes: .platform/routes.yaml
The platformapp
variable is then used like this in the install.yaml
:
pre_install_actions:
- |
#ddev-description:check project type
{{ if not (hasPrefix "php" .platformapp.type) }}
printf "\n\nUnsupported application type {{ .platformapp.type }}.\nOnly php applications are currently supported." >&2
exit 5
{{ end }}
In addition, the ~/.ddev/global_config.yaml
is read into the variable DdevGlobalConfig
, and the project .ddev/config.yaml
is loaded into the variable DdevProjectConfig
, so any element of the global or project configuration can be used in the process of a complex install.yaml
as well.
Tips from previous trainings
A previous training in November, 2023 covered many add-on topics, including testing with bats
and debugging your tests. There you can learn about creating and testing add-ons.
Checking in add-ons
Most teams choose to check in their project .ddev
directory, and this is recommended. All metadata and other files for an add-on are stored in the .ddev
directory, so this works fine. When it’s time to update an add-on with ddev get some/add-on
, do that, check in the result, and create a pull request.
Customizing an add-on without “taking it over”
There are times that you need to override the configuration provided by an add-on. Don’t forget that you can do it without editing add-on files, thus making it possible to update the add-on without having to re-add your edits, etc.
You can add a .ddev/docker-compose.<add-on-name>_extra.yaml
to add docker-compose
capabilities, for example to change the image
tag used by the add-on.
And of course you can add a config.<add-on-name>_extra.yaml
to override what the config.<add-on-name>.yaml
may have done.
Resources
- DDEV docs on add-ons
- Previous Add-on Training
docker-compose.*.yaml
docs- ddev-addon-template README
- Learn by studying other add-ons. Official ones at
ddev get --list
and all atddev get --list --all
Contributions welcome!
Your suggestions to improve this blog are welcome. You can do a PR to this blog adding your techniques. Info and a training session on how to do a PR to anything in ddev.com is at DDEV Website For Contributors.
Join us for the next DDEV Live Contributor Training. Sign up at DDEV Live Events Meetup.