May 1, 2023
8
min read

Creating Ephemeral Environments for your MedusaJS eCommerce Application

Guide on creating shareable ephemeral environments for your MedusaJS application

Introduction

Brief Overview of MedusaJS

In the world of enterprise eCommerce dominated by Shopify and other similar website building platforms, the developer experience for creating applications is localized to either a few enterprise ready solutions or building your own solution from scratch. MedusaJS was created to empower developers to take eCommerce application development in their own hands instead of being dependent on the dominant eCommerce application platforms in the market. It has bridged this gap by providing extensible eCommerce logic for creating and managing abstractions such as carts, products, order management, the ability to orchestrate these abstractions etc. and allowing developers to manage their own platform at no cost. Teams can start creating their own eCommerce application using these building blocks or even integrate them into their existing applications as they see fit.

Hurdles while developing an enterprise eCommerce application

When developing large scale eCommerce applications, teams building multiple services for it can have issues with testing, previewing, showcasing etc. The following are some hurdles which are faced during development, for example:

  • Testing transaction workflows and rollbacks : Transaction workflows and rollbacks can be hard to test; to confirm if their behavior is idempotent and the workflows work seamlessly.
  • Validating plugin integrations : As an application is continued to be developed and extended with plugins, reviewing the plugin behavior and testing it becomes imperative before releasing to production. Without testing end to end in an environment similar to the production environment is important.
  • Experimenting with different product categorization strategies : When developers are experimenting with different ways to improve the user experience, it becomes important to be able to preview and test liberally against the application in question.

In all these cases, the developer can benefit from isolated environments, ideally triggered from the changes created to the eCommerce application. These changes would be reflected in the pull requests created by them. We can use Uffizzi to create these ephemeral environments on every pull request.

Leveraging ephemeral environments to enhance developer productivity and collaboration across stakeholders

Ephemeral environments are isolated, temporary, and easily configurable. They can be shared among developers, QA teams, and stakeholders via a predictable url, which is publicly accessible. They help debug and test faster on every iteration, ensuring a smoother development process and enhanced collaboration across teams.

Creating ephemeral environments on each pull request

We are going to create a Github Actions workflow which will be triggered on every pull request made to your Medusajs application repo. Here we are using https://github.com/UffizziCloud/medusajs-previews as an example to demonstrate what that looks like. Upon successful execution the workflow will have created an ephemeral environment which can be accessed from the pull request itself. Let’s take a look at the application. It’s service architecture, and how Uffizzi is configured to create ephemeral environments for the same.

Understanding the MedusaJS service architecture and configuration

Application service architecture

The MedusaJS is only our backend which will expose an API to the frontend from where the store can be accessed. The backend is also connected to a database and a cache which will run as services of their own. The following is what the service architecture for the entire ecommerce application will look like :

Figure 1: Example e-commerce application architecture

The user will only have access to a single service from the ephemeral environment URL. Here we will be configuring it to expose only the frontend service.

Mapping the above service architecture to the sample application

The following is the directory structure of this sample application with only the relevant files and directories for this guide:

/.github /workflows # all the github actions workflows are located here uffizzi-build.yml # builds all the necessary images for the ephemeral env uffizzi-preview.yml # takes the built images and runs the preview … /frontend # source code for the frontend Dockerfile # dockerfile used to build the frontend image … /src # source code for the backend Dockerfile # dockerfile used to build the backend image docker-compose.yml # docker compose for local development docker-compose.uffizzi.yml # uffizzi configuration medusa-config.js # medusajs configuration …

Project directory structure

The frontend and the medusa backend services will be built into container images which are then used to create containers. The builds for both these images need to be mentioned in the uffizzi-build.yml configuration file which can be seen in the build-medusa and build-storefront jobs. The image tags built and pushed from here are then referenced in the Uffizzi Compose using the ${MEDUSA_IMAGE} and the ${STOREFRONT_IMAGE} placeholders. To understand more on how this can be done, check out this blog which will guide you through extending Github Actions with Uffizzi. We will not be going through how to setup the uffizzi-build.yml and uffizzi-preview.yml in this blogpost.

MedusaJS configuration

The medusa.config.js projectConfig object below gives a better idea of how the medusa backend connects to other services :

module.exports = { projectConfig: { redis_url: REDIS_URL, database_url: DATABASE_URL, database_type: "postgres" }, plugins, };

MedusaJS configuration

In the above configuration the values for REDIS_URL and DATABASE_URL are pointing to the sockets exposed by the redis and postgres services. Check out https://docs.medusajs.com/ for any other configuration you would like to add.

Uffizzi configuration

version: "3"

