Continuous Integration: The path to an errorless release

Diego Boedo
4 min readJun 4, 2015

Publishing a new version of an application is not a minor event. Besides having an anxious team of developers waiting to see the results of hard work in production, we have the users’, investors’ and company members’ expectation to see the new features that will give their product the desired quality jump. If we want to ensure that this process is 100% successful and error free, the best we can do is automate it. This is where the concept of Continuous Integration comes to the rescue.

It sounds obvious to state that as systems continue to grow in complexity and size, the impact each of them have on the source code is substantially greater. However, as small as a new functionality may be, or the change on a pre-existent feature, the higher the chances are that a functionality’s behavior will be affected (for example, one or several methods in a class). This is one of the main reasons why we test. But is this enough?

When the moment comes to launch a new version of the code, in many cases the process is practically manual. The person in charge of executing it may follow a checklist that looks like this:

  • Download the last version of the code
  • Run tests
  • Run a database backup
  • Release the new version (manually or making use of an appropriate tool, such as Capistrano).

However, the truth is that no one guarantees the checklist exists or that all of its steps are being followed. In fact, even if these were religiously followed, it doesn’t assure that the release process has no errors or warnings.

Surely, the code will be downloaded, gems and libraries will be installed, and migrations will run, as well as tests in their local development environment, which is completely different to the production environment. An error in the installation of a gem due to a lacking dependency will not be detected, as well as an error change within the database. And the list could get bigger…

The best way to improve this situation is to automate the process, which is when the concept of Continuous Integration comes into the picture. It consists of automating the code integration process to detect errors as soon as possible. This sounds good, but how do we do it?

Jenkins & GitHub, a good combination

There are many alternatives to set up a Continuous Integration Service. Lateral View chooses Jenkins (https://jenkins-ci.org/) given that it is Open Source and has a fairly big user community. Moreover, it gives us the freedom to extend its behavior via plugins, which allows us to adapt the system to our processes, and not the other way round.

Therefore, our deploy process can be summed up into two tasks in Jenkins. In the first place, it automatically detects Pull Requests to master or staging branches, and executes a series of subtasks with the aim of creating a new build:

  • Download the source code
  • Installation of the necessary gems
  • Application of necessary changes to database
  • Run tests

If the build has been created without errors, it notifies GitHub alerting that the merge can be done. If any of the previous steps failed, it also notifies GitHub with the error.

When the build creation process has started, Jenkins notifies GitHub about it.

It’s important to highlight that the creation process for a new build is run in a similar environment to the production server. When the Pull Request is approved, the only thing missing is to deploy. For this we have a second task for Jenkins, which takes care of monitoring changes in staging or production. Once new commits are detected, the following steps take place:

  • Download the source code.
  • Database backup generation (only for production).
  • New version of the code is released.
  • Server is restarted.
All right! Now, we can merge without problems.

Summing Up

At this point, we can consider that the advantages of making use of a continuous integration system are noticeable. In the first place, we make sure that both tests and backups are always run. There’s no room left for human error. On the other hand, we can expose dependencies and database related problems, which are much harder to detect in the development environment.

Finally, this configuration allows us to upload system updates from any place or device. We are no longer limited to a machine where the person responsible for the project has access keys to the production server. it only takes to create a Pull Request in GitHub, and if all goes smoothly, apply the corresponding merge and Jenkins will take care of the rest of the process automatically.

Cool, right?

--

--