DEV Community

Chris
Chris

Posted on

Use Pull Request Number as Serverless Deployment Stage

The Serverless Framework allows to deploy one service to multiple stages, for example dev, qual, and prod. The stage can be set on the provider property:

# serverless.yml
service: myservice

provider:
  name: aws
  stage: dev
  region: us-east-1
Enter fullscreen mode Exit fullscreen mode

The stage is appended to the CloudFormation stack name and added to all Lambda functions and most other resources in the service. It can also be overridden during deployment with the command line flag --stage or -s:

serverless deploy --stage prod --region eu-central-1

> Deploying myservice to stage prod (eu-central-1)

> ✔ Service deployed to stack myservice-prod (130s)

> functions:
>  hello: myservice-prod-hello (14 kB)
Enter fullscreen mode Exit fullscreen mode

Now, you may have a CI/CD environment such as GitHub Workflows where you continuously deploy changes based on a commit or pull request. These changes need to be tested separately from the development or production state. One way is to deploy them in a separate stage (e.g. qual or the name of the branch/commit/pull request) and then run your test scripts.

Instead of appending --stage to each of my deployment scripts, I like to use environment variables to set the stage dynamically. At the beginning of my GitHub workflow, I set the environment variables based on the pull request that triggered the workflow run:

# .github/workflows/ci.yml
name: GitHub CI/Testing

on:
  pull_request

env:
  PR_NUMBER: ${{ github.event.number }} # e.g. 65
  BRANCH: ${{ github.head_ref }}        # e.g bugfix/issue-42
  STAGE: pr${{ github.event.number }}   # => pr65

...
Enter fullscreen mode Exit fullscreen mode

In order for the Serverless Framework to fetch the correct stage from the environment, we need to overwrite the stage with a variable resolution:

# serverless.yml

provider:
  stage: ${opt:stage, env:STAGE, "dev"} 
Enter fullscreen mode Exit fullscreen mode

This variable defines the order in which the stage is being resolved during deployment. First, the --stage flag is checked. If it is not available, the environment variable STAGE is checked. If it is not available either, the default value dev is used.

In this example, the Serverless Framework would provide the service as myservice-pr65 and the Lambda function as myservice-pr65-hello. If you need to access the stage within the serverless.yml file, for example to name other resources and exports, you can use the buil-in variable ${sls:stage} which resolves against the provider.stage variable from above.

Links

Discussion (0)