Since Drupal 8 uses configuration management, we were wondering how we can make sure that any commit does not break the site installation or configuration synchronization.
Our usual workflow involves installation profile creation with basic configurations & import other configurations after site installation. So we needed to make sure that each commit should get tested by installing the site using specific installation profile & then import the configurations. If this does not break anything the commit should be deployed on the server. That was it at the time, no test cases or any complex executions.
While working on building such system. we came across Jenkins. While reviewing Jenkins, we came to know that it will need to be hosted separately to use it. We didn't want to host a system separately anywhere. Then we found CircleCI. It automates the process with CI hosted in the cloud or on a private server. "CI hosted in the cloud" was enough for us :)
To use it, you just need to log in using your GitHub or BitBucket account so CircleCI can access your repositories. Then you can configure your repository to allow CircleCI builds easily from there. Just go to the Add project menu & "follow" the required project. CircleCI will help you with the next steps. Here are some docs you may find useful.
After this, it comes to creating your config.yml file. Here is how we created it for Drupal 8 site:
The first job in this file is `build`. Let's see the important lines in it.
This is a reference to our docker image that will be used to build the container. It has two tags, 7.2 (for PHP 7.2) & 7.4 (for PHP 7.4). This tag can be adjusted based on what PHP version we need for the site. If you see the dockerfile, it is just an extended version of drupaldocker/php. It updates the composer version provided & install rsync (which may not be needed). Feel free to use or extend it.
MySQL image provided by CircleCI. You can see the pre-built docker images provided by CircleCI here.
MYSQL_DATABASE: drupal MYSQL_ROOT_USERNAME: root MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_HOST: "%"
These are MySQL credentials for your Drupal site. This can be anything but should match with the settings file. We will discuss this later.
For security reasons, you should add such variables under your project settings in CircleCI instead of specifying in yml file. Please read about it in detail here.
After this, you can see there are multiple steps in the file. These are basically a sequence of commands that we will run on CircleCI build environment.
This will just checkout the git repository in build container.
Terminal commands that we can use will go under this section. In our case, first was obviously `composer install` to download the dependencies for the site. You can specify the name for this to identify the process on CircleCI UI. The next section of commands is basically the steps that we usually do install Drupal 8 site along with some changes for CircleCI build.
cp .circleci/env/settings.local.php web/sites/default/
We have separate settings file with database credentials for the build. Here is how it looks:
Here please note that the database credentials must be same as per config.yml file. Or Drupal won't be able to access the database. Also, keep the host as `127.0.0.1` & not `localhost`.
cp web/sites/default/settings.dev web/sites/default/settings.php
We keep `settings.dev` example file in code. We copy & paste it as `settings.php` while setting up a site on the local environment. This file adds `settings.local.php` file so all local instance configurations can be added in it. It is basically `default.settings.php` file that comes with Drupal but with lines as below:
./vendor/bin/drush si standard -y --verbose
Install the site using drush si command. We usually install drush via site's composer file using `composer require drush/drush`. Replace your installation profile name as needed.
./vendor/bin/drush cim -y --verbose
Import the configurations using drush. The output of all these commands can be seen at CircleCI build.
We have kept the commands limited to this only. If you want, you can add more commands to run test cases too along with the required setup.
The next job in `config.yml` is `deploy`. It is used to deploy the changes over the server.
If deploying to your server requires SSH access, you will need to add SSH keys. You can read about this in detail here. Basically this command adds your SSH keys to build container so we can later use it to connect to the server.
ssh USERNAME@SERVER_HOST "sh /PATH/TO/SCRIPT/deploy.sh"
We are just running script written on the server to deploy the changes. Make sure to replace username & host in above. Here is how our deploy.sh file looks:
These commands are pretty clear. Just pull the changes, run composer & import the configs. This can have one more command to update the database. But we didn't keep it as it is not something we do each & every time.
Now the next section in `config.yml` is `workflows`. These are set of instructions about how we want to perform our jobs (`build` & `deploy`). Read more about workflows here.
In this, under `jobs` section, first, we are performing our `build` job. After that, we are performing `deploy` job but with conditions.
requires: - build
This means, our `deploy` job requires `build` job to be successful.
filters: branches: only: master
Only execute `deploy` job, when a commit is done on `master` branch of the repository. So once we develop everything on another branch & merge it to master, it will build & deploy to server.
That's all we did till now. There is a lot more we can do with this. You can run unit tests & behat tests as well. But as a starting point, this should be good to go.