Web applications are built by many people, but there are even more people who review, test, provide feedback and otherwise interact with an application during the development process. While most developers will collaborate using a source control system, it isn’t reasonable to expect non-developers to create a local copy of an application and run it.
The natural solution to this problem is to create one or more regularly updated development, staging, user acceptance and production environments where non-developers can view a regularly updated version of the application as it grows. It creates a new problem though; how do those environments then stay up to date?
Many organizations maintain these environments by a largely manual process. A developer will make a change or enhancement to a project, add that change to source control and then copy the same change over to one or more servers to show the rest of the team.
This solution is functional, but presents a few problems:
- Developers often forget to move all of their changes
- Developers may not be familiar with the setup of an individual server
- Developers might make changes directly to a server without that change being source control
- All of this copying of data takes time
These problems can lead to unstable or inconsistent environments making it difficult to deliver a polished end result. How can quality be assured when it isn’t certain the application being tested has all the latest updates? What if one developer overwrites the changes of another by bypassing source control and going directly to the server? What about all the time being wasted just copying data back and forth?
The good news here is that there is a better way: use a continuous integration server.
This isn’t a terribly new concept, though in my experience many organizations aren’t using one. The idea behind a CI server is simple – it is an automated tool that will reliably and consistently perform the steps necessary to move the latest code for an application to a target environment.
Whether you’re looking for frequent builds to an internal server during the peak of active development or irregularly scheduled deployments to a production environment there are major benefits to be had by using a CI server. By addressing the concerns with a manual process, it's easy to see how this is a preferential method.
Now let’s look at our above-mentioned issues:
- Developers often forget to move all of their changes – The CI server will move every single change, every single time
- Developers may not be familiar with the setup of an individual server – The CI server is set up with deployment steps that are appropriate for each environment
- Developers might make changes directly to a server without that change being source control – Using a CI server means no developer has any reason to directly access any environments other than their own
- All of this copying of data takes time – The CI server can be as simple as a click of the mouse, or even totally automated so that an addition to source control is automatically deployed
This should all sound great in theory, but it isn’t quite perfect. When Liquid first instituted our build server it was a godsend in terms of saving time and allowing developers to jump between projects. However, if you’re thinking about integrating a CI server into your process, there are a few things we’ve encountered along the way that we’d like to share.
- Without thorough unit test procedures in place the build server can only tell if the application successfully compiled, not if it is doing what it is supposed to. This means that a logic error can slip through the cracks and leave the resulting environment unstable. While unit testing and test driven development are important practices, they are also often the first things to get left behind when deadlines loom.
- Setting up an automated process to build and deploy code to various environments has more potential “gotchas” then we initially anticipated. Even the simple task of copying the built files can present challenges such as setting proper file permissions on the target environment or creating archives for quick rollback. Be sure to allocate ample time to adequately test and debug your build process.
- Timing of builds is not always an easy decision. Scheduled builds, such as hourly or nightly can be too slow for reviewers to see results. However, triggered builds (such as by a code check-in) can be too frequent and leave the environment in a constant state of rebuilding.
- Your CI server and target environments can become tied very closely to your build configuration and/or branching strategy. It’s taken some time for us to settle on a promotion strategy where no code goes into the master branch without being in the development branch first and our environments look something like this:
- Dev environment = Development branch (triggered or scheduled build)
- Staging/UAT environment = Master branch (triggered or scheduled build)
- Production environment = Master branch (manually triggered build)
- Other environments = Feature branches (varying build triggers)
Hopefully I haven’t swayed anyone away from considering this for their own use, because the above challenges also brought some unexpected benefits. We’ve been able to implement more robust code analysis tools than we have had before, including copy paste detection, linting, standards review and more. The build server provides an exceptional high level view of the code quality of each project as well as each developer’s contributions. It provides us with perfect starting points for reviewing and improving our performance with each successive project and even each commit.
In the end having a CI server in place has saved us a great deal of developer time as well as leading to better, more consistent end products then we were seeing without it. I would strongly encourage any development team, regardless of size, to consider how a CI server might serve their needs, and if they can find the same benefits from it that we did.
Did you like the topic of this post? Then you might also like to read these other posts from Jon Bailer:
About Jon Bailer
A technical lead at Liquid Interactive. Jon has over a decade of experience implementing custom technology solutions for a wide variety of clients.