Using The Serverless Framework To Easily Deploy To Multiple Environments

Rocky Top Solutions
Oct 2 · 3 min read

Do you currently use a serverless configuration for any of applications or are interested in migrating a current application to a serverless architecture? Have you wondered how you can easily configure your CI/CD pipeline to easily deploy to multiple environments such as development, staging, and all production environments? With the Serverless Framework you can do just that. Continue reading to find out how.


Currently, I use the Serverless Framework to deploy to multiple environments and regions on the AWS cloud. I deploy to our development, staging, and production environments. Our development and staging environments are deployed into 2 different regions and our production environment is deployed to 4 different regions for both failover and latency improvements. So I have a serverless.yml file with many properties found in the docs for serverless.yml found here.

In order to automatically deploy to multiple environments based on the git branch code is pushed to, I have setup my configuration as follows:

  • All properties that remain the same for all environments and/or regions go into the serverless.yml base file
  • For all properties that are different between each environment such as development, staging, and production, I have another config file with the following naming convention under my config/ directory (the same naming I have is not required, but just what i use):
  • config/config.dev.yml, config/config.stg.yml, config/config.prod.yml, etc

Following this guide I add all the needed custom properties to those environment specific config files, and then in the main serverless.yml file, I create the same property, but then reference the property from the environment/stage specified on the serverless deploy -s {stage}CLI command. I use a combination of both the stage CLI parameter and setting a ENV variable in a bash script before calling serverless deploy . Then i can also use ${env:ENV} to reference that value inside serverless.yml .

Here’s an example of an environment specific YAML configuration file i have for environment specific variables:

stageSuffix: -${self:provider.stackSuffix, 'dev'}
lambda:
versioning: false
prune:
automatic: ${self:lambda.versioning}
number: 5
api:
domain: api.dev.${self:custom.domain}
storage:
bucket: dev.${self:provider.region}.${self:custom.domain}
slackChannel: 'dev-slack-channel'

And inside serverless.yml, I reference those values by doing the following:

environment:
ENV: ${env:ENV, 'dev'}
STAGE: ${opt:stage, 'dev'}
REGION: ${opt:region, 'us-east-1'}
SLACK_CHANNEL: ${file(./config/config.${self:provider.stage}.yml):slackChannel}

Also, using a lot of shell environment based variables allows you to make your serverless config even more decoupled away from specific projects/microservices since you then can just create a .env file specific to each project, create a bash script to run your serverless deploycommands, and before running serverless deploy, run source .env and many values can be populated easily by just supplying your .env file


Lastly, here’s an example of the bash script we use to run our serverless deploy commands that will supply many of our values in serverless.yml with values from a .env file instead of manually finding and replacing all the values between all our different microservices:

set -evif [[ -e "./secret.env" ]]; then
source "./secret.env"
fi
if [[ -e "./.env" ]]; then
source "./.env"
fi
BRANCH="${CIRCLE_BRANCH:-$BRANCH}"if [[ $# -gt 0 ]]; then
REGION="$1"
fi
if [[ -n "$REGION" ]]; then
REGION="$REGION"
else
REGION="us-east-1"
fi
if [[ "$BRANCH" == "development" ]] || [[ "$BRANCH" =~ ^issue-* ]]; then
ENV="dev"
elif [[ "$BRANCH" == "staging" ]]; then
ENV="stg"
elif [[ "$BRANCH" == "master" ]]; then
ENV="prod"
fi
if [[ "$BRANCH" =~ ^issue-* ]]; then
export STAGE="feature"
export STACK_SUFFIX="$BRANCH"
export API_BASE_PATH_SUFFIX="-$BRANCH"
"$(dirname "$0")"/create_domain.sh -s "$STAGE" -r "$REGION"
"$NODE_MODULES_CLI_DIR"/serverless deploy -v -s "$STAGE" -r "$REGION"
else
export STACK_SUFFIX="$ENV"
"$(dirname "$0")"/create_domain.sh -s "$ENV" -r "$REGION"
"$NODE_MODULES_CLI_DIR"/serverless deploy -v -s "$ENV" -r "$REGION"
fi

and the .env file we use to supply the variable values:

export BRANCH="$(git branch | grep \* | cut -d ' ' -f2)"
export ENV="dev"
export STACK_PREFIX="{STACK_PREFIX_HERE}"
export STACK_SUFFIX="$ENV"
export APP="{APP_ID_HERE}"
export APP_NAME="{APP_NAME_HERE}"
export COMPONENT="{COMPONENT_NAME_HERE}"
export REGION="us-east-1"
export DYNAMODB_ENDPOINT="dynamodb.$REGION.amazonaws.com"
export GITHUB_USERNAME="{GITHUB_USERNAME_HERE}"
export DB_TABLE_NAME="$COMPONENT"
export DOMAIN="{DOMAIN_NAME_HERE}"
export EMAIL_SUPPORT="support@${DOMAIN}"
export NODE_PRESERVE_SYMLINKS=1
export TEST_DEPLOYMENT_SUFFIX="-test"
export SLACK_CHANNEL="slack-channel-${ENV}"
export API_VERSION="v1"
export API_BASE_PATH=""
export API_BASE_PATH_PREFIX=""
export API_BASE_PATH_SUFFIX=""
export NODE_MODULES_CLI_DIR="./node_modules/.bin"

Let me know what you think and if you also see any improvement I myself could make to this process!

Rocky Top Solutions

Updates and news from Rocky Top Solutions, LLC

Rocky Top Solutions

Written by

We help business turn their software, web, and mobile development ideas into reality!

Rocky Top Solutions

Updates and news from Rocky Top Solutions, LLC

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