├── LICENSE ├── README.md ├── config.typisttech.yml └── config.yml /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Typist Tech 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 | **[Deprecated] Use [ItinerisLtd/tiller-circleci-orb](https://github.com/ItinerisLtd/tiller-circleci-orb) instead.** 2 | 3 | --- 4 | 5 | # Tiller CircleCI 6 | 7 | Deploy Trellis, Bedrock and Sage via CircleCI. 8 | 9 | 10 | 11 | 12 | 13 | - [Requirements](#requirements) 14 | - [What's in the Box?](#whats-in-the-box) 15 | - [File Structures](#file-structures) 16 | - [Official](#official) 17 | - [Typist Tech](#typist-tech) 18 | - [SSH Key](#ssh-key) 19 | - [GitHub](#github) 20 | - [CircleCI](#circleci) 21 | - [Trellis](#trellis) 22 | - [Ensure Trellis Deploys the Correct Commit](#ensure-trellis-deploys-the-correct-commit) 23 | - [Ansible Vault Password](#ansible-vault-password) 24 | - [Caching](#caching) 25 | - [Ansible Galaxy Roles](#ansible-galaxy-roles) 26 | - [Security](#security) 27 | - [SSH Keys](#ssh-keys) 28 | - [Log Level](#log-level) 29 | - [Every Software can be Hacked](#every-software-can-be-hacked) 30 | - [FAQ](#faq) 31 | - [Is it a must to merge Trellis pull request #997?](#is-it-a-must-to-merge-trellis-pull-request-997) 32 | - [What is in the `itinerisltd/tiller` docker image?](#what-is-in-the-itinerisltdtiller-docker-image) 33 | - [Is it a must to use all Trellis, Bedrock and Sage?](#is-it-a-must-to-use-all-trellis-bedrock-and-sage) 34 | - [Is it a must to use CircleCI?](#is-it-a-must-to-use-circleci) 35 | - [Is it a must to use GitHub?](#is-it-a-must-to-use-github) 36 | - [It looks awesome. Where can I find some more goodies like this?](#it-looks-awesome-where-can-i-find-some-more-goodies-like-this) 37 | - [This package isn't on wp.org. Where can I give a :star::star::star::star::star: review?](#this-package-isnt-on-wporg-where-can-i-give-a-starstarstarstarstar-review) 38 | - [Support](#support) 39 | - [Why don't you hire me?](#why-dont-you-hire-me) 40 | - [Want to help in other way? Want to be a sponsor?](#want-to-help-in-other-way-want-to-be-a-sponsor) 41 | - [Author Information](#author-information) 42 | - [Feedback](#feedback) 43 | 44 | 45 | 46 | ## Requirements 47 | 48 | - [Trellis](https://github.com/roots/trellis) with pull request [#997](https://github.com/roots/trellis/pull/997) merged 49 | - [CircleCI](https://circleci.com) 50 | - (Optional) Bedrock [31c638f](https://github.com/roots/bedrock/commit/31c638fe5a33d9e40a5c9eee07a94deb9cb76adc) or later 51 | - (Optional) Sage [9.0.1](https://github.com/roots/sage/releases/tag/9.0.1) or later 52 | 53 | ## What's in the Box? 54 | 55 | `.circleci/config.yml` examples of running [Trellis deploys](https://roots.io/trellis/docs/deploys/) to production whenever master branch is pushed. 56 | 57 | ## File Structures 58 | 59 | [Tiller CircleCI](https://github.com/TypistTech/tiller-circleci) comes with 2 different `config.yml` examples. They are expecting different Trellis and Bedrock structures. 60 | 61 | ### Official 62 | 63 | Use [`config.yml`](./config.yml) if your directory structure follow [the official documents](https://roots.io/trellis/docs/installing-trellis/#create-a-project): 64 | ``` 65 | example.com/ # → Root folder for the project 66 | ├── .git/ # → Only one git repo 67 | ├── trellis/ # → Your clone of roots/trellis, directory name must be `trellis` 68 | └── site/ # → A Bedrock-based WordPress site, directory name doesn't matter 69 | ``` 70 | 71 | To install `config.yml`: 72 | 1. Set up SSH keys, Ansible Vault password and commit Trellis changes described in the following sections 73 | 1. Copy, review, change and commit [`config.yml`](./config.yml) to `.circleci/config.yml` 74 | 75 | ### Typist Tech 76 | 77 | At [Typist Tech](https://typist.tech/), I use a opinionated project structure: 78 | - separate Trellis and Bedrock as 2 different git repo 79 | - name the Bedrock-based WordPress site directory more creatively, i.e: `bedrock` 80 | 81 | ``` 82 | example.com/ # → Root folder for the project 83 | ├── bedrock/ # → A Bedrock-based WordPress site, directory name doesn't matter 84 | │   └── .git/ # Bedrock git repo 85 | └── trellis/ # → Clone of roots/trellis, directory name must be `trellis` 86 | └── .git/ # Trellis git repo 87 | ``` 88 | 89 | See: [roots/trellis#883 (comment)](https://github.com/roots/trellis/issues/883#issuecomment-329052189) 90 | 91 | To install `config.typisttech.yml`: 92 | 1. Set up SSH keys, Ansible Vault password and commit Trellis changes described in the following sections 93 | 1. Push the Trellis repo 94 | 1. Copy, review, change and commit [`config.typisttech.yml`](./config.typisttech.yml) to `/.circleci/config.yml` 95 | 96 | --- 97 | 98 | ## SSH Key 99 | 100 | You need a robot user for deployment. In this example, we will use a GitHub machine user account as our robot. For simplicity, this robot uses the same SSH key pair to access both GitHub private repos and the web server. 101 | 102 | ### GitHub 103 | 104 | 1. Sign up a machine user(e.g: `mybot`) on GitHub 105 | 1. Grant `mybot` **read** access to all necessary private repos 106 | 107 | ### CircleCI 108 | 109 | On CircleCI's web console: 110 | 1. Link your project repo 111 | 1. Go to **Settings** » **Checkout SSH Keys** 112 | 1. Delete the deploy key 113 | 1. Create a user key (as `mybot`) 114 | 115 | Learn more about deploy keys and user keys on CircleCI **Checkout SSH Keys** settings page. 116 | 117 | ### Trellis 118 | 119 | 1. Add the SSH key to web server 120 | ```diff 121 | # group_vars//users.yml 122 | users: 123 | - name: "{{ web_user }}" 124 | groups: 125 | - "{{ web_group }}" 126 | keys: 127 | - https://github.com/human.keys 128 | + - https://github.com/mybot.keys 129 | - name: "{{ admin_user }}" 130 | groups: 131 | - sudo 132 | keys: 133 | - https://github.com/human.keys 134 | ``` 135 | 1. Re-provision 136 | `$ ansible-playbook server.yml -e env= --tags users` 137 | 138 | ## Ensure Trellis Deploys the Correct Commit 139 | 140 | Normally, Trellis always deploy the **latest** commit of the branch. We need a change in `group_vars//wordpress_sites.yml`: 141 | 142 | ```diff 143 | # group_vars//wordpress_sites.yml 144 | wordpress_sites: 145 | example.com: 146 | - branch: master 147 | + branch: "{{ site_version | default('master') }}" 148 | ``` 149 | 150 | ## Ansible Vault Password 151 | 152 | Unlike other environment variables, [Ansible Vault](https://docs.ansible.com/ansible/playbooks_vault.html) password should never be stored as plaintext. Therefore, you should add `VAULT_PASS` via [CircleCI web console](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project) instead of commit it to `.circleci/config.yml`. 153 | 154 | The examples assume you have defined `vault_password_file = .vault_pass` in `ansible.cfg` as [the official document](https://roots.io/trellis/docs/vault/#2-inform-ansible-of-vault-password) suggested. 155 | 156 | ```diff 157 | # ansible.cfg 158 | [defaults] 159 | +vault_password_file = .vault_pass 160 | ``` 161 | 162 | To use another vault password filename: 163 | ```diff 164 | - run: 165 | name: Set Ansible Vault Pass 166 | - command: echo $VAULT_PASS > .vault_pass 167 | + command: echo $VAULT_PASS > .my_vault_password_file 168 | working_directory: trellis 169 | ``` 170 | 171 | Using [Ansible Vault](https://docs.ansible.com/ansible/playbooks_vault.html) to encrypt sensitive data is strongly recommended. In case you have a very strong reason not to use Ansible Vault, remove the step: 172 | 173 | ```diff 174 | -- run: 175 | - name: Set Ansible Vault Pass 176 | - command: echo $VAULT_PASS > .vault_pass 177 | - working_directory: trellis 178 | ``` 179 | 180 | ## Caching 181 | 182 | By default, yarn packages, Ansible Galaxy roles and [Trellis' temporary build directory](https://github.com/roots/trellis/pull/997) are cached. It speeds up the build significantly. 183 | This is optional and you can [customize the cache behaviour](https://circleci.com/docs/2.0/caching/). 184 | 185 | ### Ansible Galaxy Roles 186 | 187 | Due to the way `$ ansible-galaxy install` works, you can't cache `trellis/vendor` when installing a role from its git/hg repo branch: 188 | ```yaml 189 | # Good: Install from Ansible Galaxy 190 | - src: TypistTech.trellis-cloudflare-origin-ca 191 | version: 0.6.0 192 | 193 | # Good: Install from Ansible Galaxy 194 | # Defaults to latest tag when no version specified 195 | - src: TypistTech.trellis-cloudflare-origin-ca 196 | 197 | # Good: Not install from version control 198 | - src: TypistTech.trellis-cloudflare-origin-ca 199 | version: 0.6.0 200 | 201 | # Good: Tag name is *linked* to a specific commit hash 202 | - src: https://github.com/TypistTech/trellis-cloudflare-origin-ca 203 | version: 0.6.0 204 | 205 | # Good: Commit hash 206 | - src: https://github.com/TypistTech/trellis-cloudflare-origin-ca 207 | version: 58785793908f67480cae3729ec5900739e0d5c66 208 | 209 | # Bad: Branch name 210 | - src: https://github.com/TypistTech/trellis-cloudflare-origin-ca 211 | version: master 212 | 213 | # Bad: Defaults to `master` branch when no version specified 214 | - src: https://github.com/TypistTech/trellis-cloudflare-origin-ca 215 | ``` 216 | 217 | If you must install a role from its git/hg repo branch: 218 | ```diff 219 | -- restore_cache: 220 | - key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 221 | # ... 222 | -- save_cache: 223 | - key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 224 | - paths: 225 | - - trellis/vendor 226 | ``` 227 | 228 | ## Security 229 | 230 | ### SSH Keys 231 | 232 | - Grant the machine user **read** access to necessary private repo only 233 | - **Do not** grant the machine user any **write** or **admin** access to any repo 234 | - Add the machine user key to [`web_user`](https://roots.io/trellis/docs/ssh-keys/) only 235 | - **Do not** add the machine user key to [`admin_user`](https://roots.io/trellis/docs/ssh-keys/) 236 | 237 | ### Log Level 238 | 239 | > Note that the use of the no_log attribute does not prevent data from being shown when debugging Ansible itself via the ANSIBLE_DEBUG environment variable. 240 | > 241 | > --- [Ansible Docs](http://docs.ansible.com/ansible/latest/faq.html#how-do-i-keep-secret-data-in-my-playbook) 242 | 243 | By default, verbose level is set to maximum. [Sensitive data might be logged](https://github.com/TypistTech/trellis-cloudflare-origin-ca#why-cloudflare-origin-ca-key-is-logged-even-cloudflare_origin_ca_no_log-is-true). 244 | 245 | To disable verbose mode: 246 | ```diff 247 | - run: 248 | name: Install Ansible Galaxy Roles 249 | - command: ansible-galaxy install -r galaxy.yml -vvvv 250 | + command: ansible-galaxy install -r galaxy.yml 251 | working_directory: trellis 252 | - deploy: 253 | - command: ansible-playbook deploy.yml -e env=$SITE_ENV -e site=$SITE_KEY -e site_version=$CIRCLE_SHA1 -vvvv 254 | + command: ansible-playbook deploy.yml -e env=$SITE_ENV -e site=$SITE_KEY -e site_version=$CIRCLE_SHA1 255 | working_directory: trellis 256 | ``` 257 | 258 | ### Every Software can be Hacked 259 | 260 | If you discover any security related issues, please email [tiller-circleci@typist.tech](mailto:tiller-circleci@typist.tech) instead of using the issue tracker. 261 | 262 | ## FAQ 263 | 264 | ### Is it a must to merge Trellis pull request [#997](https://github.com/roots/trellis/pull/997)? 265 | 266 | Yes and no. 267 | 268 | It is required for compiling Sage assets. 269 | If you don't use Sage: 270 | - you can omit pull request [#997](https://github.com/roots/trellis/pull/997) 271 | - you **might** have to checkout bedrock source code by yourself 272 | 273 | ### What is in the `itinerisltd/tiller` docker image? 274 | 275 | It is maintained by the [Tiller](https://github.com/ItinerisLtd/tiller) project. 276 | Read its [readme](https://github.com/ItinerisLtd/tiller#docker-image-1) to learn more. 277 | 278 | ### Is it a must to use all Trellis, Bedrock and Sage? 279 | 280 | No, you don't need all of them. Only Trellis is required. 281 | 282 | ### Is it a must to use CircleCI? 283 | 284 | No. The original [Tiller](https://github.com/ItinerisLtd/tiller) project uses AWS CodeBuild. You can tweak it to run on different CI providers. 285 | 286 | ### Is it a must to use GitHub? 287 | 288 | No. GitHub is just an example. 289 | 290 | ### It looks awesome. Where can I find some more goodies like this? 291 | 292 | * Articles on Typist Tech's [blog](https://typist.tech) 293 | * [Tang Rufus' WordPress plugins](https://profiles.wordpress.org/tangrufus#content-plugins) on wp.org 294 | * More projects on [Typist Tech's GitHub profile](https://github.com/TypistTech) 295 | * Stay tuned on [Typist Tech's newsletter](https://typist.tech/go/newsletter) 296 | * Follow [Tang Rufus' Twitter account](https://twitter.com/TangRufus) 297 | * Hire [Tang Rufus](https://typist.tech/contact) to build your next awesome site 298 | 299 | ### This package isn't on wp.org. Where can I give a :star::star::star::star::star: review? 300 | 301 | Thanks! 302 | 303 | Consider writing a blog post, submitting pull requests, [donating](https://typist.tech/donation/) or [hiring me](https://typist.tech/contact/) instead. 304 | 305 | ## Support 306 | 307 | Love [Tiller CircleCI](https://github.com/TypistTech/tiller-circleci)? Help me maintain it, a [donation here](https://typist.tech/donation/) can help with it. 308 | 309 | ### Why don't you hire me? 310 | 311 | Ready to take freelance WordPress jobs. Contact me via the contact form [here](https://typist.tech/contact/) or, via email [info@typist.tech](mailto:info@typist.tech) 312 | 313 | ### Want to help in other way? Want to be a sponsor? 314 | 315 | Contact: [Tang Rufus](mailto:tangrufus@gmail.com) 316 | 317 | ## Author Information 318 | 319 | [Tiller CircleCI](https://github.com/TypistTech/tiller-circleci) is a [Typist Tech](https://typist.tech/) project created by [Tang Rufus](https://typist.tech). 320 | 321 | Special thanks to [Itineris Limited](https://www.itineris.co.uk/) who hired me to create the original [Tiller](https://github.com/ItinerisLtd/tiller) project. 322 | 323 | Special thanks to [the Roots team](https://roots.io/about/) whose [Trellis](https://github.com/roots/trellis) make this project possible. 324 | 325 | Full list of contributors can be found [here](https://github.com/ItinerisLtd/tiller/graphs/contributors). 326 | 327 | ## Feedback 328 | 329 | **Please provide feedback!** We want to make this library useful in as many projects as possible. 330 | Please submit an [issue](https://github.com/ItinerisLtd/tiller/issues/new) and point out what you do and don't like, or fork the project and make suggestions. 331 | **No issue is too small.** 332 | -------------------------------------------------------------------------------- /config.typisttech.yml: -------------------------------------------------------------------------------- 1 | # See: https://github.com/TypistTech/tiller-circleci 2 | --- 3 | version: 2 4 | jobs: 5 | deploy-production: 6 | docker: 7 | - image: itinerisltd/tiller:latest 8 | environment: 9 | ANSIBLE_HOST_KEY_CHECKING: false 10 | # TODO: Customize these environment variables 11 | SITE_ENV: production 12 | SITE_KEY: example.com 13 | TRELLIS_BRANCH: master 14 | TRELLIS_REPO: git@github.com:XXX/YYY.git 15 | steps: 16 | - run: 17 | name: Clone Trellis Repo 18 | command: git clone --verbose --branch $TRELLIS_BRANCH --depth 1 $TRELLIS_REPO . 19 | working_directory: trellis 20 | - restore_cache: 21 | key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 22 | - restore_cache: 23 | keys: 24 | - v1-production-{{ .Branch }}-{{ .Revision }}- 25 | - v1-production-{{ .Branch }}- 26 | - v1-production- 27 | - run: 28 | name: Set Ansible Vault Pass 29 | command: echo $VAULT_PASS > .vault_pass 30 | working_directory: trellis 31 | - run: 32 | name: Install Ansible Galaxy Roles 33 | command: ansible-galaxy install -r galaxy.yml -vvvv 34 | working_directory: trellis 35 | - deploy: 36 | command: ansible-playbook deploy.yml -e env=$SITE_ENV -e site=$SITE_KEY -e site_version=$CIRCLE_SHA1 -vvvv 37 | working_directory: trellis 38 | - save_cache: 39 | key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 40 | paths: 41 | - trellis/vendor 42 | - save_cache: 43 | key: v1-production-{{ .Branch }}-{{ .Revision }}-{{ epoch }} 44 | paths: 45 | - /tmp/trellis 46 | - /usr/local/share/.cache/yarn/v1 47 | 48 | # TODO: Customize the workflow 49 | workflows: 50 | version: 2 51 | tiller: 52 | jobs: 53 | - deploy-production: 54 | filters: 55 | branches: 56 | only: master 57 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | # See: https://github.com/TypistTech/tiller-circleci 2 | --- 3 | version: 2 4 | jobs: 5 | deploy-production: 6 | docker: 7 | - image: itinerisltd/tiller:latest 8 | environment: 9 | ANSIBLE_HOST_KEY_CHECKING: false 10 | # TODO: Customize these environment variables 11 | SITE_ENV: production 12 | SITE_KEY: example.com 13 | steps: 14 | - checkout 15 | - restore_cache: 16 | key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 17 | - restore_cache: 18 | keys: 19 | - v1-production-{{ .Branch }}-{{ .Revision }}- 20 | - v1-production-{{ .Branch }}- 21 | - v1-production- 22 | - run: 23 | name: Set Ansible Vault Pass 24 | command: echo $VAULT_PASS > .vault_pass 25 | working_directory: trellis 26 | - run: 27 | name: Install Ansible Galaxy Roles 28 | command: ansible-galaxy install -r galaxy.yml -vvvv 29 | working_directory: trellis 30 | - deploy: 31 | command: ansible-playbook deploy.yml -e env=$SITE_ENV -e site=$SITE_KEY -e site_version=$CIRCLE_SHA1 -vvvv 32 | working_directory: trellis 33 | - save_cache: 34 | key: v1-ansible-galaxy-{{ checksum "trellis/galaxy.yml" }} 35 | paths: 36 | - trellis/vendor 37 | - save_cache: 38 | key: v1-production-{{ .Branch }}-{{ .Revision }}-{{ epoch }} 39 | paths: 40 | - /tmp/trellis 41 | - /usr/local/share/.cache/yarn/v1 42 | 43 | # TODO: Customize the workflow 44 | workflows: 45 | version: 2 46 | tiller: 47 | jobs: 48 | - deploy-production: 49 | filters: 50 | branches: 51 | only: master 52 | --------------------------------------------------------------------------------