LocalStack LogoLocalStack Icon

Preview Environments for AWS apps on every Pull Request with LocalStack

Integrating LocalStack's Ephemeral Environments with your GitHub Actions CI workflows allows you to automatically generate a fully functioning preview of your AWS applications, eliminating the need for costly-staging environments.

Preview Environments for AWS apps on every Pull Request with LocalStack

Introduction

LocalStack’s core cloud emulator allows you to set up your cloud infrastructure on your local machine. You can access databases, queues, and other managed services without needing to connect to a remote cloud provider. This speeds up your Software Development Life Cycle (SDLC) by making development and testing more efficient.

Despite this, you still need a staging environment to do final acceptance tests before deploying your application to production. In many cases, staging environments are costly and deploying changes to them takes a lot of time. Also, teams can only use one staging environment at a time, which makes it difficult to test changes quickly.

With LocalStack’s Ephemeral Instances, you can create short-lived, self-contained deployments of LocalStack in the cloud. These Ephemeral Instances also let you deploy your application on a remote LocalStack container on every pull/merge request, creating an Application Preview. This allows you to run end-to-end tests, preview features, and collaborate within your team or across teams asynchronously.

In this tutorial, we’ll set up a full-stack AWS serverless application and serve it in a short-lived preview environment for each pull request using LocalStack and GitHub Actions.

About the application

This tutorial uses a public LocalStack sample to showcase a serverless quiz application. The example application is a traditional three-tier architecture that uses the following AWS resources:

  • S3: Hosts static frontend assets in a bucket for CloudFront distribution.
  • CloudFront: Delivers frontend assets from S3 globally for fast user access.
  • Lambda: Executes serverless functions for creating, submitting, scoring, and fetching quizzes.
  • API Gateway: Exposes REST endpoints for quiz operations, linking HTTP methods to Lambda functions.
  • DynamoDB: Stores the quiz, associated metadata and user data for persistence.

Infrastructure architecture

There are several other AWS resources that are part of the application, but these are the main ones we’ll focus on. The application is deployed using the AWS CLI and a helper script (bin/deploy.sh) to set it up from scratch locally with the awslocal wrapper and LocalStack.

We can now write a GitHub Action workflow to deploy the sample application on an Ephemeral Instance and create a preview environment.

Prerequisites

Create the GitHub Action workflow

GitHub Actions serves as a continuous integration and continuous delivery (CI/CD) platform, automating software development workflows directly from GitHub. It allows customization of actions and automation throughout the software development lifecycle.

We can implement a workflow that:

  • Checks out the repository from GitHub.
  • Installs necessary dependencies.
  • Deploys the application on a ephemeral LocalStack Instance using a GitHub Action Runner to generate a sharable application preview.

To begin, let’s fork the LocalStack sample repository on GitHub. If you’re using GitHub’s gh CLI, fork and clone the repository with this command:

Terminal window
gh repo fork https://github.com/localstack-samples/serverless-quiz-app

Alternatively, you can fork the repository manually by clicking the “Fork” button on the repository page and then cloning it to your local machine using the git clone command.

After forking and cloning, navigate to the .github/workflows directory in your forked repository. Open the preview.yml file, which contains the GitHub Action workflow configuration, required to setup the preview environment.

The file is included in this repo for convenience. If starting from scratch, you can optionally delete and recreate it or simply open it to review its contents.

Set Up the Actions & dependencies

To achieve our goal, we can utilize a few prebuilt Actions:

We can now add the following content to the preview.yml file:

name: 'Create Preview on Pull Request'
on:
workflow_dispatch:
pull_request:
types: [opened, synchronize, reopened]

This configuration triggers the workflow on every pull request event and allows manual execution via the GitHub Actions UI.

Create a new job named localstack to define the GitHub-hosted runner for executing workflow steps and checking out the code for deployment to the preview environment:

jobs:
localstack:
permissions: write-all
name: Setup LocalStack Preview
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

To ensure our dependencies are installed, we can add the following step to the job:

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

Setup the preview environment workflow

