Continuous Integration, Delivery, and Deployment - Sander Rossel - E-Book

Continuous Integration, Delivery, and Deployment E-Book

Sander Rossel

0,0
41,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Getting started with the processes and the tools to continuously deliver high-quality software

About This Book

  • Incorporate popular development practices to prevent messy code
  • Automate your build, integration, release, and deployment processes with Jenkins, Git, and Gulp?and learn how continuous integration (CI) can save you time and money
  • Gain an end-to-end overview of Continuous Integration using different languages (JavaScript and C#) and tools (Gulp and Jenkins)

Who This Book Is For

This book is for developers who want to understand and implement Continuous Integration and Delivery in their daily work. A basic knowledge of at least JavaScript and HTML/CSS is required. Knowing C# and SQL will come in handy. Most programmers who have programmed in a (compiled) C-like language will be able to follow along.

What You Will Learn

  • Get to know all the aspects of Continuous Integration, Deployment, and Delivery
  • Find out how Git can be used in a CI environment
  • Set up browser tests using Karma and Selenium and unit tests using Jasmine
  • Use Node.js, npm, and Gulp to automate tasks such as linting, testing, and minification
  • Explore different Jenkins jobs to integrate with Node.js and C# projects
  • Perform Continuous Delivery and Deployment using Jenkins
  • Test and deliver a web API

In Detail

The challenge faced by many teams while implementing Continuous Deployment is that it requires the use of many tools and processes that all work together. Learning and implementing all these tools (correctly) takes a lot of time and effort, leading people to wonder whether it's really worth it. This book sets up a project to show you the different steps, processes, and tools in Continuous Deployment and the actual problems they solve.

We start by introducing Continuous Integration (CI), deployment, and delivery as well as providing an overview of the tools used in CI. You'll then create a web app and see how Git can be used in a CI environment. Moving on, you'll explore unit testing using Jasmine and browser testing using Karma and Selenium for your app. You'll also find out how to automate tasks using Gulp and Jenkins. Next, you'll get acquainted with database integration for different platforms, such as MongoDB and PostgreSQL. Finally, you'll set up different Jenkins jobs to integrate with Node.js and C# projects, and Jenkins pipelines to make branching easier.

By the end of the book, you'll have implemented Continuous Delivery and deployment from scratch.

Style and approach

This practical book takes a step-by-step approach to explaining all the concepts of Continuous Integration and delivery, and how it can help you deliver a high-quality product.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 582

Veröffentlichungsjahr: 2017

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Continuous Integration, Delivery, and Deployment                    
Reliable and faster software releases with automating builds, tests, and deployment
Sander Rossel

 

 

 

BIRMINGHAM - MUMBAI

Continuous Integration, Delivery, and Deployment

 

Copyright © 2017 Packt Publishing  

 

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

 

 

First published: October 2017

 

 

Production reference: 1271017

 

 

Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.

ISBN 978-1-78728-661-0

 

www.packtpub.com

Credits

Author

Sander Rossel

Copy Editor

Akshata Lobo

Reviewers

Wen Gu

Oleksandr Tkachuk

Rui Vilão

Olga Filipova

Project Coordinator

Devanshi Doshi

Commissioning Editor

Ashwin Nair

Proofreader

Safis Editing

Acquisition Editor

Shweta Pant

Indexer

Pratik Shirodkar

ContentDevelopmentEditor

Roshan Kumar

Graphics

Jason Monteiro

Technical Editors

Bharat Patil

Sachin Sunilkumar

Harshal Kadam

Production Coordinator

Shraddha Falebhai

About the Author

Sander Rossel is a professional developer with working experience in .NET (VB and C#, WinForms, MVC, Web API, and Entity Framework), JavaScript, Git, Jenkins, Oracle, and SQL Server. He has an interest in various technologies including, but not limited to, functional programming, NoSQL, Continuous Integration (and more generally, software quality), and software design.

He has written two e-books so far: Object-Oriented Programming in C# Succinctly and SQL Server for C# Developers Succinctly, which you can download from Syncfusion for free. He seeks to educate others through his articles on his CodeProject profile, and through his book writing.

I would like to thank my parents for their support and advice. Also, of course, I would like to thank the people at Packt, and especially Shweta Pant, Johann Barretto and Roshan Kumar, for making this book possible.

About the Reviewers

Wen Gu has worked at several industry leading technology companies. He led the effort to create large-scale Continuous Integration and Continuous Delivery platforms and solutions to drive the adoption of Continuous Integration and Continuous Delivery.

I would like to thank to my wife, Annie, and my daughter, Tiffany, for their inspiration and love. I would also like to thank my colleagues at work for their encouragement and advice.

Oleksandr Tkachuk has more than 15 years of experience. He has been working as a software engineer and is responsible for full life cycle development of next-generation software, from initial requirement gathering, planning, and analysis to design, coding, testing, documentation, and implementation.

He graduated from Lviv Polytechnic National University, Ukraine, with a master's degree in computer systems and networks.

He worked as a Senior Developer, Team Leader, Solution Architect, Solution Architect, and also worked in Ukraine, UK, and Germany IT companies.

This is his first reviewed book.

Rui Vilão and Olga Filipova are a happy couple of software engineers and travelers currently living in Berlin. Rui is originally from Coimbra, Portugal, and Olga is from Kiev, Ukraine.

Both Rui and Olga are technical cofounders of a non-profit online education project called EdEra based in Ukraine. Besides that, Olga is a lead software engineer at a fintech company called OptioPay based in Berlin, and Rui is a lead software engineer at an online fitness company called Gymondo based in Berlin.

They live in Berlin since 2014; before that, they lived in Portugal, where both graduated as masters in computer science and worked for 5 years at Feedzai--the most successful Portuguese startup that prevents fraud all over the world.

Olga is author of Learning Vue.js 2 and Web development with Vue.js, Bootstrap, and Firebase, and Rui unofficially reviewed both these books.

www.PacktPub.com

For support files and downloads related to your book, please visit www.PacktPub.com. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details. At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.

https://www.packtpub.com/mapt

Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.

Why subscribe?

Fully searchable across every book published by Packt

Copy and paste, print, and bookmark content

On demand and accessible via a web browser

Customer Feedback

Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/1787286614. If you'd like to join our team of regular reviewers, you can e-mail us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!

Table of Contents

Preface

What this book covers

What you need for this book

Who this book is for

Conventions

Reader feedback

Customer support

Downloading the example code

Downloading the color images of this book

Errata

Piracy

Questions

Continuous Integration, Delivery, and Deployment Foundations

Continuous Integration

Source control

CI server

Software quality

Unit tests

Integration tests

Big bang testing

Incremental testing

Acceptance tests

Smoke tests

Other quality gates

Automation

Teamwork

Continuous Delivery

Continuous Deployment

Summary

Setting Up a CI Environment

Installing a Virtual Machine

Installing Ubuntu

Installing Git

Installing GitLab

Configuring GitLab

Using Git

Installing Jenkins

Installing Jenkins on Ubuntu

Installing Jenkins on Windows

Configuring Jenkins

Installing PostgreSQL

Installing PostgreSQL on Ubuntu

Installing PostgreSQL on Windows

Installing pgAdmin

Installing SonarQube

Configuring PostgreSQL

Installing SonarQube on Ubuntu

Installing SonarQube on Windows

Trigger SonarQube from Jenkins

Summary

Version Control with Git

The basics

Centralized Source Control Management

Distributed Source Control Management

The working directory

The staging area

Committing and pushing

Reviewing commits

Pulling and stashing

Branching

Merging

Cherry picking

Rebasing

Reverting changes

The branching model

Tagging

Summary

Creating a Simple JavaScript App

The web shop specs

Installing Node.js and npm

Creating the project

Creating the Home page

Creating the Product page

Creating the Search page

Creating the Shopping cart page

Summary

Testing Your JavaScript

Unit testing with Jasmine

The Yeoman shortcut

Why Jasmine?

Testing the web shop

Running tests with Karma

Installation

Karma plugins

Browser launchers

Code coverage

JUnit reporter

Running Mocha and Chai with Karma

End-To-End testing with Selenium

Running Selenium tests with Protractor

Testing our website

Customizing reporters

Testing with Mocha

Headless browser testing

PhantomJS

Summary

Automation with Gulp

Gulp basics

The Gulp API

Gulp plugins

Minification

Cleaning your build

Checking file sizes

Linting with JSHint

Running your Karma tests

Getting our site production ready

Minifying HTML

Minifying CSS

Bundling JavaScript with Browserify

Karma and Browserify

Concatenating CSS

Replacing HTML references

Putting it all together

Summary

Automation with Jenkins

Installing Node.js and npm

Creating a Jenkins project

Executing Gulp in Jenkins

Publishing test results

JUnit report

Cobertura report

HTML report

Build triggers

Build periodically

Poll SCM

On commit

Setting up email notifications

Setting up SonarQube

Setting up email

HTML and CSS analysis

Including code coverage

Leak periods

Artifacts

Running on Windows with Jenkins Slaves

Running our tests

Triggering a project pipeline

Summary

A NodeJS and MongoDB Web App

Installing MongoDB

Installing MongoDB on Ubuntu

Installing MongoDB on Windows

Creating the Node.js Back-end

Express

EJS

The Login Page

Connecting with AJAX

Saving to MongoDB

Moving our Products to MongoDB

Putting the Shopping Cart in MongoDB

Moving the Shopping Cart Module

Gulp

Jenkins

PM2

Summary

A C# .NET Core and PostgreSQL Web App

Installing .NET Core and Visual Studio Code

Creating the views

Running tasks

Adding the database

Entity Framework Core

Selecting the data

Fixing the login

Adding to the cart

Testing the database

Installing pgTap

Testing our C# code

Reporting

Adding Selenium tests

Jenkins

Building the project

Testing the project

Testing the database

Summary

Additional Jenkins Plugins

Views

Cleanup workspaces

Conditional build steps

Pipelines

Promoted builds

Parameterized builds

Triggering builds remotely

Blue ocean

Security

Jenkins on HTTPS

HTTPS on Linux

HTTPS on Windows

Jenkins security

Role-based authorization strategy

Summary

Jenkins Pipelines

Groovy

Pipeline projects

Declarative pipeline syntax

Scripted pipeline syntax

Pipeline stages

The snippet generator

Building the web shop

The Jenkinsfile

Multibranch pipeline

Branch scripts

Completing the script

Node.js tests

SonarQube

Selenium tests

Archiving artifacts

Build failure

Summary

Testing a Web API

Building a REST service

Postman

Writing tests

Testing XML

Collections

Environments

Newman

Summary

Continuous Delivery

Branching

Manual deployment

Installing NGINX

Node.js web shop

PM2

MongoDB

Run

E2E testing

C# .NET Core web shop

Run

PostgreSQL

Summary

Continuous Deployment

JavaScript Deployment using SSH

E2E testing

C# .NET Core Deployment using SSH

E2E testing

Database

Summary

Preface

A problem that a lot of developers face is that software is complex and becomes only more complex over time. A single change to the software can lead to numerous unexpected bugs that may not be discovered in time. Using Continuous Integration, we can automatically test software before it is released. Using other tools, such as SonarQube, we can ensure that our code adheres to the latest standards. Unfortunately, getting started with testing and automation requires various tools and all of those tools take time and effort to learn.

In this book, we will start a project from scratch and use Continuous Integration techniques to guarantee a certain software quality. Tools such as Git, Jasmine, Karma, Selenium, Protractor, Gulp, Jenkins, SonarQube, and Postman are introduced and used to ensure that our software is up to par.

Finally, to further reduce the chances of human error, we will automatically deploy our software to another environment so that we can go from Git commit to production deployment fully automated and still sleep easy at night.

What this book covers

Chapter 1, Continuous Integration, Delivery, and Deployment Foundations, starts by exploring some of the theory covering Continuous Integration, Delivery, and Deployment, as well as the differences between the three.

Chapter 2, Setting Up a CI Environment, teaches us how to install our environment. We will set up a Linux Virtual Machine and install some of the tools we will use throughout the book, such as Jenkins, PostreSQL, and SonarQube.

Chapter 3, Version Control with Git, source control is a necessity for any software project and is also a prerequisite for CI, so this explores Git and how to work with it, both from a command line as well as from a graphical tool.

Chapter 4, Creating a Simple JavaScript App, says that before we can continue, we need a project, so we will create a simple web shop using only frontend technologies. Throughout the rest of the book, we will use this app and expand on it.

Chapter 5, Testing Your JavaScript, informs us that we can start writing tests for our project using the project from Chapter 4, Creating a Simple JavaScript App. For our unit tests, we will use Jasmine and Karma, and for our End-To-End (E2E) tests, we will use Selenium and Protractor.

Chapter 6, Automation with Gulp, begins with automating our tests and adding other tasks, such as linting and other frontend work, to our automated build using Gulp.

Chapter 7, Automation with Jenkins, takes our automation a step further with Jenkins. With Jenkins, we can run tasks automatically on any Git commit so that no code is left untested.

Chapter 8, A NodeJS and MongoDB Web App, informs us that moving our app forward, we will add a Node.js and MongoDB backend for our web shop. This presents us with some new challenges that are best automated.

Chapter 9, A C# .NET Core and PostgreSQL Web App, repeats Chapter 8, A NodeJS And MongoDB Web App, but with C# .NET Core and PostgreSQL. Additionally, we will add SQL database tests.

Chapter 10, Additional Jenkins Plugins, explores Jenkins further now that our apps are pretty much done. We will see plugins that will make your life easier and your options greater.

Chapter 11, Jenkins Pipelines, dives deeper into Jenkins to explore Jenkins pipelines, which are basically Jenkins configuration in code. This opens up new possibilities in Jenkins.

Chapter 12, Testing a Web API, is a little unrelated to the rest of the book, but not unimportant; here, we will take a look at Postman and API testing.

Chapter 13, Continuous Delivery, takes us near to the end of the book, and all that is left is to deploy our apps. First, we will do a manual deployment, and then automate this task using Jenkins.

Chapter 14, Continuous Deployment, concludes with completely automating our entire deployment process. The goal of this chapter is to get a Git commit to production without any manual intervention.

What you need for this book

For this book, we will need various software, but everything is explained in the chapters of this book. A computer with at least 16 GB memory is advised.

Who this book is for

The audience will typically be the developer. Developers tend to lose themselves in their code while missing the bigger picture. Continuous Integration, for many developers, is something that must be done, but is not truly understood by many. This book will get developers, but hopefully also team leads, into Continuous Integration and Continuous Deployment, and show them the added value it brings. Basic knowledge of at least JavaScript and HTML/CSS is required. Knowledge of C# and SQL comes in handy. Most programmers that have programmed in a (compiled) C-like language should be able to follow along.

Conventions

In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.

Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "A thousand-line function with multiple nested if and while loops (and I've seen plenty) is pretty much untestable." A block of code is set as follows:

public static class MyMath { public static int Add(int a, int b) { return a + b; } }

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

<!DOCTYPE html><html> <head> [...] </head> <body ng-app="shopApp">

<%- include navbar.ejs %>

<div class="container" ng-controller="productController"> [...] </div> </body></html>

Any command-line input or output is written as follows:

sudo apt-get update

sudo apt-get install ubuntu-desktop

New terms and important words are shown in bold. Words that you see on the screen, for example, in menus or dialog boxes, appear in the text like this: "Git will rewind your work until it finds the master, which is after the Added weapons commit."

Warnings or important notes appear like this.
Tips and tricks appear like this.

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.

Downloading the example code

You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. You can download the code files by following these steps:

Log in or register to our website using your email address and password.

Hover the mouse pointer on the

SUPPORT

tab at the top.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box.

Select the book for which you're looking to download the code files.

Choose from the drop-down menu where you purchased this book from.

Click on

Code Download

.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR / 7-Zip for Windows

Zipeg / iZip / UnRarX for Mac

7-Zip / PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Continuous-Integration-Delivery-and-Deployment. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

Downloading the color images of this book

We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/ContinuousIntegrationDeliveryandDeployment_ColorImages.pdf.

Errata

Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.

Piracy

Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.

Questions

If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.

Continuous Integration, Delivery, and Deployment Foundations

Continuous Integration, Delivery, and Deployment are relatively new development practices that have gained a lot of popularity in the past few years. Continuous Integration is all about validating software as soon as it's checked in to source control, more or less guaranteeing that software works and continues to work after new code has been written. Continuous Delivery succeeds Continuous Integration and makes software just a click away from deployment. Continuous Deployment then succeeds Continuous Delivery and automates the entire process of deploying software to your customers (or your own servers).

If Continuous Integration, Delivery, and Deployment could be summarized with one word, it would be Automation. All three practices are about automating the process of testing and deploying, minimizing (or completely eliminating) the need for human intervention, minimizing the risk of errors, and making building and deploying software easier up to the point where every developer in the team can do it (so you can still release your software when that one developer is on vacation or crashes into a tree). Automation, automation, automation, automation...Steve Ballmer, would say, while stomping his feet on the ground and sweating like a pig.

The problem with Continuous Integration, Delivery, and Deployment is that it's not at all easy to set up and takes a lot of time, especially when you've never done it before or want to integrate an existing project. However, when done right, it will pay itself back by reducing bugs, making it easier to fix the bugs you find and producing better quality software (which should lead to more satisfied customers).

The terms Continuous Integration, Continuous Delivery, and Continuous Deployment are often used incorrectly or interchangeably (and then I've also seen the term Continuous Release). People say Continuous Integration when they mean Continuous Deployment, or they say Continuous Deployment when they mean Delivery, and so on. To make matters more complex, some people use the word DevOps when they mean any of the Continuous flavors. DevOps, however, is more than just Continuous Integration, Delivery, and/or Deployment. When talking to people about any of these subjects, don't make assumptions and make sure you're using the same definitions. DevOps is outside the scope of this book.

Continuous Integration

The first step to delivering consistent and high-quality software is Continuous Integration (CI). CI is all about ensuring your software is in a deployable state at all times. That is, the code compiles and the quality of the code can be assumed to be of reasonably good quality.

Source control

CI starts with some shared repository, typically a source control system, such as Subversion (SVN) or Git. Source control systems make sure all code is kept in a single place. It's easy for developers to check out the source, make changes, and check in those changes. Other developers can then check out those changes.

In modern source control systems, such as Git, you can have multiple branches of the same software. This allows you to work on different stages of the software without troubling, or even halting, other stages of the software. For example, it is possible to have a development branch, a test branch, and a production branch. All new code gets committed on development; when it is tested and approved, it can move on to the test branch and, when your customer has given you approval, you can move it into development. Another possibility is to have a single main branch and create a new (frozen) branch for every release. You could still apply bug fixes to release branches, but preferably not new features.

Don't underestimate the value of source control. It makes it possible for developers to work on the same project and even the same files without having to worry too much about overwriting others' code or being overwritten by others.

Next to code, you should keep everything that's necessary for your project in your repository. That includes requirements, test scripts, build scripts, configurations, database scripts, and so on.

Each check into this repository should be validated by your automated build server. As such, it's important to keep check-ins small. If you write a new feature and change too many files at once, it becomes harder to find any bugs that arise.

CI server

Your builds are automated using some sort of CI server. Popular CI server software includes Jenkins (formerly Hudson), Team Foundation Server (TFS), CruiseControl, and Bamboo. Each CI server has its own pros and cons. TFS, for example, is the Microsoft CI server and works well with .NET (C#, VB.NET, and F#) and integrates with Visual Studio. The free version only has limited features for only small teams. Bamboo is the Atlassian CI server and, thus, works well with JIRA and BitBucket. Like TFS, Bamboo is not free. Jenkins is open source and free to use. It works well for Java, in which Jenkins itself was built, and works with plugins. There are a lot of other CI servers, all with their own pros and cons, but the thing they all have in common is that they automate software builds. For this book, we will use Jenkins as the CI server of choice.

Your CI server monitors your repository and starts a build on every check in. A single build can compile your code, run unit tests, calculate code coverage, check style guidelines, lint your code, minify your code, and much more. Whenever a build fails, for example, because a programmer forgot a semi-colon and checked in invalid code or because a unit test fails, the team should be notified. The CI server may send an email to the programmer who committed the offending code, to the entire team, or you could do nothing (which is not best practice) and just check the status of your build every once in a while. The conditions for failure are completely up to the developer (or the team). Obviously, when your code does not compile correctly because it's missing a semicolon, that's a fail. Likewise, a failing unit test is an obvious fail. Less obvious is that a build can fail when a certain project does not have at least a 90% test code coverage or your technical debt, that is, the time it takes to rewrite quick and dirty solutions to more elegant solutions grows to more than 40 hours.

The CI server should build your software, notify about failures and successes, and ultimately create an artifact. This artifact, an executable of the software, should be easily available to everyone on the team. Since the build passed all of the teams, criteria for passing a build, this artifact is ready for delivery to the customer.

Software quality

That brings us to the point of software quality. If a build on your CI server succeeds, it should guarantee a certain level of software quality. I'm not talking perfect software that is bug-free all of the time, but software that's well tested and checked for best practices. Numerous types of tests exists, but we will only look at a few of them in this book.

Integration tests

Checking whether an Add function really adds a and b is nice, but does not really give you an indication that the system as a whole works as well. As said, unit tests only test small and isolated units of code and should not interact with external components (external components are mocked). That is why you will want integration tests as well. Integration tests test whether the system as a whole operates as expected. We need to know whether a record can indeed be saved in and retrieved from a database, that we can request some data from an external service, and that we can log to some file on the filesystem. Or, more practically we can check whether the frontend that was created by the frontend team actually fits the backend that was created by the backend team. If these two teams have had any problems or confusion in communication, the integration tests will, hopefully, sort that out.

Last year, we created a service for a third party who wanted to interface with a system we wrote. The service did not do a lot basically it took the received message and forwarded it to another service that we used internally (and wasn't available outside of the network). The internal service had all of the business rules and could read from, and write to, a database. Furthermore, it would, in some cases, create additional jobs that would be put on a (asynchronous) queue, which is yet another service. Last, a fourth service would pick up any messages from the queue and process them. In order to process a single request, we potentially needed five components (external service, internal service, database, queue, and queue processor). The internal service was thoroughly unit tested, so the business rules were covered. However, that still leaves a lot of room for errors and exceptions when one of the components is not available or has an incompatible interface.

Big bang testing

There are two approaches to integration testing: big bang testing and incremental testing. With big bang testing, you simply wait until all the components of a system are ready and then start testing. In the case of my service, that meant developing and installing everything, then posting some requests and checking whether the external service could call the internal service, and whether the internal service could access the database and the queue and, not unimportant, give feedback to the external service. Furthermore, of course, I had to test whether the queue triggered the processing service and whether the processing service processed the message correctly too.

In reality, the processing also used the database; it put new messages on the queue and sent emails in case of errors. Additionally, all the components had to access the hard drive for logging to a file (and do not assume the filesystem is always available; the first time on production I actually ran into an Unauthorized Exception and nothing was logged). So that means even more integration testing.

Incremental testing

With incremental testing, you test components as soon as they are available and you create stubs or drivers (some sort of placeholder) for components that are not yet available. There are two approaches here:

Top-down testing

: Using top-down testing would mean I would've checked whether the external service could make a call to the internal service and, if the internal service was not available yet, create a stub that pretends to be the internal service.

Bottom-up testing

: Bottom-up is testing the other way around, so I'd start testing the internal service and create a driver that mimics the external service.

Incremental testing has the advantage that you can start defining tests early before all the components are complete. After that, it becomes a matter of filling in the gaps.

Acceptance tests

After having unit tested our code and checked whether the system as a whole works, we can now assume our software works and is of decent quality (at least, the quality we expect). However, that does not mean that our software actually does what was requested. It often happens that the customer requests feature A, the project manager communicates B, and the programmer builds C. There is a really funny comic about it with a swing (do a Google image search for how projects really work). Luckily, we have acceptance tests.

An acceptance test tests whether specific functionality, as described in the specification, works as expected. For example, the external service we built made it possible for the third party to make a call using a specific login method, create a user, update the user, and finally, deactivate that user. The specifics of the updates were described in the specifications document. Some fields were specified by the third party and some fields were calculated by the service. Keep in mind that the actual calculations had been unit tested and that we knew all the parts worked together as we had done some integration testing. This test was all about testing whether the third party, using their Java technology (our service was written in C#, but communication was XML), could indeed create and update a user. I probably tested that manually once or twice. The problem with testing this manually was that it was a web service; the input and output was XML which is not that easy to read and write. The service only returned whether or not the user was successfully created (and if not, why) so in order to test whether everything had gone well, I needed to look up the user record in the database, along with all other records that should have been created. I knew how to do that at the time, but if I needed to do it again now, I'd be pretty frustrated. And if I do not know how to properly test it, then how will my coworkers who need to make changes to the service know? Needless to say, I created something like 30 automated tests that check whether specific use cases work as intended.

Another one of our applications, a website, works pretty much the same. A user can create a record on page A, look it up on page B, and update it. Obviously, XML is not going to cut it here; this is not a web service. In this case, we used GUI tests (that is, Graphical User Interface tests). Our build server is just going to run the application and click on the buttons that we told it to click. If the button is not available, we've got ourselves an error. If the button is available, but does not take us to the requested page, we've got an error. If the page is correctly loaded, but the record is not visible (for whatever reason), we've got an error. The important thing here is that the tests do more or less exactly what our users will do as well.

There is some confusion on the difference between integration tests and acceptance tests. Both test the entire system, but the difference is that integration tests are written from a technical perspective while acceptance tests are written from the perspective of the product owner or business users.

Smoke tests

Of course, even when all of your tests succeed, a product can still break in production. The database may be down or maybe you have a website and the web server is down. It is always important to also test whether your software is actually working in a production environment, so be sure to always do an automated smoke test after deployment that gives you fast and detailed feedback when something goes wrong. A smoke test should test whether the most important parts of your system work. A manual smoke test is fine (and I'd always manually check whether your software, at least, runs after a release), but remember it's another human action that may be forgotten or done poorly.

Some people run smoke tests before doing integration and acceptance tests. Integration and acceptance tests test an entire system and, as such, may take a bit of time. A smoke test, however, tests only basic functionality, such as does the page load? When a smoke test fails, you can skip the rest of your tests, saving you some time and giving you faster feedback.

There are many types of tests available out there. Unit tests, smoke tests, integration tests, system tests, acceptance tests, database tests, functional tests, regression tests, security tests, load tests, UI tests... it never ends! I'm pretty sure you could spend an entire year doing nothing but writing tests. Try selling that to your customer; you can't deliver any working software, but the software you can't deliver is really very well tested. Personally, I'm more pragmatic. A test should support your development process, but a test should never be a goal on its own. When you think you need a test, write a test. When you don't, don't. Unfortunately, I have seen tests that did absolutely nothing (except give you a false sense of security), but I'm guessing someone just wanted to see tests, any tests, really bad.

Other quality gates

Next to tests, you want other measurements of code quality. For example, code that has many nested if statements is hard to test and understand. Writing an if statement without curly braces (for single statements) will increase the chances of bugs in the future. Not closing database connections or file handles may lock up your system and cause other processes to fail. Failing to unsubscribe from (static) events may cause memory leaks. Such errors may easily pass unit tests, but will eventually fail in production. These sort of errors can be very difficult to find as well. For example, a memory leak may cause your application to run slowly or even crash after a day or two. Good luck finding bugs that only happen to some users, sometimes, because they haven't closed the application in two days. Luckily, there are tools that find exactly these kinds of issues. SonarQube is one such tool. It will show you where you can improve your code, how important it is that you fix this code, the time it will probably take to fix it, and a trending graph of your technical debt.

It is important to note here that these issues, unlike unit tests, may or may not be actual bugs. For example, the following code is completely valid, but may introduce bugs that are not easy to spot:

if (valid) DoSomething();

Now the specifications change and you, or a coworker, have to change this code so something else is also executed when valid. You change the code as follows:

if (valid) DoSomething(); DoSomethingElseIfValid(); // This is a bug as it's always executed.

Tools such as SonarQube, will recognize this pattern and they will warn you that the code is not best practice including an explanation on what's wrong with it and how to change it. In this case, the original code should be changed, so it's clear what happens when valid:

if (valid) { DoSomething(); }

We will have a look at SonarQube later in this book and see both C# and JavaScript issues that may or may not be bugs.

Automation

Depending on what you're used to, I've got some bad news for you. When doing CI, the command line is your best friend. Personally, I see the need for a command line, but I don't like it one bit. It requires way too much typing and memorization for my taste. Anyway, Linux users rejoice and spoiled Windows users get ready for a trip back to the 80s when user interfaces had yet to be invented. However, we're going to automate a lot, and that will be the computer's job. Computers don't use user interfaces. So, while you hit F5 in Visual Studio and compile your code, your build server needs to know it should run MSBuild with some parameters, such as the location of your solution or the msbuild file.

Luckily, most tools have some form of command-line interface. Whether you are working with .NET, JavaScript, Java, SQL Server, Oracle, or any language or tool, you can always run it using a command line. Throughout this book, we will use various tools and I do not think we will use any of them without using the command line as well. In fact, the command line seems to be back (although, was it ever really gone?). Various tools, such as NodeJS, npm, and MongoDB, are used through the command line. Furthermore, we will see tools, such as MSBuild, MSTest, and NuGet, that all work from the command line (or from a single click in your IDE).

Teamwork

Imagine doing all this locally on your own computer. For simplicity, let's say you've got some code that has to compile and some unit tests that have to run. Easy enough, everybody should be able to do that. Except your manager, who doesn't have the developer software installed at all. Or the intern, who forgot to kick off the unit tests. Or the developer, who works on a different OS making some tests, that aren't important to him, fail (for example, we have an application developed on and for Windows, but a complimentary app for iOS developed on a Mac). Suddenly, getting a working and tested executable becomes a hassle for everyone who isn't working on this project on a daily basis. Besides, the people who can get a working executable may forget to run tests, creating a risk that the executable is compiling, but not actually working. As you can see, a lot can go wrong and there are only two steps. I've intentionally left out all the other tests and quality gates we might have. And that's the biggest benefit to CI. The software is compiled and fully tested automatically, reducing the chance of human errors and making it considerably easier to get a working executable that is more or less guaranteed to work. By testing on a server that closely or completely resembles the production environment, you can further eliminate hard to find bugs.

As you might have guessed, CI is not something you just do. It's a team effort. If you're writing unit tests to make sure everything works as best as it can, but your team members commit large chunks of code, never write tests and ignore the build status, your build becomes untrustworthy and quite useless. In any case, it will not lead to the (increase in) software quality you were hoping for.

Having said all of the above, it's crucial that you, and your team, take your automated build environment very seriously. Keep build times short, so that you get near-instant feedback when a build fails. When someone checks in code that makes the build fail, it should become a top priority to fix the build. Maybe it's that missing semi-colon, maybe a test fails, or maybe more tests have to be added. The bottom line is, when the build fails, it becomes impossible to get an executable with the latest features that's guaranteed to pass your tests and other quality criteria.

When your build passes, it guarantees that the software passes your tests and other quality gates for good software, which should indicate that it's unlikely that the software will break or, worse, produce erroneous results in that part of the system. However, if your tests are of low quality, the software may still break even though your tests pass. Parts of the system that are not tested may still break. Even tested parts can still produce bugs. As such, Continuous Integration is not some magical practice that will guarantee that your code is awesome and free of bugs. However, not practicing it will almost certainly guarantee something somewhere sometime will go wrong.

Continuous Delivery

The next step towards successful software deployment is Continuous Delivery (which doesn't have an abbreviation, as it would be the same as that of Continuous Deployment and the difference between the two is already confusing enough). With Continuous Delivery, the artifacts that are produced by your CI server are deployed to the production server with a single button click. Continuous Integration is a prerequisite for successful Continuous Delivery.

Let's first take a quick look at what you are probably doing now or have done in the past. You implement the feature, compile, run tests, and when it all works, decide to release the new version of the software to your customer. You need to copy/paste some files to their environment manually. You need to check whether the specific configuration is correct (so your customer will not be targeting your local database). By the way, did you make a backup of the current version of their software in case your fix breaks something else? When a database update is involved, you probably need to stop some services that read and/or write to the database. Oops, you forgot to turn on the maintenance page for your customers, website. Now, they'll see this wonderful This site can't be reached ERR_CONNECTION_REFUSED page. Ah well, update the database, copy those files, and getting it back up as soon as possible. And now, you have to test if everything works as expected. Also, don't forget to restart that service you had to stop in order to update the database. Those are quite a lot of steps for a single deployment and each of those steps can go wrong. And even if you do it right, will your coworkers know what to do as well? Will you still know next month when you need to do another release? So, you've just finished this release and now the customer calls again, looks good, but can you make that button green? Yes, you can make that button green. That's like three seconds of work and then another thirty minutes sweating and swearing while you release it to production. And who will do all of this when you're on vacation?

But we have documented our entire delivery process, I hear you say. Be that as it may, people could still skip a step or execute it incorrectly. Documentation needs to be written and updated, which is, again, a time-consuming and error prone task. Sure, it helps, but is by no means fail-safe.

The benefits of having an automated deployment soon become visible. Less obvious, but most useful, is that automated deployment makes it so much easier to deploy that you can (and will) deploy more frequently as well. When a release takes an hour of your time and has considerable risks of failure, not to mention frustration, every time you do it, you tend to postpone a release as long as possible. That also means that the releases you make probably have many changes, which increases the risk that anything breaks the software and which makes it harder to find the bug. Making the release process easier, by automating it, is important, since you will now deploy smaller changes more often. That means that it is easier to roll back any deployments in case of failure, but it will also reduce the risk that any failures occur in the first place. After all, the changes relative to the old version of the software remain small.

You should be able to deploy your software to a production (like) environment at any time. To achieve this, your software must always be in a deliverable state, meaning your build succeeds, the code compiles, and your tests succeed. The advantages should be obvious; your customer calls and asks for a new feature, or maybe he has found a bug in the software and wants you to fix it. You can now simply implement the feature or fix the bug and have it on production just minutes later. Your CI server builds the software and you know it is probably alright because it compiles and your tests succeeded.

Unfortunately, Continuous Delivery is not always (completely) possible. For example, when your customer has a database administrator (the dreaded DBA) that prevents you direct access to the database, you could still automate the delivery of the software, but not the database. In one case, I even had a customer where only the system administrator had internet access. All other computers in the company (or at least, at that specific site) were not connected to the internet. As a result, each software update was done manually and on site (a one-hour drive single trip, no matter how small the update). Even then, the more you can automate, the better, so get that CI server up and running, get that tested artifact, drive to the customer, and deploy that artifact (using a local script if possible). If you do it right, which we didn't at the time, you could email it to the system administrator and tell him just run that script, saves you a two hour drive!

Not everyone is keen on having their deployments automated, especially not customers. When, at one time, my manager mentioned that we were looking at automating deployments as it would be faster, easier, and less likely to go wrong, the customer actually responded that they did not want that as we, and they, could not check on, or control, automated deployments. That's a pretty absurd statement as if anything is controllable, it's a script, and if anything isn't, it's a person who can ignore protocol or make honest mistakes. Still, people aren't known to be rational about stuff they don't understand. So, if you are looking to implement any of the above expect some initial resistance. On the flip side, customers are never around when you deploy anyway, so they will not even notice when you automate it (you did not get that from me).

Continuous Deployment

The final stage of automating your software development process is Continuous Deployment. When practicing Continuous Deployment, every check into your source control is deployed to a production (like) environment on a successful build. The rationale behind this is that you are going to deploy the software to production sooner or later anyway. The sooner you do this, the better the chance you'll be able to fix bugs faster. It's easier to remember what you did yesterday that might have caused the bug than it is to remember what you did two months ago that might have caused the bug. Imagine checking some code into source control and get error messages from your production environment five minutes later. You'll be able to find and fix the bug immediately and, five minutes later, the production software is up and running without bugs again. Unfortunately, most managers and software owners I know get pretty nervous at the thought of automated deployment, let alone automated deployment on every check in.

Again, as with Continuous Delivery, Continuous Deployment is not always possible. All the issues with Continuous Delivery still apply, except now when a DBA doesn't give you access to the database, Continuous Deployment is pretty much out of the question. After all, you can't automatically deploy software multiple times a day while your database is only updated when some DBA has time. Currently, I'm working on a website for a customer who in turn has a customer who needs three days' notice before any changes to the website can be made. It's a contractual obligation and whether it makes sense or not, it is what it is. So in that particular case, Continuous Deployment is obviously a no-go. Still, we use this technique on our own test environment and automate as much as possible while still giving three days, notice.

The difference between Continuous Integration, Continuous Delivery, and Continuous Deployment may still be a bit vague. Consider the following image (I apologize for my poor MS Paint skills) which indicates where the three types start and stop:

Does all of this mean we have no more manual tasks? Not at all. For example, the only way that you're going to know if what you build is actually what the customer wanted is by having the customer see it and, ideally, use it. So the customer should validate any changes manually. Even if it's just a bug fix, your customer probably wants to see that it's fixed with his own eyes before you can release to production. Likewise, exploratory testing is a typical manual task. Other tasks, such as making changes to your firewall, (web) server, or database may (or even must) be done manually, although preferably not.

Summary

Continuous Deployment helps in getting software out to your customer as soon as it is written. Continuous Delivery is a good alternative if you need more control over your deployments. To minimize the risk of deploying bugs, your software should be thoroughly tested using Continuous Integration. Continuous Integration is all about making sure your software is tested and deployable. In the next chapter, we are going to set up an environment with some tools that are necessary for Continuous Integration.

Setting Up a CI Environment

In the remainder of this book, we're going to implement Continuous Integration, Delivery, and Deployment. However, before we start, we must choose some software to work with. As I have mentioned, we have multiple choices for our source control and for our CI server and, of course, we can use a ton of programming languages and databases. Additionally, we need to create some project to work with. This chapter will lay out the technologies that are used in the remainder of the book, as well as a high-level overview of how they all work together. For the test project, we'll create a simple to-do list web app. We'll implement it in Node.js with a MongoDB database and in C# Core with a PostgreSQL database. That way, we'll see CI in action in both frontend and backend development, as well as the popular JavaScript language, the compiled C# .NET Core language, SQL, and NoSQL.

We'll start by building a frontend using JavaScript and the npm package manager, creating unit tests and UI tests in Selenium and Jasmine, and automating these using Karma and Gulp. After that, we'll hook it up to a JavaScript-driven Node.js and MongoDB backend.

With the same frontend, we can build a C# .NET Core and PostgreSQL database backend. We'll use NuGet and Microsoft's unit testing framework as well as MSBuild and MSTest.

Chapter 1,