x-uffizzi:

ingress:

  service: frontend

  port: 8000

services:

backend:

  image: ${MEDUSA_IMAGE}

  environment:

    DATABASE_URL: postgres://postgres:postgres@0.0.0.0:5432/medusa-docker

    REDIS_URL: redis://0.0.0.0

    NODE_ENV: development

    JWT_SECRET: something

    COOKIE_SECRET: something

    PORT: 9000

  ports:

    - "9000:9000"

  deploy:

    resources:

      limits:

        memory: 2000M

frontend:

  image: ${STOREFRONT_IMAGE}

  container_name: frontend

  ports:

    - "8000:8000"

  deploy:

    resources:

      limits:

        memory: 2000M

postgres:

  image: postgres:10.4

  ports:

    - "5432:5432"

  environment:

    POSTGRES_USER: postgres

    POSTGRES_PASSWORD: postgres

    POSTGRES_DB: medusa-docker

redis:

  image: redis

  expose:

    - "6379:6379"

Uffizzi Configuration for MedusaJS

The Uffizzi configuration is derived from the docker-compose.yml. This allows anyone to get started with Uffizzi given that they know how to configure docker-compose files. Now let’s look at some of the changes we have made on top of the docker-compose.yml so that it can be used with Ufffizzi

  • the rest of the services directly or indirectly, and it is a user interface used to interact with the application, this is definitely a good choice.
  • When an ephemeral environment is created, Uffizzi creates a single ingress per ephemeral environment. If one would like to access multiple services from the ingress they would have to configure a loadbalancer and point the ingress to the loadbalancer service. Read this blog post to understand how you can do that.
  • The image parameters are updated to use ${MEDUSA_IMAGE} and the ${STOREFRONT_IMAGE} placeholders instead of local build contexts so that we can replace these placeholders with the image tags from the github action builds.
  • The DATABASE_URL and REDIS_URL environment variables are set to consume postgres and redis from the same network (i.e. 0.0.0.0) as all of these services are running as containers in a Kubernetes Pod sharing the same network. So if there are multiple services which listen on the same port, the ports will have to be changed in a way that each service will listen on a unique port.

Once the configurations are finalised, the ephemeral environments can be tested by creating a pull request against the repo.

Triggering, building and running ephemeral environments for the sample ecommerce application

After the above changes have been committed to the github repo which houses the medusajs application, and GitHub workflows, the repo is now ready to be tested.

Open a pull request to the GitHub repository

Opening a pull request to your repo containing the Medusa backend and frontend, the two stage workflow would kick off the ephemeral environment creation process after which the environment link would be advertised in a comment posted on the PR like the one below.

The x-uffizzi section defines configuration specific to Uffizzi. The ingress has to be defined here which dictates which service will all the requests be routed to. In this specific configuration, all requests will be routed to the frontend service. As the frontend service is  connected to

Figure 2: A Uffizzi GitHub Actions workflow posts a comment to the pull request issue with a link to the Uffizzi ephemeral environment.

Review the changes using the ephemeral environment

Following the link will take you to your Medusajs ecommerce store built from the changes in the pull request. You can explore the store and see how the ephemeral environment works.

Figure 3: A preview of changes can be tested in this ephemeral environment.

Next Steps : getting creative with using ephemeral environments

Once you know how to set up the github actions workflow to trigger ephemeral environments for your Medusajs application, you can now start evolving them as per your needs. The following are a few ways you can start getting creative with your Ephemeral Environments.

  • Running integration tests against Ephemeral Environments : Once the ephemeral environments are up, and if the project uses playwright or selenium for end to end or integration testing, the final UFFIZZI_URL can be passed to the test suite to run tests against a running ephemeral environment instance. This would allow the project to have integration tests to run on every PR.
  • Interacting with your Ephemeral Environment using Webterminal : If the application has a CLI environment which would be useful to have access to, the user can build their application with a webterminal installed and then access every ephemeral environment instance using a webterminal.

If you have a project for which you would like to build ephemeral environments for and discuss the different ways you can use them to better fit your needs, we look forward to speaking with you. You can get in touch with us by going to https://www.uffizzi.com/contact and we will reach out to you !

Open Source projects using Uffizzi in the wild

Uffizzi has been used in multiple open source projects across github with Github Actions. These projects are all listed here.

Uffizzi logo
Environments as a Service
Learn More
preview icon
Empower your devs with an environment for every pull request
time icon
Avoid release delays that cost millions in missed revenue
Velocity icon
Improve development velocity at scale by up to 50%
Lifecycle icon
Plan capacity in real time with lifecycle management built in
Learn More