This is a DDEV add-on that prepares any project to use the DDEV local development tool combined with ce-deploy, the Ansible-based code deployment tool by Code Enigma.
Install this add-on with:
ddev add-on get codeenigma/ddev-ce-deployOnce installed, you can use the custom ddev deploy command to deploy your application using ce-deploy.
ddev deployThe deploy command supports the following flags:
--install- perform a clean installation--own-branch- specify a feature branch to use--build-id- change the build ID (defaults toddev)--verbose- additional verbosity for the Ansible output
- You have installed DDEV.
- You are running an up to date version of DDEV (at least 1.25.0)
- You are running a Mac or Linux workstation.
- To actually run the
ddev deploycommand you have created an Ansible playbook at./deploy/deploy-ddev.yml(instructions below)
Windows users can still use these tools, but you will have to follow the steps in the script manually, because the installer is a Linux shell script.
This add-on installs ce-deploy in the DDEV web container and provides a custom ddev deploy command that wraps the ce-deploy functionality.
- A
.ddev/web-build/Dockerfilethat installsce-deployon the web container - The
.ddev/web-build/provision.ymlfile theDockerfileneeds in order to install Ansible andce-deployproperly using ource-provisionserver management tool - The
ce-deploy.shscript that executesce-deployin the web container - A custom command for deploying applications,
.ddev/commands/web/deploywhich is called withddev deploy- this supports the following flag combinations:- no flags - this is a standard
ce-deploydeployment with Ansible --install- this is a clean install--own-branch- useful if you are developingce-deployfeatures, let's you specify a feature branch to use--build-id- this defaults toddevbut you can change it if you need--verbose- additional verbosity for the Ansible output
- no flags - this is a standard
There is a help message provided by the custom command which you can read by entering ddev help deploy.
Because it is a wrapper for Ansible, it cannot work if a playbook does not exist. The command expects to find an Ansible playbook at ./deploy/deploy-ddev.yml in your repository, which it will pass to ce-deploy for execution. If that playbook does not exist then the command will simply exit with an error message.
Because ce-deploy is almost infinitely flexible, how you create and manage your Ansible playbook is entirely up to you, but here is an example for a Drupal project:
---
- hosts: localhost
vars_files:
- vars/common.yml
tasks:
- ansible.builtin.import_role:
name: _init
- name: Create needed public directories
ansible.builtin.file:
path: /var/www/shared/{project_name}_ddev_default_public_files
state: directory
- name: Create needed private directories
ansible.builtin.file:
path: /var/www/shared/{project_name}_ddev_default_private_files
state: directory
- ansible.builtin.import_role:
name: composer
- ansible.builtin.import_role:
name: database_backup
- ansible.builtin.import_role:
name: config_generate
- ansible.builtin.import_role:
name: cache_clear/cache_clear-opcache
- ansible.builtin.import_role:
name: database_apply
- ansible.builtin.import_role:
name: npm
- ansible.builtin.import_role:
name: cache_clear/cache_clear-drupal8
- ansible.builtin.import_role:
name: cron/cron_drupal8
- ansible.builtin.import_role:
name: _exitAnd this is the file loaded in by the vars_files list, from the ./deploy/vars directory of the code repository:
---
# common.yml variables
# See ~/ce-deploy/config/hosts/group_vars/all in the web container for ddev defaults.
# You can override them here if necessary.
project_name: example
project_type: drupal8
webroot: web
mysql_backup:
databases:
- database: "{{ (project_name + '_' + build_type) | regex_replace('-', '_') }}" # avoid hyphens in MySQL database names
user: "{{ (project_name + '_' + build_type) | truncate(32, true, '', 0) }}" # 32 char limit
credentials_file: "/home/{{ _ce_provision_username }}/.my.cnf"
keep: 0
credentials_handling: manual
handling: none
databases:
- database: db
user: root
credentials_file: "/home/{{ ansible_user_id }}/.my.cnf"
deploy_code:
keep: 0
perms_fix_path: "web/sites/default"
drupal:
drush_verbose_output: true
sites:
- folder: "default"
public_files: "sites/default/files"
config_import_command: "cim"
config_sync_directory: "config/sync"
sanitize_command: "sql-sanitize"
install_command: "-y si"
cron:
- minute: "*/{{ 10 | random(start=1) }}"
job: cron
cachetool:
adapter: "--fcgi=/var/run/php-fpm.sock"If you are already using ce-deploy on your project then you will have an existing common.yml file that you probably want to keep intact as this will set up many of the settings for your dev/stage/prod deployments. To keep those settings you need to include a ./deploy/vars/ddev.yml file and override them where needed.
---
# ddev.yml deploy variables, overriding the common.yml settings.
# See ~/ce-deploy/config/hosts/group_vars/all for ce-deploy defaults.
deploy_base_path: "/var/www"
deploy_assets_base_path: "/var/www/shared"
# If you have overridden the *_user variables to non-standard values due to
# your server set up, you will need to explicitly override them to use the ddev
# user's username.
ansible_user: "{{ lookup('ansible.builtin.env','DDEV_USER') }}"
deploy_user: "{{ ansible_user }}"
www_user: "{{ ansible_user }}"
mysql_backup:
databases:
- database: "{{ (project_name + '_' + build_type) | regex_replace('-', '_') }}" # avoid hyphens in MySQL database names
user: "{{ (project_name + '_' + build_type) | truncate(32, true, '', 0) }}" # 32 char limit
credentials_file: "/home/{{ _ce_provision_username }}/.my.cnf"
keep: 0
maintenance_mode:
mode: drupal-core
deploy_code:
keep: 0
perms_fix_path: "web/sites/default"
drupal:
drush_verbose_output: true
sites:
- folder: "default"
public_files: "sites/default/files"
config_import_command: ""
config_sync_directory: "config/sync"
sanitize_command: "sql-sanitize"
install_command: ""
cron:
- minute: "*/{{ 10 | random(start=1) }}"
job: cron
cachetool:
adapter: "--fcgi=/var/run/php-fpm.sock"This will inherit settings like project_name and project_type so there is no need to define those in this file.
This is then included in your deploy-ddev.yml in the following way.
vars_files:
- vars/common.yml
- vars/ddev.ymlMake sure these are in the correct order. You want the common.yml file first, followed by the ddev.yml file to override variables in the common.yml file.
Here are some known issues and workarounds.
If you're deploying a Drupal application in DDEV with ce-deploy using a drupal project type can cause problems. When the DDEV project type is drupal it always wants to make the sites/default/files directory when you run ddev start. This clashes with ce-deploy, which always wants that same directory to be a symbolink link. Until we fix that you can either use project type of php and forego the drush integration from the CLI or manually remove sites/default/files after ddev start and before running ddev deploy.
Another possibility is to start the project with a type of php so that DDEV does not try to install Drupal, run ddev deploy and then switch later to a drupal project with ddev config --project-type drupal to have drush support. It will give you an error about the files directory on start, but you can ignore it.
If you are running config import to Drupal with ce-deploy you might see this error:
Site UUID in source storage does not match the target storage.
If so, go to your config sync directory and look in the system.site.yml file. Copy the uuid value in that file and then run this command:
ddev drush cset "system.site" uuid "<your-uuid>"Where <your-uuid> is the value you copied from the system.site.yml file.