This week we follow up from our discussion on Code Review with a look at the Continuous Integration (CI) software development philosophy. We'll highlight best practices, go over commonly used build terms and suggest tools that can help startup teams effectively use it.
So what is CI? The CI mantra focuses on rapid integration and automation: One should integrate code with the existing code repository as frequently as possible to minimize integration conflicts, while also being able to create builds automatically based on some triggering mechanism.
This fits well with the needs of startup teams, who often find themselves facing short product-development life cycles. Other benefits include:
- Reduction in repetitive manual processes – A typical build process requires some forms of code compilation, database integration, integration testing, inspection, deployment and feedback. Automating these processes can help startups save time and money and allow developers to focus more on development.
- The ability to release deployable software at any time – With CI, any small change you make and integrate into the source code will be done consistently. If there are problems, the team is notified instantly and the fixes are applied. Teams who do not embrace this practice will wait until immediately after delivery of a build to integrate and test the software. This can delay release or prevent fixing certain defects, which will cause new defects while the team is rushing to complete the product.
- Better visibility aka analytics – Often, startups begin projects with no previous data, which prevents them from noticing trends and making effective project decisions. While data can be mined manually from sources such as SQL queries or Git-metadata, the effort can be burdensome. A CI system can provide just-in-time information on builds and quality metrics based on tests that were run with each build.
Best Practices
- Commit often - By following a frequent schedule, all developers can reduce the number of merge/integration changes downstream. Early, small conflicts in an area of the system encourages team members to be actively engaged about the changes they are making, which only enforces a better understanding of the code base in the long run.
- Every commit to the main product branch should be built - The system should build commits to the current working version to verify that integration is sound. While this can be done manually, automation can help save time and effort. And you’re in luck, most CI solutions offer automation!
- Automate, automate, automate - Many tools support automation of the continuous integration build process to encourage frequency of code submissions. However, automation also encourages teams to build solid test cases that are repeatable to help confirm that the build behaves in the way the developer expects. Most CI systems also support plugins and scripts, such as packaging, that are utilized after a build finishes. This way, development can focus on making the product while the actual delivery of the product can be made seamless.
- Communicate results - It should be easy for everyone to see the results of the latest build to get an accurate context of the latest state of the build.
CI Terms and Definitions
This section will cover some technical terms that are commonly part of any CI system:
- Build configuration - Describes a set of procedures used to create a build. This can include integration builds, release builds, nightly builds and others. Build configurations are usually represented by an .xml file (ie POM.xml in Maven) which contains details such as:
- Username/password to access a VCS repository
- Goals or set of tasks to be executed such as a script that runs a set of test cases
- Triggering
- Build agent - A piece of software that actually executes the build process as represented by the build configuration. It can be installed on the same computer as the CI server or on a different machine, which is usually the preferred option for server performance reasons. An agent will usually perform some of these steps:
- Use the POM.xml to check out the source code and download artifacts of other builds to run the build process if defined in the configuration.
- The number of agents basically limit the number of parallel builds and environments in which your build processes are run.
- Build artifact – An object produced by the software development process. This can include either compiled source code (executable) or documentation related to the software. Build tools, such as Maven, use build configuration files (ie. POM.xml) to describe how an artifact is built, how unit tests are run, etc.
CI Tools
Jenkins/Hudson
Both free and open-sourced under the MIT License, Jenkins and Hudson share the same origins and offer similar features. The differences lie primarily in the management of the tools:
- Supported by Oracle, Hudson has fewer frequent releases than Jenkins but is more heavily tested to ensure backward compatibility. Teams in enterprise environments might be more comfortable with Hudson given the “enterprise-style” approach to release management. Hudson favours the use of Maven and/or Nexus for its repository and artifact management. This is different from Jenkins, which works well with Gradle and other build system/artifact repositories
- Jenkins relies on the developer community to provide support and this can be found on both their GitHub and JIRA environments. Hudson provides professional support from SontaType and Oracle.
- According to Cloudbees, Jenkins boasts a far larger amount of plug-ins than Hudson. However, for most developer concerns, both CI solutions offer a wide range of support for the following environments/tools:
- All distributed version control systems such as Git and SVN. Centralized VCS such as Perforce and ClearCase are also supported.
- Similar support for test suits for Ruby/Rails, .Net and Java development.
TeamCity offers its CI solution through a licence-based service. Free for small teams, the cost is significant for teams that require more than 20 build configurations and/or 3 build agents. Just like with Jenkins/Hudson, TC has an official GitHub plug-in and can support all the common version control systems. Further, it also supports popular build tools such as:
- MSBuild for .Net
- Ant, Maven and Gradle for Java
- RVM, Bundler and Ruby SDK for Ruby on Rails
TC stands out for its proprietary development environment and code coverage solutions that integrate well with its CI services. While all three CI tools offer support for Eclipse, TC offers its own proprietary code coverage apps for each development language including:
- JetBrains dotCover for .Net
- JetBrains RubyMine for Ruby on Rails