├── .ansible-lint ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── release.yml │ └── stale.yml ├── .gitignore ├── .yamllint ├── LICENSE ├── README.md ├── defaults └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── composer.yml │ ├── converge.yml │ ├── molecule.yml │ ├── requirements.yml │ └── source.yml └── tasks ├── install-drush-composer.yml ├── install-drush-launcher.yml ├── install-source.yml └── main.yml /.ansible-lint: -------------------------------------------------------------------------------- 1 | skip_list: 2 | - 'yaml' 3 | - 'no-handler' 4 | - 'role-name' 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | --- 3 | github: geerlingguy 4 | patreon: geerlingguy 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 'on': 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "0 4 * * 1" 10 | 11 | defaults: 12 | run: 13 | working-directory: 'geerlingguy.drush' 14 | 15 | jobs: 16 | 17 | lint: 18 | name: Lint 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out the codebase. 22 | uses: actions/checkout@v4 23 | with: 24 | path: 'geerlingguy.drush' 25 | 26 | - name: Set up Python 3. 27 | uses: actions/setup-python@v5 28 | with: 29 | python-version: '3.x' 30 | 31 | - name: Install test dependencies. 32 | run: pip3 install yamllint 33 | 34 | - name: Lint code. 35 | run: | 36 | yamllint . 37 | 38 | molecule: 39 | name: Molecule 40 | runs-on: ubuntu-latest 41 | strategy: 42 | matrix: 43 | include: 44 | - distro: ubuntu2404 45 | playbook: converge.yml 46 | - distro: debian12 47 | playbook: converge.yml 48 | # See: https://github.com/geerlingguy/docker-rockylinux9-ansible/issues/6 49 | # - distro: rockylinux9 50 | # playbook: composer.yml 51 | - distro: debian12 52 | playbook: source.yml 53 | 54 | steps: 55 | - name: Check out the codebase. 56 | uses: actions/checkout@v4 57 | with: 58 | path: 'geerlingguy.drush' 59 | 60 | - name: Set up Python 3. 61 | uses: actions/setup-python@v5 62 | with: 63 | python-version: '3.x' 64 | 65 | - name: Install test dependencies. 66 | run: pip3 install ansible molecule molecule-plugins[docker] docker 67 | 68 | - name: Run Molecule tests. 69 | run: molecule test 70 | env: 71 | PY_COLORS: '1' 72 | ANSIBLE_FORCE_COLOR: '1' 73 | MOLECULE_DISTRO: ${{ matrix.distro }} 74 | MOLECULE_PLAYBOOK: ${{ matrix.playbook }} 75 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This workflow requires a GALAXY_API_KEY secret present in the GitHub 3 | # repository or organization. 4 | # 5 | # See: https://github.com/marketplace/actions/publish-ansible-role-to-galaxy 6 | # See: https://github.com/ansible/galaxy/issues/46 7 | 8 | name: Release 9 | 'on': 10 | push: 11 | tags: 12 | - '*' 13 | 14 | defaults: 15 | run: 16 | working-directory: 'geerlingguy.drush' 17 | 18 | jobs: 19 | 20 | release: 21 | name: Release 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Check out the codebase. 25 | uses: actions/checkout@v4 26 | with: 27 | path: 'geerlingguy.drush' 28 | 29 | - name: Set up Python 3. 30 | uses: actions/setup-python@v5 31 | with: 32 | python-version: '3.x' 33 | 34 | - name: Install Ansible. 35 | run: pip3 install ansible-core 36 | 37 | - name: Trigger a new import on Galaxy. 38 | run: >- 39 | ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} 40 | $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) 41 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Close inactive issues 3 | 'on': 4 | schedule: 5 | - cron: "55 2 * * 1" # semi-random time 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - uses: actions/stale@v8 15 | with: 16 | days-before-stale: 120 17 | days-before-close: 60 18 | exempt-issue-labels: bug,pinned,security,planned 19 | exempt-pr-labels: bug,pinned,security,planned 20 | stale-issue-label: "stale" 21 | stale-pr-label: "stale" 22 | stale-issue-message: | 23 | This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 24 | 25 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 26 | close-issue-message: | 27 | This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 28 | stale-pr-message: | 29 | This pr has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 30 | 31 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 32 | close-pr-message: | 33 | This pr has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 34 | repo-token: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | */__pycache__ 3 | *.pyc 4 | .cache 5 | 6 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | line-length: 6 | max: 120 7 | level: warning 8 | 9 | ignore: | 10 | .github/workflows/stale.yml 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jeff Geerling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Role: Drush 2 | 3 | [![CI](https://github.com/geerlingguy/ansible-role-drush/actions/workflows/ci.yml/badge.svg)](https://github.com/geerlingguy/ansible-role-drush/actions/workflows/ci.yml) 4 | 5 | Installs [Drush](http://www.drush.org), a command line shell and scripting interface for Drupal, on any Linux or UNIX system. 6 | 7 | ## Requirements 8 | 9 | PHP must be installed on the system prior to running this role (suggested role: `geerlingguy.php`). 10 | 11 | Global composer installation requires Composer to also be installed on the system (suggested role: `geerlingguy.composer`). 12 | 13 | Source installation additionally requires Git and Composer to also be installed on the system (suggested roles: `geerlingguy.git` and `geerlingguy.composer`). 14 | 15 | ## Role Variables 16 | 17 | Available variables are listed below, along with default values (see `defaults/main.yml`): 18 | 19 | ### Drush Launcher 20 | 21 | [Drush Launcher](https://github.com/drush-ops/drush-launcher) is a small wrapper around Drush for your global `$PATH`. 22 | 23 | It is the recommended way to use `drush`, but there are some situations where you might wish to install and run Drush globally without using Drush Launcher. The following variables control Drush Launcher's installation: 24 | 25 | drush_launcher_install: true 26 | 27 | Set to `no` if you don't want the launcher installed. 28 | 29 | drush_launcher_version: "0.10.1" 30 | 31 | The version of the Drush Launcher to install. This should exactly match an available [Drush Launcher release](https://github.com/drush-ops/drush-launcher/releases). 32 | 33 | drush_launcher_phar_url: https://github.com/drush-ops/drush-launcher/releases/download/{{ drush_launcher_version }}/drush.phar 34 | 35 | The URL from which the Drush Launcher phar file will be downloaded. 36 | 37 | drush_launcher_path: /usr/local/bin/drush 38 | 39 | The path where drush will be installed and available to your system. Should be in your user's `$PATH` so you can run commands simply with `drush` instead of the full path. 40 | 41 | ### Drush global install via Composer 42 | 43 | Some people need to have the full power of `drush` available globally, and this role allows the global install of Drush via Composer. If using this option, make sure you have Composer installed! 44 | 45 | drush_composer_global_install: false 46 | 47 | Set to `yes` (and set `drush_launcher_install` to `false`) if you want to install `drush` globally using Composer. 48 | 49 | drush_composer_version: "~11.0" 50 | 51 | The version constraint for the global Drush installation. 52 | 53 | drush_composer_update: false 54 | 55 | Whether to run `composer update drush/drush` to ensure the version of Drush installed globally is the latest version. 56 | 57 | drush_composer_global_bin_path: ~/.config/composer/vendor/bin 58 | drush_composer_path: /usr/local/bin/drush 59 | 60 | The global path where Composer installs global binaries, and the path in which you'd like the `drush` binary to be placed. 61 | 62 | > NOTE: Composer 'global' installation is global _to the user under which Drush is installed_—e.g. if you install globally using the root user, `drush` will only work properly as `root` or when using `sudo`. 63 | 64 | ### Variables used for source install (Git). 65 | 66 | You can also install Drush from source if you need a bleeding-edge release, or if you need a specific version which can't be installed via Composer. 67 | 68 | drush_install_from_source: false 69 | 70 | Set to `yes` (and set `drush_launcher_install` to `false`) if you want to install `drush` globally using the Drush source code. 71 | 72 | drush_source_install_bin_path: /usr/local/bin/drush 73 | drush_source_install_path: /usr/local/share/drush 74 | 75 | The location of the entire drush installation (includes all the supporting files, as well as the `drush` executable file. 76 | 77 | drush_source_install_version: "11.x" 78 | 79 | The version of Drush to install (examples: `"master"` for the bleeding edge, `"11.x"`, `"10.x"`, `"6.2.0"`). This should be a string as it refers to a git branch, tag, or commit hash. 80 | 81 | drush_keep_updated: false 82 | drush_force_update: false 83 | 84 | Whether to keep Drush up-to-date with the latest revision of the branch specified by `drush_version`, and whether to force the update (e.g. overwrite local modifications to the drush repository). 85 | 86 | drush_force_composer_install: false 87 | 88 | Use this if you get an error message when provisioning like `Unable to load autoload.php. Run composer install to fetch dependencies and write this file`. It will force a `composer install` inside the Drush directory. 89 | 90 | drush_composer_cli_options: "--prefer-source --no-interaction" 91 | 92 | These options are the safest for avoiding GitHub API rate limits when installing Drush, and can be very helpful when working on dependencies/installation, but builds can be sped up substantially by changing the first option to --prefer-dist. 93 | 94 | drush_clone_depth: 1 95 | 96 | Whether to clone the entire repo (by default), or specify the number of previous commits for a smaller and faster clone. 97 | 98 | ## Dependencies 99 | 100 | None. 101 | 102 | ## Example Playbook 103 | 104 | - hosts: servers 105 | roles: 106 | - geerlingguy.drush 107 | 108 | After the playbook runs, the `drush` command will be accessible from normal system accounts. 109 | 110 | ## License 111 | 112 | MIT / BSD 113 | 114 | ## Author Information 115 | 116 | This role was created in 2014 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). 117 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Install Drush Launcher. 3 | drush_launcher_install: true 4 | drush_launcher_version: "0.10.1" 5 | drush_launcher_phar_url: >- 6 | https://github.com/drush-ops/drush-launcher/releases/download/{{ drush_launcher_version }}/drush.phar 7 | drush_launcher_path: /usr/local/bin/drush 8 | 9 | # Install Drush via Composer globally. 10 | drush_composer_global_install: false 11 | drush_composer_version: "~11.0" 12 | drush_composer_update: false 13 | drush_composer_global_bin_path: ~/.config/composer/vendor/bin 14 | drush_composer_path: /usr/local/bin/drush 15 | 16 | # Install from source (git clone + composer-based install). 17 | drush_install_from_source: false 18 | drush_source_install_bin_path: /usr/local/bin/drush 19 | drush_source_install_path: /usr/local/share/drush 20 | drush_source_install_version: "11.x" 21 | drush_keep_updated: false 22 | drush_force_update: false 23 | drush_force_composer_install: false 24 | drush_composer_cli_options: "--prefer-dist --no-interaction" 25 | drush_clone_depth: 1 26 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: [] 3 | 4 | galaxy_info: 5 | role_name: drush 6 | author: geerlingguy 7 | description: Drush - command line shell for Drupal 8 | company: "Midwestern Mac, LLC" 9 | license: "license (BSD, MIT)" 10 | min_ansible_version: 2.10 11 | platforms: 12 | - name: GenericUNIX 13 | versions: 14 | - all 15 | - name: Fedora 16 | versions: 17 | - all 18 | - name: opensuse 19 | versions: 20 | - all 21 | - name: GenericBSD 22 | versions: 23 | - all 24 | - name: FreeBSD 25 | versions: 26 | - all 27 | - name: Ubuntu 28 | versions: 29 | - all 30 | - name: SLES 31 | versions: 32 | - all 33 | - name: GenericLinux 34 | versions: 35 | - all 36 | - name: Debian 37 | versions: 38 | - all 39 | galaxy_tags: 40 | - development 41 | - web 42 | - drush 43 | - drupal 44 | - command 45 | - cli 46 | -------------------------------------------------------------------------------- /molecule/default/composer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | #become: true 5 | 6 | vars: 7 | php_enable_webserver: false 8 | php_opcache_enable: "0" 9 | 10 | # Use Composer global install. 11 | drush_launcher_install: false 12 | drush_composer_global_install: true 13 | drush_composer_update: true 14 | 15 | pre_tasks: 16 | 17 | - name: Update apt cache. 18 | apt: update_cache=true cache_valid_time=600 19 | when: ansible_os_family == 'Debian' 20 | 21 | - name: Ensure unzip is installed. 22 | package: name=unzip state=present 23 | 24 | roles: 25 | - role: geerlingguy.repo-remi 26 | when: ansible_os_family == 'RedHat' 27 | - role: geerlingguy.php-versions 28 | - role: geerlingguy.php 29 | - role: geerlingguy.composer 30 | - role: geerlingguy.drush 31 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | #become: true 5 | 6 | vars: 7 | php_enable_webserver: false 8 | php_opcache_enable: "0" 9 | 10 | pre_tasks: 11 | - name: Update apt cache. 12 | apt: update_cache=true cache_valid_time=600 13 | when: ansible_os_family == 'Debian' 14 | 15 | - name: Ensure unzip is installed. 16 | package: name=unzip state=present 17 | 18 | roles: 19 | - role: geerlingguy.repo-remi 20 | when: ansible_os_family == 'RedHat' 21 | - role: geerlingguy.php-versions 22 | - role: geerlingguy.php 23 | - role: geerlingguy.composer 24 | - role: geerlingguy.drush 25 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | role_name_check: 1 3 | dependency: 4 | name: galaxy 5 | options: 6 | ignore-errors: true 7 | driver: 8 | name: docker 9 | platforms: 10 | - name: instance 11 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible:latest" 12 | command: ${MOLECULE_DOCKER_COMMAND:-""} 13 | volumes: 14 | - /sys/fs/cgroup:/sys/fs/cgroup:rw 15 | cgroupns_mode: host 16 | privileged: true 17 | pre_build_image: true 18 | provisioner: 19 | name: ansible 20 | playbooks: 21 | converge: ${MOLECULE_PLAYBOOK:-converge.yml} 22 | -------------------------------------------------------------------------------- /molecule/default/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | roles: 3 | - name: geerlingguy.repo-remi 4 | - name: geerlingguy.php-versions 5 | - name: geerlingguy.php 6 | - name: geerlingguy.composer 7 | - name: geerlingguy.git 8 | -------------------------------------------------------------------------------- /molecule/default/source.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | #become: true 5 | 6 | vars: 7 | php_enable_webserver: false 8 | php_opcache_enable: "0" 9 | drush_launcher_install: false 10 | drush_composer_global_install: false 11 | drush_install_from_source: true 12 | 13 | pre_tasks: 14 | - name: Update apt cache. 15 | apt: update_cache=true cache_valid_time=600 16 | when: ansible_os_family == 'Debian' 17 | 18 | roles: 19 | - role: geerlingguy.repo-remi 20 | when: ansible_os_family == 'RedHat' 21 | - role: geerlingguy.php-versions 22 | - role: geerlingguy.php 23 | - role: geerlingguy.composer 24 | - role: geerlingguy.git 25 | - role: geerlingguy.drush 26 | -------------------------------------------------------------------------------- /tasks/install-drush-composer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Use manual composer tasks until Ansible 2.10.4 is released. 3 | - name: Ensure Drush is installed globally via Composer. 4 | command: "{{ composer_path }} global require drush/drush:{{ drush_composer_version }}" 5 | register: drush_composer_require 6 | changed_when: "'Nothing to install' not in drush_composer_require.stderr" 7 | 8 | - name: Update global Drush install if configured. 9 | command: "{{ composer_path }} global update drush/drush --with-dependencies" 10 | changed_when: "'Nothing to install' not in drush_composer_require.stderr" 11 | register: tasky 12 | when: 13 | - drush_composer_update 14 | - not drush_composer_require.changed 15 | tags: ['skip_ansible_lint'] 16 | 17 | # Switch back to these tasks after Ansible 2.10.4 is released. 18 | # - name: Ensure Drush is installed globally via Composer. 19 | # composer: 20 | # command: require 21 | # global_command: true 22 | # arguments: "drush/drush:{{ drush_composer_version }}" 23 | # register: drush_composer_require 24 | # 25 | # - name: Update global Drush install if configured. 26 | # composer: 27 | # command: update 28 | # global_command: true 29 | # arguments: "drush/drush --with-dependencies" 30 | # when: 31 | # - drush_composer_update 32 | # - not drush_composer_require.changed 33 | # tags: ['skip_ansible_lint'] 34 | 35 | - name: Ensure globally-installed Drush is symlinked into bin dir. 36 | file: # noqa 208 37 | src: "{{ drush_composer_global_bin_path }}/drush" 38 | dest: "{{ drush_composer_path }}" 39 | state: link 40 | -------------------------------------------------------------------------------- /tasks/install-drush-launcher.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check current state. 3 | stat: 4 | path: "{{ drush_launcher_path }}" 5 | register: drush_path_state 6 | 7 | - name: Perform cleanup of old symlink. 8 | file: 9 | path: "{{ drush_launcher_path }}" 10 | state: absent 11 | when: drush_path_state.stat.islnk is defined and drush_path_state.stat.islnk 12 | 13 | - name: Ensure Drush path directory exists. 14 | file: 15 | path: "{{ drush_launcher_path | dirname }}" 16 | state: directory 17 | mode: 0755 18 | 19 | - name: Install Drush. 20 | get_url: 21 | url: "{{ drush_launcher_phar_url }}" 22 | dest: "{{ drush_launcher_path }}" 23 | 24 | - name: Ensure Drush is executable. 25 | file: 26 | path: "{{ drush_launcher_path }}" 27 | mode: 0755 28 | -------------------------------------------------------------------------------- /tasks/install-source.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Clone Drush from GitHub. 3 | git: 4 | repo: https://github.com/drush-ops/drush.git 5 | dest: "{{ drush_source_install_path }}" 6 | version: "{{ drush_source_install_version }}" 7 | update: "{{ drush_keep_updated }}" 8 | force: "{{ drush_force_update }}" 9 | depth: "{{ drush_clone_depth }}" 10 | register: drush_clone 11 | 12 | - name: Check for composer.json 13 | stat: path={{ drush_source_install_path }}/composer.json 14 | register: drush_composer 15 | 16 | # See: https://github.com/geerlingguy/ansible-role-drush/issues/6 17 | - name: Ensure Drush can be installed on Debian Wheezy. 18 | command: > 19 | {{ composer_path }} update {{ drush_composer_cli_options }} 20 | chdir={{ drush_source_install_path }} 21 | when: 22 | - drush_clone.changed and ansible_distribution == "Debian" 23 | - ansible_distribution_release == "wheezy" 24 | - drush_composer.stat.exists 25 | tags: ['skip_ansible_lint'] 26 | 27 | - name: Install Drush dependencies with Composer. 28 | command: > 29 | {{ composer_path }} install {{ drush_composer_cli_options }} 30 | chdir={{ drush_source_install_path }} 31 | when: (drush_clone.changed and drush_composer.stat.exists) or drush_force_composer_install 32 | tags: ['skip_ansible_lint'] 33 | 34 | - name: Create drush symlink. 35 | file: # noqa 208 36 | src: "{{ drush_source_install_path }}/drush" 37 | dest: "{{ drush_source_install_bin_path }}" 38 | state: link 39 | force: true 40 | 41 | - name: Run drush to finish setting it up. 42 | command: "{{ drush_source_install_bin_path }}" 43 | register: drush_result 44 | changed_when: "'Available commands' not in drush_result.stdout" 45 | become: false 46 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: install-drush-launcher.yml 3 | when: drush_launcher_install 4 | 5 | - include_tasks: install-drush-composer.yml 6 | when: drush_composer_global_install 7 | 8 | - include_tasks: install-source.yml 9 | when: drush_install_from_source 10 | --------------------------------------------------------------------------------