Continuous Integration, Delivery, and Deployment

CI

Disclaimer

Example

  • Highly theoretical presentation
  • Some people have limited experience with CI/CD
  • Need a real world example
  • Developer issues PR to dev branch
  • Peers review code, CI visible in GIT integrations
  • PR is merged, webhook hits CI
  • CI checks out code, initializes environment, fixtures
  • CI runs unit tests, installs and runs ngrok, notifies GI
  • GI runs tests against ngrok tunnel with fixture data
  • CI waits for GI to complete. Stops on failure
  • CI SSHs into remote machine, runs:
    • Git pull
    • Dependency install
    • Database migrate
    • Server restart
  • CI notifies Slack, server is live
  • Total downtime: 0.2s for minor versions, 2s for major.

Existing Project CD with CircleCI and Ghost Inspector

  • Developer issues PR to dev branch
  • Peers review code, CI visible in GIT integrations
  • PR is merged, webhook hits CI

Existing Project CD with CircleCI and Ghost Inspector

  • CI checks out code, initializes environment, fixtures
  • CI runs unit tests, installs and runs ngrok, notifies GI

Existing Project CD with CircleCI and Ghost Inspector

  • GI runs tests against ngrok tunnel with fixture data
  • CI waits for GI to complete. Stops on failure

Existing Project CD with CircleCI and Ghost Inspector

  • CI SSHs into remote machine, runs:
    • Git pull
    • Dependency install
    • Database migrate
    • Server restart
  • CI notifies Slack, server is live
  • Total downtime: 0.2s for minor versions, 2s for major.

Existing Project CD with CircleCI and Ghost Inspector

Continuous Integration
Continuous Delivery
Continuous Deployment

Continuous Integration

  • A strategy for how a developer can integrate code into the mainline continuously
    • The difference between continuously and frequently is project dependent
  • Delivery frequency depends on work unit size
  • Continuous delivery prefers  small   tasks
  • Management of integration is obviously VC agnostic
  • Often simply a strategy of code management
    • Commonly referred to at KG as git flow

Continous Delivery

  • An extension of continuous integration
    • CD requires CI
  • More of a concept than a practice
  • Often linked closely with Agile principles
  • Concerned with early and frequent delivery
  • Focused on delivering value, not code
  • Delivery must embrace your "definition of done" 
  • Similar or synonymous to Continuous Deployment

We will refer to the whole CI/CD/CD ecosystem as Continous Delivery

Continuous Deployment

  • As developers, we may think of this as delivery
  • Delivery is a concept, deployment is an action
  • Involves the process of deploying already integrated code to deliver improved, removed, or modified value
  • Usually involves transferring updated source/dist to a remote
  • Can be as simple as FTP, or as complex as multi-node delivery using Docker, etc.
  • I normally just use a bash script or something more native (Fabric, etc.)

"You never mentioned tests!"

  • Testing is concerned with preventing
    • Integration of broken code
    • Delivery of broken functionality
    • Deployment of broken systems
  • Tests can be used in every step of the continuous delivery lifecycle
  • The CI/CD lifecycle is somewhat agnostic to verification steps

Integration

Build Server

VC

Service Node

Developer

Updates

Notifies

Builds For

Notifies

Service Node

  • Good CI is service agnostic
  • Service node could be anything. Commonly:
    • Build updates (ie. Slack notifications)
    • Trigger a deployment process
    • Branch changes, revert stable branch, notify developers

Delivery/Deployment

Deploy Server

Deploy Node

Notifies

Executes

Targets

Notifies

Build Server

Deploy Script

Deploy Node

  • Good CD is deploy target agnostic
  • Deploy node could be anything. Commonly:
    • AWS EC2 CodeDeploy to remote
    • .NET WebDeploy/FTP to remote
    • Heroku deploy
    • Docker Trusted Registry update
    • SSH deploy to remote
    • Various server commands (restart, migrate, etc.)
    • Artifact storage 

Delivery/Deployment

CI

CD

Note: Build/Deploy server are often the same

Verification

CI

CD

Code Review

Unit/Integration Tests

X

  • Verification steps intercept during certain points
  • Stop the flow of defective code
  • Code reviews catch badly written code

Local Unit Tests

Utilizing VC in CD

  • KG developers should be familiar with this common GIT Flow model
  • Following a similar model is ideal for CI

See: http://nvie.com/posts/a-successful-git-branching-model/

Utilizing VC in CD

  • Version control can do more than trigger a build
  • Use VC to target deployments
    • Protected branches can trigger a build/deploy to a server
    • For example:
