Continuous Integration with Jenkins
Before we conclude this chapter, here is a list of the key practices of Continuous Integration (as defined by Martin Fowler in 2006) with the examples of the ways in which Jenkins can be used to help you achieve them:
- Maintain a Single Source Repository: Jenkins can interact with all modern source code and version control repositories—some abilities are built-in, others can be added as extensions.
- Automate the Build: As described earlier in the use cases, this is one of the core aims of Jenkins and often the main driver to start using Jenkins.
- Make Your Build Self-Testing: This is usually the second step in setting up a CI environment with Jenkins—once you automate the building of the code, automating the tests as well is a natural progression.
- Everyone Commits To the Mainline Every Day: We can't really force developers to do this, unfortunately. However, we can quite easily highlight and report who is doing—or not doing—what, which should eventually help them learn to follow this best practice.
- Every Commit Should Build the Mainline on an Integration Machine: Builds can be triggered by developer commits, and Jenkins Slave Nodes can be used to build and provide accurate replica environments to build upon.
- Fix Broken Builds Immediately: This is another developer best practice that needs to be adopted—when Jenkins shows red, the top focus should be on fixing the issue until it shows green. No one should commit new changes while the build is broken, and Jenkins can be configured to communicate the current status in the most effective way.
- Keep the Build Fast: By offloading and spreading work to distributed Slave Nodes and by breaking down builds to identify and focus on the areas that have changed, Jenkins can be tuned to provide a rapid response to changes—a good target would be to check in a change and obtain a clear indication of the result or impact under 10 minutes.
- Test in a Clone of the Production Environment: After compiling the new change, downstream Jenkins jobs can be created that will prepare the environment and take it to the required level—applying database changes, starting up dependent processes, and deploying other prerequisites. Using virtual machines or containers in conjunction with Jenkins to automatically start up environments in a known-good state can be very useful here.
- Make it Easy for Anyone to Get the Latest Executable: Jenkins can be set up to act as a web server hosting the latest version at a known location so that everyone (and other processes/consumers) can easily fetch it, or it can also be used to send out details and links to interested parties whenever a new version has been uploaded to Nexus, Artifactory, and so on.
- Everyone can see what's happening: There are many ways in which Jenkins communications can be extended—email alerts, desktop notifications, Information Radiators, RSS feeds, Instant Messaging, and many more—from lava lamps and traffic lights to the ubiquitous toy rocket launchers!
- Automate Deployment: This is usually a logical progression of the
Build -> Test -> Deploy
automation sequence, and Jenkins can help in many ways; with Slave Nodes running on the deployment host, or jobs set up to connect to the target and update it with the most recently built artifact.
The benefits that can be realized once you have achieved the preceding best practices are often many and significant—your team will release software of higher quality and will do this more quickly and for less cost than before. However, setting up an automated build, test, and deployment pipeline will never be enough in itself; the tests, environment, and culture must be of sufficient quality too, and having the developers, managers, and business owners "buy in" to the processes and practices often makes all the difference.