├── .circleci └── config.yml ├── LICENSE ├── README.md ├── defaults └── main.yml ├── meta └── main.yml ├── tasks └── main.yml └── tests └── test.yml /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | test-ansible-galaxy-role: 5 | executors: 6 | default: 7 | docker: 8 | - image: 'circleci/python:3-stretch' 9 | 10 | jobs: 11 | syntax-check: 12 | parameters: 13 | ansible-version: 14 | type: string 15 | executor: default 16 | steps: 17 | - run: python --version 18 | - checkout 19 | # TODO: Cache pip OR install via apt-get. 20 | - run: sudo pip install ansible<< parameters.ansible-version >> 21 | - run: ansible --version 22 | - run: ansible-playbook -i 'localhost,' --syntax-check tests/test.yml 23 | 24 | lint: 25 | executor: default 26 | steps: 27 | - run: python --version 28 | - checkout 29 | # TODO: Cache pip OR install via apt-get. 30 | - run: sudo pip install ansible-lint 31 | - run: ansible-lint --version 32 | - run: ansible-lint tests/test.yml 33 | 34 | workflows: 35 | syntax-check-and-lint: 36 | jobs: 37 | - test-ansible-galaxy-role/lint 38 | - test-ansible-galaxy-role/syntax-check: 39 | name: syntax-check-ansible-latest 40 | ansible-version: '' 41 | - test-ansible-galaxy-role/syntax-check: 42 | name: syntax-check-ansible-2.9 43 | ansible-version: ~=2.9.0 44 | - test-ansible-galaxy-role/syntax-check: 45 | name: syntax-check-ansible-2.8 46 | ansible-version: ~=2.8.0 47 | - test-ansible-galaxy-role/syntax-check: 48 | name: syntax-check-ansible-2.7 49 | ansible-version: ~=2.7.0 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Itineris Limited 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # trellis_install_wp_cli_via_composer 2 | 3 | [![Ansible Role](https://img.shields.io/ansible/role/45815?style=flat-square)](https://galaxy.ansible.com/ItinerisLtd/trellis_install_wp_cli_via_composer) 4 | [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/itinerisltd/trellis_install_wp_cli_via_composer?style=flat-square)](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer/releases) 5 | [![Ansible Role](https://img.shields.io/ansible/role/d/45815?style=flat-square)](https://galaxy.ansible.com/ItinerisLtd/trellis_install_wp_cli_via_composer) 6 | [![CircleCI](https://circleci.com/gh/ItinerisLtd/trellis_install_wp_cli_via_composer.svg?style=svg)](https://circleci.com/gh/ItinerisLtd/trellis_install_wp_cli_via_composer) 7 | [![Ansible Quality Score](https://img.shields.io/ansible/quality/45815?style=flat-square)](https://galaxy.ansible.com/ItinerisLtd/trellis_install_wp_cli_via_composer) 8 | [![GitHub License](https://img.shields.io/github/license/itinerisltd/trellis_install_wp_cli_via_composer.svg?style=flat-square)](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer/blob/master/LICENSE) 9 | [![Hire Itineris](https://img.shields.io/badge/hire-Itineris-ff69b4.svg?style=flat-square)](https://www.itineris.co.uk/contact/) 10 | [![Twitter Follow @itineris_ltd](https://img.shields.io/twitter/follow/itineris_ltd?style=flat-square&color=1da1f2)](https://twitter.com/itineris_ltd) 11 | [![Twitter Follow @TangRufus](https://img.shields.io/twitter/follow/TangRufus?style=flat-square&color=1da1f2)](https://twitter.com/tangrufus) 12 | 13 | Install WP-CLI via composer on Trellis servers. 14 | 15 | 16 | 17 | 18 | 19 | - [Goal](#goal) 20 | - [The Problem](#the-problem) 21 | - [The Solution](#the-solution) 22 | - [Role Variables](#role-variables) 23 | - [Requirements](#requirements) 24 | - [Installation](#installation) 25 | - [FAQ](#faq) 26 | - [How to install certain commands only instead of the whole WP-CLI bundle?](#how-to-install-certain-commands-only-instead-of-the-whole-wp-cli-bundle) 27 | - [What to do when composer couldn't install packages because of conflicting version constraints?](#what-to-do-when-composer-couldnt-install-packages-because-of--conflicting-version-constraints) 28 | - [How to verify WP-CLI is installed via composer?](#how-to-verify-wp-cli-is-installed-via-composer) 29 | - [Is it idempotent or deterministic?](#is-it-idempotent-or-deterministic) 30 | - [It looks awesome. Where can I find more goodies like this?](#it-looks-awesome-where-can-i-find-more-goodies-like-this) 31 | - [Where can I give :star::star::star::star::star: reviews?](#where-can-i-give-starstarstarstarstar-reviews) 32 | - [Testing](#testing) 33 | - [Feedback](#feedback) 34 | - [Security](#security) 35 | - [Credits](#credits) 36 | - [License](#license) 37 | 38 | 39 | 40 | ## Goal 41 | 42 | ### The Problem 43 | 44 | > [Since WP-CLI v2.0.0,] the most problematic set of the dependencies, the hard requirement on an old version of Symfony, is gone. The only Symfony component we still have (yet) is `symfony/finder`, as there’s no upper version limit for that one. 45 | > 46 | > -- https://make.wordpress.org/cli/2018/08/08/wp-cli-v2-0-0-release-notes/ 47 | 48 | However, the phar bundles with [WP-CLI's dependencies](https://github.com/wp-cli/wp-cli/blob/bc37f66e25b9992813b0c50b933aefbf88718e6a/composer.lock). Those dependencies' always being loaded from the phar. As a result, their versions are _locked_. 49 | 50 | For example: WP-CLI v2.4.0 phar bundles with [`symfony/process` v2.8.5](https://github.com/wp-cli/wp-cli-bundle/blob/v2.4.0/composer.lock#L1205-L1206) (as a dependency of `symfony/finder`). Assume we have `my-awesome-command` which requires `symfony/process:5.0.0`. `$ wp package install my-awesome-command` installs `symfony/process` v5.0.0 as expected. However, `symfony/process` v2.8.5 (from the WP-CLI phar) is always used; the newer version of `symfony/process` (which required by `my-awesome-command`) is being ignored. Thus, `my-awesome-command` fails when trying to use `symfony/process`. 51 | 52 | ```sh-session 53 | $ wp shell 54 | 55 | wp> $reflector = new \ReflectionClass('Symfony\Component\Process\Process'); 56 | => object(ReflectionClass)#2801 (1) { 57 | ["name"]=> 58 | string(33) "Symfony\Component\Process\Process" 59 | } 60 | wp> echo $reflector->getFileName(); // Note that it is loaded form the WP-CLI phar. 61 | phar:///usr/bin/wp/vendor/symfony/process/Process.php 62 | ``` 63 | 64 | This problem affects `symfony/finder` and its dependencies. 65 | 66 | ### The Solution 67 | 68 | [Installing WP-CLI via composer](https://make.wordpress.org/cli/handbook/installing/#installing-via-composer) resolves the problem. 69 | 70 | ```sh-session 71 | $ wp shell 72 | 73 | wp> $reflector = new \ReflectionClass('Symfony\Component\Process\Process'); 74 | => object(ReflectionClass)#2801 (1) { 75 | ["name"]=> 76 | string(33) "Symfony\Component\Process\Process" 77 | } 78 | wp> echo $reflector->getFileName(); // Note that it is loaded form composer's vendor folder. 79 | /home/web/.composer/vendor/symfony/process/Process.php 80 | ``` 81 | 82 | ## Role Variables 83 | 84 | ```yaml 85 | # Composer packages to be removed before installing WP-CLI 86 | # Default: [] 87 | wp_cli_composer_global_remove_packages: 88 | - wp-cli/wp-cli-bundle 89 | - psy/psysh 90 | 91 | # Composer packages to be installed 92 | # Default: "wp-cli/wp-cli-bundle:{{ wp_cli_version }}" 93 | wp_cli_composer_global_require_packages: 94 | - "wp-cli/wp-cli:2.4.0" 95 | - "wp-cli/package-command:^2" 96 | - "psy/psysh:^0.9.12" 97 | - "xxx/yyy:'^1.2.3 || ^2.2.3'" 98 | 99 | # WP-CLI package to be installed 100 | # Default: [] 101 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L10 102 | wp_cli_packages: 103 | - "typisttech/image-optimize-command:@stable" 104 | - "git@github.com:Yoast/wp-cli-faker.git" 105 | 106 | # WP-CLI path 107 | # Default: /usr/bin/wp 108 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L3 109 | wp_cli_bin_path: /usr/bin/wp 110 | 111 | # WP-CLI bash completion path 112 | # Default: /etc/bash_completion.d/wp-completion.bash 113 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L9 114 | wp_cli_completion_path: /etc/bash_completion.d/wp-completion.bash 115 | ``` 116 | 117 | ## Requirements 118 | 119 | - [Trellis](https://github.com/roots/trellis) v1.3.0 or later 120 | - Ansible v2.7.0 or later 121 | - Python v3.7.6 or later 122 | 123 | ## Installation 124 | 125 | 1. Add `itinerisltd.trellis_install_wp_cli_via_composer` to `galaxy.yml` 126 | ```diff 127 | # galaxy.yml 128 | 129 | + - src: itinerisltd.trellis_install_wp_cli_via_composer 130 | + version: XXX.YYY.ZZZ # Check for latest version! 131 | ``` 132 | 133 | 2. Replace `wp-cli` role with `itinerisltd.trellis_install_wp_cli_via_composer` 134 | ```diff 135 | # server.yml 136 | 137 | - - { role: wp-cli, tags: [wp-cli] } 138 | + - { role: itinerisltd.trellis_install_wp_cli_via_composer, tags: [wp-cli] } 139 | ``` 140 | 141 | 3. Install galaxy roles 142 | ```bash 143 | trellis galaxy install 144 | # Alternatively 145 | ansible-galaxy install -r galaxy.yml --force 146 | ``` 147 | 148 | 4. Re-provision 149 | ```bash 150 | trellis provision production 151 | # Alternatively 152 | ansible-playbook server.yml -e env=production 153 | ``` 154 | 155 | ## FAQ 156 | 157 | ### How to install certain commands only instead of the whole WP-CLI bundle? 158 | 159 | By default, the whole WP-CLI bundle ([`wp-cli/wp-cli-bundle`](https://packagist.org/packages/wp-cli/wp-cli-bundle)) installed. If you want to keep your servers _lean_, install command packages selectively: 160 | 161 | ```yaml 162 | wp_cli_composer_global_remove_packages: 163 | - wp-cli/wp-cli-bundle 164 | 165 | wp_cli_composer_global_require_packages: 166 | # Required: WP-CLI framework 167 | - "wp-cli/wp-cli:^2.4" 168 | # Only install commands you need: 169 | - "wp-cli/core-command:^2" 170 | - "wp-cli/cron-command:^2" 171 | - "wp-cli/db-command:^2" 172 | - "wp-cli/package-command:^2" 173 | ``` 174 | 175 | ### What to do when composer couldn't install packages because of conflicting version constraints? 176 | 177 | Double check existing composer packages. Then, change [version constraints](https://getcomposer.org/doc/articles/versions.md) via [role variables](#role-variables). You might need to uninstall some packages. 178 | 179 | These commands are your friends: 180 | 181 | ```bash 182 | composer global show 183 | cat $(composer config --global --absolute home)/composer.json 184 | 185 | wp package list 186 | cat $(wp package path)/composer.json 187 | ``` 188 | 189 | ### How to verify WP-CLI is installed via composer? 190 | 191 | ```sh-session 192 | # Bad: Installed via Trellis, i.e: the phar 193 | $ wp cli info 194 | WP-CLI root dir: phar://wp-cli.phar/vendor/wp-cli/wp-cli 195 | ``` 196 | 197 | ```sh-session 198 | # Good: Installed via this role, i.e: composer 199 | $ wp cli info 200 | WP-CLI root dir: /home/web/.composer/vendor/wp-cli/wp-cli 201 | ``` 202 | 203 | ### Is it idempotent or deterministic? 204 | 205 | No. 206 | 207 | Specific exact package versions might help but you will need to manage them manually. 208 | 209 | ### It looks awesome. Where can I find more goodies like this? 210 | 211 | - Articles on [Itineris' blog](https://www.itineris.co.uk/blog/) 212 | - More projects on [Itineris' GitHub profile](https://github.com/itinerisltd) 213 | - More plugins on [Itineris](https://profiles.wordpress.org/itinerisltd/#content-plugins) and [TangRufus](https://profiles.wordpress.org/tangrufus/#content-plugins) wp.org profiles 214 | - Follow [@itineris_ltd](https://twitter.com/itineris_ltd) and [@TangRufus](https://twitter.com/tangrufus) on Twitter 215 | - Hire [Itineris](https://www.itineris.co.uk/services/) to build your next awesome site 216 | 217 | ### Where can I give :star::star::star::star::star: reviews? 218 | 219 | Thanks! Glad you like it. It's important to let my boss knows somebody is using this project. Since this is not hosted on wordpress.org, please consider: 220 | 221 | - tweet something good with mentioning [@itineris_ltd](https://twitter.com/itineris_ltd) and [@TangRufus](https://twitter.com/tangrufus) 222 | - :star: star this [Github repo](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer) 223 | - :eyes: [watch](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer/subscription) this Github repo 224 | - write blog posts 225 | - submit [pull requests](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer) 226 | - [hire Itineris](https://www.itineris.co.uk/services/) 227 | 228 | ## Testing 229 | 230 | ```bash 231 | ansible-playbook -i 'localhost,' --syntax-check tests/test.yml 232 | ``` 233 | 234 | ## Feedback 235 | 236 | **Please provide feedback!** We want to make this library useful in as many projects as possible. 237 | Please submit an [issue](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer/issues/new) and point out what you do and don't like, or fork the project and make suggestions. 238 | **No issue is too small.** 239 | 240 | ## Security 241 | 242 | If you discover any security related issues, please email [dev@itineris.co.uk](mailto:dev@itineris.co.uk) instead of using the issue tracker. 243 | 244 | ## Credits 245 | 246 | [trellis_install_wp_cli_via_composer](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer) is a [Itineris Limited](https://www.itineris.co.uk/) project created by [Tang Rufus](https://typist.tech). 247 | 248 | Full list of contributors can be found [here](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer/graphs/contributors). 249 | 250 | ## License 251 | 252 | [trellis_install_wp_cli_via_composer](https://github.com/ItinerisLtd/trellis_install_wp_cli_via_composer) is released under the [MIT License](https://opensource.org/licenses/MIT). 253 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | wp_cli_composer_global_remove_packages: [] 3 | 4 | wp_cli_composer_global_require_packages: 5 | - "wp-cli/wp-cli-bundle:^2.4.0" 6 | 7 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L10 8 | wp_cli_packages: [] 9 | 10 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L3 11 | wp_cli_bin_path: /usr/bin/wp 12 | 13 | # Taken form https://github.com/roots/trellis/blob/4425669bab0665f0c9aed92c80eb9b8c54f63e85/roles/wp-cli/defaults/main.yml#L9 14 | wp_cli_completion_path: /etc/bash_completion.d/wp-completion.bash 15 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Tang Rufus 3 | description: Install WP-CLI via composer on Trellis servers 4 | company: Itineris Limited 5 | 6 | license: MIT 7 | 8 | min_ansible_version: 2.7 9 | 10 | platforms: 11 | - name: Ubuntu 12 | versions: 13 | - xenial 14 | - bionic 15 | 16 | galaxy_tags: 17 | - trellis 18 | - wordpress 19 | - wpcli 20 | 21 | dependencies: [] 22 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Remove WP-CLI bash completion file installed by Trellis 3 | file: 4 | path: "{{ wp_cli_completion_path }}" 5 | state: absent 6 | 7 | - name: Remove WP-CLI bundle components via composer 8 | composer: 9 | command: remove 10 | global_command: yes 11 | arguments: "{{ wp_cli_composer_global_remove_packages | join(' ') }}" 12 | when: wp_cli_composer_global_remove_packages | length 13 | become: true 14 | become_user: "{{ web_user }}" 15 | 16 | - name: Install WP-CLI via composer 17 | composer: 18 | command: require 19 | global_command: yes 20 | arguments: "{{ wp_cli_composer_global_require_packages | join(' ') }}" 21 | become: true 22 | become_user: "{{ web_user }}" 23 | 24 | - name: Symlink WP-CLI 25 | file: 26 | src: "/home/{{ web_user }}/.composer/vendor/bin/wp" # TODO: Find the path dynamically. 27 | dest: "{{ wp_cli_bin_path }}" 28 | mode: "0755" 29 | state: link 30 | 31 | - name: Install WP-CLI packages 32 | command: "wp package install {{ item }}" 33 | become: true 34 | become_user: "{{ web_user }}" 35 | register: wp_cli_packages_installed 36 | changed_when: 37 | - "'Nothing to install or update' not in wp_cli_packages_installed.stdout" 38 | - "'Package operations: 0 installs, 0 updates, 0 removals' not in wp_cli_packages_installed.stdout" 39 | loop: "{{ wp_cli_packages }}" 40 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - ../.. 6 | --------------------------------------------------------------------------------