Contributor Training: Advanced Add-On Techniques

July 23, 2024 5 min read

Edit this page
Add-on puzzle pieces
Ideogram.ai: Create a banner image for a tech blog, featuring three colorful puzzle pieces labeled 'Solr', 'Memcached', and 'Elasticsearch'

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 add-on 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.

  1. Add a ddev_version_constraint to the install.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.24.3"
  2. Add a ddev_version_constraint to a config.<add-on-name>.yaml. This will only fail at ddev start time, so is less pleasant. But a config.<add-on-name>.yaml might have:

    ddev_version_constraint: ">= v1.24.3"

Reading and using YAML files, including config.yaml (yaml_read_files)

ddev add-on 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 add-on 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

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. Use the contact link to ask for a calendar invitation.