To deploy the preview environment, use the LocalStack/setup-localstack action with the following parameters:

  • github-token: Automatically set on the GitHub Action runner.
  • state-backend: Set to ephemeral to create an Ephemeral Instance.
  • state-action: Set to start to start the Ephemeral Instance.
  • include-preview: Set to true to include the Ephemeral Instance URL in the PR comment.
  • install-awslocal: Set to true to install the awslocal AWS CLI wrapper.
  • preview-cmd: Commands required to deploy the application and its infrastructure on LocalStack.

The job step should look like this:

- name: LocalStack Preview
uses: LocalStack/setup-localstack@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
state-backend: ephemeral
state-action: start
include-preview: 'true'
install-awslocal: 'true'
preview-cmd: |
./bin/deploy.sh
distributionId=$(awslocal cloudfront list-distributions | jq -r '.DistributionList.Items[0].Id');
echo LS_PREVIEW_URL=$AWS_ENDPOINT_URL/cloudfront/$distributionId/ >> $GITHUB_ENV;
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}

In the preview-cmd section, the deploy.sh script is executed to deploy the application on LocalStack. The CloudFront distribution ID is retrieved and appended to the LS_PREVIEW_URL environment variable, which is then used to display the preview URL in the pull request comment. This provides quick access to the deployed URL for validating features or updates.

Configure a CI Auth Token

Before triggering the workflow, set up a Continuous Integration (CI) Auth Token for LocalStack. This token is required to activate licensed features like Ephemeral Instances in CI environments. As you can see in the env section of the LocalStack Preview step, we’re using the LOCALSTACK_AUTH_TOKEN secret to authenticate with LocalStack.

To add the CI Auth Token to your GitHub repository:

  1. Go to the LocalStack Web Application and open the Auth Token page.

  2. Under the “CI Auth Tokens” section, provide a name and click “Generate new CI Auth Token” to create a token.

    CI Auth Token page

  3. Add the token to your GitHub repository secrets with:

    • “Name”: LOCALSTACK_AUTH_TOKEN
    • “Secret”: The generated CI Auth Token.

    Add secret to GitHub repository

Now, you can commit and push your workflow to your forked GitHub repository.

If you do not have access to creating CI keys, contact your LocalStack account administrator.

Run the GitHub Action workflow

With the GitHub Action workflow set up, each pull request in your forked repository will trigger the creation of a preview environment. LocalStack will build, deploy, and package the application in an Ephemeral Instance, accessible via a preview URL in the pull request comment.

This might take a short while to complete, depending on the infrastructure’s complexity and the build/deploy process. The workflow automatically updates the preview environment when new commits are pushed to the pull request.

Here is an example of a pull request comment with the preview URL:

Preview URL in pull request comment

You can now access the preview URL to test the application and validate the changes made in the pull request. You can also integrate the preview URL with tools like Slack or Teams to notify your team or run automated E2E tests using Cypress or Playwright to validate functionality.

The Ephemeral Instance is automatically terminated after a period of 2 hours, ensuring that resources are not left running unnecessarily. If you push further commits to the pull request, the preview environment is removed and recreated with the latest changes.

Conclusion

Preview environments are ubiquitous in in the frontend space, and with LocalStack you can now now spin up your entire application, including your AWS infrastructure, as a live environment with every change. This allows you to:

  • Collaborate with GTM, RevOps, and Marketing teams to showcase new features to potential customers.
  • Eliminate staging environments by providing each engineer with an isolated environment.
  • Reduce staging costs by automatically tearing down environments to avoid unnecessary cloud expenses.

This preview-on-pull-request feature positions LocalStack a true cloud development platform — not only for developers but also for QA & management, to fully become the backbone of cloud development throughout the entire SDLC. In future blog posts, will explore more such use-cases including using Cloud Pods for fast infrastructure setup, E2E testing using popular frameworks, and setting up pre-production environments with synthesized test data for acceptance testing.


Harsh Mishra
Harsh Mishra
Engineer at LocalStack
Harsh Mishra is an Engineer at LocalStack and AWS Community Builder. Harsh has previously worked at HackerRank, Red Hat, and Quansight, and specialized in DevOps, Platform Engineering, and CI/CD pipelines.