At AirSwap, we believe strongly in solid CI/CD pipelines. It underpins our ability to quickly deploy code and makes a daily production release possible. In addition to our CI/CD pipeline, we have cycled through a few CI providers over the last year. We’ll outline our CI/CD strategy, our release process, and open source some orbs for other CircleCI users to use to make their own CI/CD process easier.

Earlier this year, we used Jenkins and a long, but re-usable, Groovy script to deploy out our code. While Jenkins is complex to learn, it is very good at processing complex workflows. However, the overhead associated with maintaining the build server itself lead our DevOps team in search of other solutions. We settled on CircleCI as our SaaS CI vendor about 8 months ago.

Our CI/CD Strategy

AirSwap operates on a continual release cycle, pushing out code when it is production ready. This means that we don’t have a “cut to production” day every few quarters. Instead, we have a daily time slot where any code that needs to go to production gets merged to the master branch and shipped out to our production servers.

In order to keep with this pace of deployments, we 100% automate our deployment process. This means from the moment a developer pushes “Merge Pull Request”, every step of putting that code in a production container is handled by a fail-safe deployment script.

This might sound like a daunting task, but, with a few exceptions, all our repositories fall into one of three internal templates we use for CircleCI. This makes creating new services and placing them in our CI/CD pipeline incredibly simple for the development team.

While updating CircleCI scripts across multiple repositories is time consuming, we keep that to a minimum by using CircleCI’s orbs, essentially sub-modules, hosted by CircleCI, that any CircleCI script can use and re-use.

Lastly, we make extensive use of the Contexts option in CircleCI. Contexts allow us to set global environment variables–like the AWS access key and secret key for our deployment user, as well as the account numbers for our various deployment accounts in AWS. We don’t need to worry about cross-account mis-deployments due to typos since each job in a workflow runs in a dedicated context based on the branch name.

Our Release Process

Our release process starts with a feature branch. On this feature branch, changes are made and tests are written to ensure these changes actually do what we think they will do.

Then, a pull request is opened to merge in the feature branch to the development branch. We use a PULL_REQUEST_TEMPLATE.md file in our repositories that outline what should be included in a properly formatted pull request.

We further make use of branch protections on GitHub to stop errant PRs and ensure that someone other than the author has a chance to review the code. This also ties in with our CircleCI scripts for automated testing.

Once merged into the development branch, our CircleCI script takes that code and ships it to our development environment. This can be seen in our workflows section of our scripts.

Of course, the workflow continues to other jobs for testing and deployment as well

This process continues just the same for our release to production. The development branch is merged into the master branch, and the master branch then goes through a similar workflow but with the Production context and the master branch.

In this way, we can easily push new code within minutes into any production system, simply by merging in PRs and running through a suite of fail-safe steps. If any part of the build, test, and deployment process does not successfully pass, the entire deployment is immediately stopped and no new code is pushed out.

Open Source CircleCI Orbs

Lastly, we make extensive use of CircleCI’s orbs. And, we think your organization can benefit from our orbs as well. That’s why we open-sourced our orbs in the CircleCI Orb repository.

Let’s walk through our orbs briefly and how you can use them in your own CI scripts.

airswap/assume-role

This orb can be found here: https://circleci.com/orbs/registry/orb/airswap/assume-role

Inspired by the CircleCI aws cli orb, we added a few extra steps to assume role into another account and utilize the returned access credentials in the rest of the script. We suggest setting the values for $AWS_ACCESS_KEY, $AWS_SECRET_ACCESS_KEY, $AWS_REGION, and $ACCOUNT_ID in your Context. This means that your actual usage in your script is as simple as:

orbs:

role: airswap/assume-role@volatile jobs:

deploy:

steps:

...

- role/assume-role:

role-name: MyOtherAccountRole

And just like that, all the other steps in your deploy job will use the MyOtherAccountRole role and account, meaning that you can now cross-account deploy from your CircleCI scripts.

airswap/datadog

This orb can be found here: https://circleci.com/orbs/registry/orb/airswap/datadog

One of the coolest features of Datadog is the ability to overlay events on your charts. This makes seeing if something external that happened, like a code change and deploy, is responsible for the uptick in your CPU usage across your infrastructure. Rather than having to manually add an event to Datadog for each deploy, why not have CircleCI do it for you?

We recommend setting the $ENV and $DATADOG_API_KEY in your Context. Then you can use the orb like:

orbs:

datadog: airswap/datadog@volatile jobs:

deploy:

steps:

...

- datadog/deploy

The result is a very useful, graph-able Datadog event that you can pull into your monitoring dashboards.

All the who, what, when, where, and other details you need to troubleshoot — or congratulate!

airswap/kubectl

This orb can be found here: https://circleci.com/orbs/registry/orb/airswap/kubectl

When it comes to using kubernetes, there is nothing quite as powerful as the kube.yml file for making new services. Because of this and because we use many environments, we craft a generic kube template file for each service and then interpolate the environment variables specific to the Context in which we run our CI.

This particular orb works very well with CircleCI’s aws-ecr orb, as shown below:

orbs:

kubectl: airswap/kubectl@volatile

aws-ecr: circleci/aws-ecr@0.0.4 jobs:

build:

steps:

- aws-ecr/ecr-login:

region: "us-east-1"

- aws-ecr/build-image:

account-url: $REPO

repo: $CIRCLE_PROJECT_REPONAME

tag: $CIRCLE_SHA1

- aws-ecr/push-image:

account-url: $REPO

repo: $CIRCLE_PROJECT_REPONAME

tag: $CIRCLE_SHA1

deploy:

steps:

- run:

name: Creating kube.yml from template

command: |

sudo apt-get install gettext-base

envsubst < kube.template.yml > kube.yml

- kubectl/apply:

url: your.url.here.$ENV

state-store: s3://your-state-here-$ENV

With that simple script, your kubernetes get a rolling update and a new service definition. Plus, with a bit more scripting, you have a generic kubernetes build script for CircleCI you can pull into any new repository to start shipping kubernetes services immediately.

airswap/serverless

This orb can be found at: https://circleci.com/orbs/registry/orb/airswap/serverless

When it comes to quickly proving an API idea or a simple microservice, we are huge fans of the Serverless framework. Similar to a kubernetes template file, Serverless ships with a great serverless.yml file. This, combined with the Serverless command line tool gives us great portability for this orb.

orbs:

serverless: airswap/serverless@volatile jobs:

deploy:

steps:

- serverless/install

- serverless/deploy

These two lines give us the Serverless command line tool and a fail-safe deployment of the new Lambda functions. Bundled in the orb is a setting to automatically, by default, set up a custom domain for the project using Serverless Domain Manager. Build, deploy, and access your microservice via the web immediately. And you can even use a single CircleCI template script across multiple repositories, so your development team can deploy out their new service immediately, with no help needed from the DevOps team.