Branch Deploy Target
develop Dev server
stage Staging server
master or release/* Production server          

Utilizing VC in CI/CD

  • Proper git flow helps manage automated CD
  • Release branches can be targeted for production
  • Feature branches stop deployments while features are incomplete
  • Code reviews can ensure quality of code
  • Note: builds should occur on every remote update
    • Deploys can be either manually or triggered by certain branches

Utilizing VC in CI/CD

  • Use of automated production deploys is highly contested
    • I've been doing it for years
  • Use of automated develop and staging deploys should not be
    • Saves time
    • Decreases frequency of human error
    • Speeds up delivery process
    • Ensures that VC contains all information necessary to replicate project state

Choosing a CI provider

  • Price often calculated per project, build, or concurrent container
  • Need to consider (per project):
    • Price
    • Environment/OS support
    • Concurrency support
    • Configuration style
    • Built-in deployment options
  • Opinion: Prefer providers that offer configuration via some sort of script (commonly YAML)

Configuring CD

  • Set up SSH keys for GIT/remote access
    • Usually done within CD provider settings
    • Always avoid using passwords for production environments

Configuring CD

  • Teach build server how to build and run the code
    • Install dependencies
    • Load fixtures, migrate database
      • Fixtures are incredibly useful and should be used to isolate integration tests
    • A good configuration allows the build server to expose a working application​

Configuring CD

  • Teach build server how to run tests and verify
    • Unit tests are great, but we have a working application
    • Integration tests are better here
      • ie. Protractor, Ghost Inspector, etc.
    • Can use something like ngrok to expose the application to a third party

Configuring CD

  • Teach build server how to deploy. This often includes:
    • A bash script or something similar
    • An automated deploy task for a service like Heroku or AWS EC2
    • A health check or simple request to ensure the application updated properly

Configuring CD

  • CD can be configured in a web GUI in almost all cases
  • It is ideal to configure CD in a file whenever possible
    • If you check out an older version, you can also check out the old build process
    • Two people can work at the same time on branches that have different build requirements
    • DR can be automated more easily

CD Integration Tests

  • Example time! 
  • In-build integration tests

Example Configuration

machine:
  python:
    version: 2.7.10
  node:
    version: 6.2.0
dependencies:
  pre:
    - npm install -g gulp
    - cd app/client; npm install
test:
    post:
        # Load fixtures
        - app/entry.js loaddata testdata.json

        # Run tests
        - npm test
deployment:
  staging:
    branch: dev
    commands:
      - ssh web@dev.website.com "cd app; git checkout dev; git pull origin dev;"
      - ssh web@dev.website.com "cd app; ./install.sh; sudo systemctl restart server;"
  production:
    branch: master
    commands:
      - ssh web@website.com "cd app; git checkout master; git pull origin master;"
      - ssh web@website.com "cd app; ./install.sh; sudo systemctl restart server;"

Example Integration Tests

...
test:
    post:
        # Load fixtures
        - app/entry.js loaddata testdata.json

        # Run tests
        - npm test

        # Start our application
        - app/entry.js runserver 8000 --insecure

        # Download ngrok and open tunnel to our application
        - wget https://bin.equinox.io/a/6xUGYveZLH7/ngrok-2.0.9-linux-amd64.zip
        - unzip ngrok-2.0.9-linux-amd64.zip
        - ./ngrok authtoken $NGROK_TOKEN
        - ./ngrok http 8000

        # Download json parser for determining ngrok tunnel
        - wget http://stedolan.github.io/jq/download/linux64/jq
        - chmod +x jq

        # Execute Ghost Inspector tests using the ngrok tunnel
        - curl "https://api.ghostinspector.com/v1/suites/$GHOST_SUITE_ID/execute/?apiKey=$GHOST_API_KEY&startUrl=$(curl 'http://localhost:4040/api/tunnels' | jq -r '.tunnels[1].public_url')" > $CIRCLE_ARTIFACTS/ghostinspector.json
        # Exit with a fail status if any tests have failed
        - if [ $(grep -c '"passing":false' $CIRCLE_ARTIFACTS/ghostinspector.json) -ne 0 ]; then exit 1; fi

... etc

Simplifying CD

  • The biggest barrier to entry to decent CD is a complicated local setup and build process
  • There are often a few commands people need to run
    • npm install
    • npm install again
    • gulp build
    • database migrations
    • etc.
  • Simplify this early with a single application entry point
    • Again, something as simple as install.sh

Keeping CD Throughput High

  • Keeping CD Throughput high can be difficult
  • Dependency install and integration tests can take forever
  • Run unit tests as a pre-push hook to decrease failure rates
  • Run nightly builds on every branch to identify issues early
  • Bamboo and other providers allow you to separate build/deploy segments

Ship it!

CI

By Jamie Counsell

CI

  • 1,010