AWS Serverless App: Continuous Integration and Deployment

Jul 1 · 8 min read

There are several ways to get the latest codebase uploaded into your testing and production servers. Manually copying them over is fine and all, but having something take care of running tests and deploying the code will save your team countless hours of manual labor. This will also lessen the chance for human error. In this post, we discuss some steps you can take to add continuous integration and deployment (CI/CD) to your serverless project.


Welcome to part 2 of the AWS Serverless app tutorial set. By now you should already have a serverless project you have been working with. If not, feel free to fork or clone the sample drug search project from GitHub from part 1 of the tutorial to move forward. We will be wiring up our projects with TravisCI and Codeship, to give you an idea of how both work. Feel free to follow whichever one works best for you. If your project is an open source project, TravisCI and CircleCI both provide free builds!

We will be adding the following:

  • Linter configurations with eslint
  • Testing foundation files (no tests yet)
  • TravisCI configuration file
  • Configuration steps for Codeship


To get started, create your account with whichever CI/CD service provider you prefer and hook it up to your GitHub account. The account will need access to your repositories. You can either allow access to all by default or add them individually (recommended to reduce potential charges).

If you have a serverless project in GitHub already, go ahead and add that. If you cloned the same drug search project, you will need to add it to the listing of repositories for the CI/CD service. We will be adding the rest momentarily.

You will also need an AWS service account or user account in order to perform the deployments.

Putting CI/CD to Work

There are several ways you can leverage CI/CD with your team. One being the verification of feature branches prior to a merge. When a developer pushes up their changes, you can configure your CI/CD build to verify code formatting with a linter, run unit tests, and check its ability to start. In the case of your serverless app, the last two are a definitive way to know whether the feature build will break your main branch and live resources prior to deployment.

Upon a merge into the master or main branch, the service can run through the linter and unit tests again but you can also get your service to deploy to your project to wherever it is being hosted (AWS in our case).

Setting up Codeship

Go into your project settings and in the Tests tab, update your Setup Commands to include the following:

This will install serverless globally to execute your tests and to allow for deployment. It will also install the dependencies for the project. Next, add npm test into the Test Configuration box:

Remember the service or user account we created in Part 1? If you haven’t created one yet, now will be the time. Once you create it, grab the AWS Access Key and Secret generated and add them to your environment variable section:

This is required to be able to deploy and use AWS services in your scripts

We will be setting up the linter and test foundation files next. If you don’t intend on setting up Travis, you may skip the next section.

Setting up TravisCI

First, enable Travis for the repository. Go into your dashboard and click on the plus symbol. It will provide the search bar, start searching for the project and flip the switch on the project:

Toggle the switch to enable the repository

Click on the settings button to provide any customizations you need, like your AWS Access and Secret keys for deployment and AWS services usage. Place them in your Environment Variables section like so:

TravisCI allows you to display in build log, it is not recommended

You will then add the following contents .travis.yml file in your project’s root directory:

To run serverless offline for your tests or even to perform the deployment, you will need serverless. You will need to do an npm install in order to install the dependencies needed to run the tests. The npm test will run your linter and unit tests that we will set up in the next sections.

Notice the deploy stage has a conditional on whether it is the master branch (which for PRs it will automatically set it like that) and whether or not its a PR. We do not want it attempting to deploy during a PR, just run the tests. It should only deploy merges into the master branch.

Setting up the Linter

We don’t have tests yet but we can wire up a linter real quick to execute with our npm test command. Install eslint dependencies with the following terminal command:

You will need an eslint configuration. There are tons of examples in GitHub that you can grab. This is the one I used for the drug search project:

You will also need to update your package.json scripts listing to appear like the following:

"scripts": {   "start": "sls offline --noAuth",   "test": "NODE_ENV=test PORT=9100 ./node_modules/.bin/nyc ./node_modules/.bin/mocha --opts mocha.opts",   "offline": "sls offline start",   "precommit": "eslint .",   "pretest": "eslint --ignore-path .gitignore ."},

On your local machine, run the following to start the linter:

You may or may not find yourself with a handful of linting errors, I know I did. In order for your build to succeed, you will need to fix the linting issues marked in red (a.k.a. errors) or modify the eslint config as needed to reduce the errors to zero.

Setting up Tests

As you probably already noticed, the test command also has the dependency on the NYC module used to determine test coverage and the test command uses mocha.opts, which we don’t have.

Install NYC for code coverage:

You will need to create a mocha.opts file in the root of the project directory with the following:

--timeout 5000
--reporter list
--ui bdd

Now when you run npm test, it will attempt to give you the code coverage but it will also come across a failure message. Let’s add some supporting files in the test directory.

At the root of the test directory, add the following bootstrap.test.js file:

Create a new directory called support in the test directory. Add a file called slsOfflineTestConfig.js and place the following function into it:

module.exports.getSlsOfflinePort = () => {   return process.env.PORT || '3005';};

Now when you run the npm test command, the output should look like the following:

No errors should show here, just 0 passing and 0 coverage for now

Yikes! Looks like it is time to write some tests. We will save that for the next post.

Triggering a Build

With all your latest changes and linter fixes, you now have a fair amount of changes to push up. If this isn’t on a feature branch yet, go ahead and do a git checkout -b branchName, commit your changes, and push them up to GitHub. Codeship, Travis or whatever you are using will be triggered with the changes and attempt a build.

Note: If you didn’t set up Codeship or Travis to have this repo before you attempted to push up, it may not trigger a build as expected.

If you create a pull request, your page will show the status of the build similar to the image below:

The following is how your Codeship will look like when it begins the build:

Similarly, TravisCI will appear like the image below during a branch or PR build:

Configuring Deployment Steps

Your project is reporting a successful build, yay! Let’s remove one more manual step out of the way. The TravisCI configuration already has the deployment step defined and will execute sls deploy -v. This will upload your latest files to your AWS resources. You can specify in this step what stage this is going to. By default, the stage will be dev, but it could be test, prod, etc.

For Codeship, select the Deploy tab and create the deployment pipeline:

The branch can either match exactly or given a pattern (handy if your team does release tags). Now select Scripts from the Add Deployment section. You will need to enter the following:

And you're done. If you merge your pull request, it will immediately trigger a final build and deployment. Your resources should be available automatically after you get the success email from either service provider.

All gists and the entire drug search project repository is publically available on GitHub.

What’s Next

There you have it! Your project should now be building and deploying with the expected triggers. Think of how much time this will save you or your team! I personally couldn’t choose between the CI/CD service providers in the beginning and ended up going through the steps for both Travis and Codeship to see how they worked with my project. We will be exploring testing and debugging in the next post, AWS Serverless App: Testing.

Thanks for reading!


Written by


Engineer, Entrepreneur, and Ph.D. Student. Special interest in microservice architecture design, ML, and CCN. |

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade