Serverless & Stage Agnostic Deployments

Chris Sullivan
Jan 5 · 2 min read

I recently spun up a new Serverless project following this excellent tutorial written by Yatin badal. However I quickly found an issue when it came time to deploy my newly created Serverless project. The problem was that I did not want to deploy theplayground lambda associated with local offline testing. It wasn’t only the AWS cost, but also that I didn’t want end-users to be able to interact with my GraphQL directly.

Searching the Serverless Github Repo, I was unable to find a plugin that would exclude specific assets during the deployment process, nor could I find any configurable approach through their documentation.

So I did what any bright-eyed engineer would do, I wrote a plugin. The serverless-plugin-staging allows developers to exclude certain functions and resources in a stage specific way.

Installation

npm i -D serverless-plugin-staging

or

yarn add -D serverless-plugin-staging

Usage

To use the plugin we will need to add it to our serverless.yml plugins list.

plugins:                         
- serverless-plugin-staging

Configuration

Now that serverless can see our plugin, we can start excluding certain functions or resources on a per-stage basis.

To exclude the playground function during prod deployment, we will add it to our custom staging variable within the excludeFunctions definition.

custom:                          
staging:
excludeFunctions:
prod:
- playground
functions:
playground:
handler: src/graphQL/playground.default
events:
- http:
path: playground
method: get
plugins:
- serverless-plugin-staging

Resources can also be excluded, and are referenced by their top-level names similar to how function names are excluded. A real-world case for this would be restricting dev-specific environments from creating resources such as S3 buckets.

Let’s assume that is the case and we have three devs: devA, devB, and devC. Additionally we have a custom bucket name that is generated using the stage.

custom: 
uploadBucket: ${self:service}-${self:provider.stage}-uploads
staging:
excludeResources:
devA:
- UploadBucket
devB:
- UploadBucket
devC:
- UploadBucket
resources:
Resources:
UploadBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.uploadBucket}

Now when deploying on devA, devB, or devC the uploads bucket will not be created and deployed.

Simplifying (optional)

We can now exclude stage agnostic assets during the deployment process, but our custom variables are going to start looking very verbose if we continue down this route. To clean up the serverless.yml file, exclusions can be moved to their own yaml file and referenced inline.

# exclusions.ymlexcludeFunctions:
dev:
- playground
excludeResources:
devA:
- UploadBucket
devB:
- UploadBucket
devC:
- UploadBucket

Reference Example:

custom:
staging: ${file(exclusions.yml)}

This helps clean up our serverless.yml file and also helps isolate pull request conflicts on a per-file basis.

Future

The plugin is currently at v0.0.4, but here is a roadmap for the future of the plugin.

  1. Add regular expression support
  2. Add an only option, to reduce duplicate code

Give it a try and feel free to submit new ideas or improvements.

Chris Sullivan

Written by

Software Engineer @SocialNewsDesk

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