---
title: "A Successful One-Click Deployment in Drupal 8"
url: "/articles/a-successful-drupal-8-deployment"
type: article
date: 2017-07-19
updated: 2017-07-26
---

# A Successful One-Click Deployment in Drupal 8

#  A Successful One-Click Deployment in Drupal 8 

 One-click deployments in Drupal 8 are possible thanks to Configuration Management, Drush, Jenkins, and a development workflow.

 By

 [  Juampy NR   ](/about/juampy-nr) 

 July 19, 2017

  

When I started building the [DrupalCamp Spain 2017](https://2017.drupalcamp.es/) website I was very excited to see how far could I get with [Configuration Management](https://www.drupal.org/docs/8/configuration-management). A lot of effort went into Drupal 8 to make the management of configuration seamless without the dependency on contributed modules like [Features](https://www.drupal.org/project/features). Long story short: Configuration Management works wonderfully if you introduce it in your development workflow. In this article, we will walk through how to implement, test, and deploy a release of DrupalCamp Spainâ&#128;&#153;s website, including some issues we ran into and how we resolved them.

## The goal: just push the button

Our goal with deployments at DrupalCamp Spain was that there should be nothing left to do on the website after the Jenkins job that performs the deployment has completed. It worked in the following way:

Someone would open the Jenkins production deployment job, select a git tag, and click build:

   

   

 ![Production deployment](/sites/default/files/styles/wide_xs/public/assets/2017-07/prod-deployment-job_0.png.webp?itok=eBtGn1g7 "prod-deployment-job.png")

The above job would, via an Ansible task:

1. Deploy the source code.
2. Run [composer install in a new directory](https://github.com/AsociacionDrupalES/DrupalCampSpain/blob/master/ansible/deploy.yml#L22).
3. Run database updates: `drush update-db -y`.
4. Import configuration: `drush config-import -y`.
5. Purge Varnish caches: `varnish clean domain all`.

Here is the [log of a successful deployment](https://gist.github.com/juampynr/04c0254311c109908a994879a7d411e3). In the following sections, we will see how to setup our project to achieve one-click deployments.

## The starting point

The DrupalCamp Spain website has a [public repository](https://github.com/AsociacionDrupalES/DrupalCampSpain) that you can fork and explore. It uses:

- [drupal-project](https://github.com/drupal-composer/drupal-project) to manage dependencies via Composer.
- [Ansible](https://www.redhat.com/en/ansible-collaborative?intcmp=7015Y000003t7aWQAQ) and [Ansistrano](https://github.com/ansistrano) to describe [deployment tasks](https://github.com/AsociacionDrupalES/DrupalCampSpain/blob/master/ansible/deploy.yml).
- [Drush](https://github.com/drush-ops/drush)â&#128;&#153;s [config-export](https://drushcommands.com/drush-8x/config/config-export/) and [config-import](https://drushcommands.com/drush-8x/config/config-import/) commands to manage the `config` directory.
- [Jenkins](https://www.jenkins.io/) to deploy changes in the `master` branch to the development environment automatically, and to deploy a Git tag to the production environment manually. Here is a screenshot of our Jenkins setup:  

       

       

     ![Jenkins jobs](/sites/default/files/styles/wide_xs/public/assets/2017-07/jenkins-jobs.png.webp?itok=m3O-saPS "jenkins-jobs.png")

Now, letâ&#128;&#153;s look at one of the past deployments and then dissect it together.

## A sample deployment

Even though the DrupalCamp Spain website was a fairly small project, we did many deployments to the production environment. As an example, I have chosen the [2.2.2 release - List session proposals](https://github.com/AsociacionDrupalES/DrupalCampSpain/releases/tag/2.2.2) because:

- It includes a database update.
- It contains configuration changes.
- It involves code changes.
- It adds new dependencies.

Here is the [list of changes](https://github.com/AsociacionDrupalES/DrupalCampSpain/compare/2.2.1...2.2.2) for the release:

   

   

 ![Release changes](/sites/default/files/styles/wide_xs/public/assets/2017-07/release-diff_0.png.webp?itok=Rwn7TjOZ "release-diff.png")

If you are wondering how all of the above could be deployed successfully, the answer is twofold. First, we had a Jenkins job in charge of deploying the code. Second, we had a development process which tested deployments that we will look at in the next section.

## Working on an issue

Release [2.2.2](https://github.com/AsociacionDrupalES/DrupalCampSpain/releases/tag/2.2.2) was the result of the [Call4Papers milestone](https://github.com/AsociacionDrupalES/DrupalCampSpain/milestone/6?closed=1). This milestone consisted of four issues which were completed via pull requests. We followed this development process:

1. Install the site locally following the repositoryâ&#128;&#153;s [README](https://github.com/AsociacionDrupalES/DrupalCampSpain/blob/master/README.md).
2. Pick an open issue like [List session proposals](https://github.com/AsociacionDrupalES/DrupalCampSpain/issues/113).
3. Create a new branch from `master` with the issue number such as `113-list-proposals`.
4. Implement the requirements and [create a pull request](https://github.com/AsociacionDrupalES/DrupalCampSpain/pull/138/files) when the branch is ready for review. If there are changes in configuration, export them via `drush config-export` and include them in the pull request.
5. Once the pull request is merged, check Jenkins to verify that the automatic deployment to the development environment worked.

## Polishing the deployment

In this case, I merged the pull request, and that triggered a Jenkins job that deployed the changes in the master branch to the development environment. [It failed](https://gist.github.com/juampynr/fc3b3af93e35f0f5cec9514248d0971a#file-deployment-log-L161), as I made a change in the pull request just before it was merged that introduced a bug. Once I [fixed that](https://github.com/AsociacionDrupalES/DrupalCampSpain/commit/283f50b7358d7249b2f9bd581f5f900dc513adc2) in a second pull request, I introduced a different bug (slap me with a trout, please), which needed a [third pull request](https://github.com/AsociacionDrupalES/DrupalCampSpain/commit/b95fbd822353da8794c3a678519b238b9e6fd839). Once it was merged, Jenkins could run [the deployment task](https://github.com/AsociacionDrupalES/DrupalCampSpain/blob/master/ansible/tasks/after-symlink-tasks.yml) to the development environment [successfully](https://gist.github.com/juampynr/b25d167ba0bbec438fe59cbff9022f9a), and there was much rejoicing.

To verify the deployment, I opened the development environment in the web browser. I was puzzled when I found out that even though the [database update that installed the new module](https://github.com/AsociacionDrupalES/DrupalCampSpain/compare/2.2.1...2.2.2#diff-c1ba30618f3fea880d13dd4f9113b821R394) did complete successfully, the module was not installed. After some debugging, I discovered that I forgot to export my local environmentâ&#128;&#153;s configuration into the `config` directory, which, after doing it with `drush config-export`, contained a setting to keep the new module installed. Since Jenkins runs `drush config-import` after `drush update-db`, it uninstalled the module before the module was present in the site configuration. Therefore, I created a [fourth pull request](https://github.com/AsociacionDrupalES/DrupalCampSpain/commit/80ab4aafa5a0c10ed6b4952f98bc26d0f292971a) that included this fix. When Jenkins deployed it to the development environment, this time, the module was successfully installed. Phew!

It took us four deployments to get the release working in the development environment. For production, we want to accomplish it in a single deployment. In the next section, we will see how to test that.

*We use a tool called [Tugboat](https://www.tugboatqa.com/) in our client's projects that helps us to spot and fix implementation and deployment bugs in the early stages of development. You can find out further details at <https://www.tugboatqa.com/>.*

## Testing the deployment to production

Once we completed [all the milestoneâ&#128;&#153;s issues](https://github.com/AsociacionDrupalES/DrupalCampSpain/milestone/6?closed=1) for listing sessions, we needed to make sure they could be deployed as a whole without causing errors.

### Simulating a production deployment

Here is an example of how we test production deployments:

First, we triggered the Jenkins job that copies the production environment's database and files into the development environment:

   

   

 ![Development deployment job](/sites/default/files/styles/wide_xs/public/assets/2017-07/dev-deploy-job_0.png.webp?itok=7Uh3Y2Zq "dev-deploy-job.png")

Here is the [log](https://gist.github.com/juampynr/085b03bef03c5e10f5074e3f834b1707). Once we had fresh data at the development environment, we triggered the job that kicks in when someone makes changes to the master branch (which ran the [Ansible task to update the database](https://github.com/AsociacionDrupalES/DrupalCampSpain/blob/master/ansible/tasks/after-symlink-tasks.yml)).

   

   

 ![Jenkins job to copy database and files](/sites/default/files/styles/wide_xs/public/assets/2017-07/dev-reload_0.png.webp?itok=TZgO09Er "dev-reload.png")

The job completed successfully (Yay!). I also opened the development environmentâ&#128;&#153;s website and verified that the new module was installed and that all the new features that we worked on the milestone were working as expected. We were ready to publish this to production!

### Hitting the button

The release was complete, and we tested its deployment. Therefore, we were ready to publish it. We used the Jenkins job that takes a git tag as a parameter, deploys the code to the production environment, and finally runs the post-deploy task to update the database. It worked!

When you test deployments beforehand, you get a deep understanding of what happens during such a process. It gets especially interesting when something goes wrong, as it gives you a chance to debug the deployment process locally, fix it, and test it again at the development environment until it works flawlessly.

What happens when a deployment goes wrong in production? Setting up a roll back process is something that deserves its own article. In the meantime, whatâ&#128;&#153;s your development and deployment process like? Do you have any suggestions? I am looking forward to hearing your insights below.

### Acknowledgements

This article was possible thanks to the following folks:

- [Pedro GonzÃ¡lez NITEMAN](https://www.drupal.org/u/niteman), for his help with the DrupalCamp Spainâ&#128;&#153;s infrastructure.
- [Matt Oliveira](https://www.lullabot.com/about/matt-oliveira), [James Sansbury](https://www.lullabot.com/about/james-sansbury), [Andrew Berry](https://www.lullabot.com/about/andrew-berry), and [Seth Brown](https://www.lullabot.com/about/seth-brown) for their technical and editorial reviews.

Footer image by By wÅ&#130;odi from London, UK (The Big Red ButtonUploaded by Yarl) \[[CC BY-SA 2.0](http://creativecommons.org/licenses/by-sa/2.0)\], [via Wikimedia Commons.](https://commons.wikimedia.org/wiki/File%3AThe_Big_Red_Button_(3085157011).jpg)

 Published in:

- [  Deployment   ](/topics/deployment)
- [  Drupal Development   ](/topics/drupal-development)

 

   You must have JavaScript enabled to use this form.

## Get in touch with us

### Tell us about your project. We'd love to hear from you!

 First Name  

 Last Name  

 Your email address  

 Your organization  

 How you heard about us  

 Tell us more 

     Leave this field blank