Skip to main content
Version: 1.0.0

Ephemeral Environments

Ephemeral environments in a cloud infrastructure and DevOps context are temporary, dynamic setups created on-demand to test, build, or run software applications. They are spun up quickly for a specific purpose, such as testing a new feature or a pull request, and are torn down automatically once their job is done, ensuring resources are used efficiently and costs are minimized. This approach supports continuous integration and delivery (CI/CD) practices by providing isolated, replicable, and scalable testing environments that mimic production settings without the long-term overhead.

Ephemeral Environments build on our built-in Preview Branches to provide multi-Project environments for more advanced testing.

Quick Start

The following guide assumes a simple two-project (frontend, backend) architecture, and uses Github Actions to spin up a new ephemeral environment on Pull Request open. This guide assumes you've already deployed an instance of each of the Projects you want to have included in the Ephemeral Environment.

  1. Create a new Zeet API Key from your Team's API Settings. While you're here, grab your team's User ID from the API Identifiers section below
  2. Create 2 repo secrets in Github called ZEET_API_KEY and ZEET_TEAM_ID with your API key and Team's User ID respectively. These secrets will be secured by Github and injected during the Github Action Run.
  3. For each Project you want to include, navigate to Settings > API and copy the "Repo ID".
  4. Create a new file in .github/workflows/zeet.yml in your repo with the following content:
types: [opened, closed]
name: Zeet
runs-on: ubuntu-latest
contents: read
# Required to post comments
pull-requests: write

ZEET_API_KEY: ${{ secrets.ZEET_API_KEY }}
ZEET_TEAM_ID: ${{ secrets.ZEET_TEAM_ID}}
# Checkout the current PR branch.
- name: Checkout PR branch
uses: actions/checkout@v3

# Create a new environment that encompasses the relevant Project IDs you care about. Defaults to naming the new environment after the branch being merged in.
- name: Create Environment
uses: zeet-co/kang@v0.3.1
if: github.event.action == 'opened'
args: start --name=${{ github.head_ref }} --ids=#[comma-separated list of the Repo IDs from Step 2]

# Destroy any projects stored in the created environment. Make sure the name matches the name of the environment you created!
- name: Run Destroy Action
uses: zeet-co/kang@v0.3.1
if: github.event.action == 'closed'
args: stop --name=${{ github.head_ref }}

# Posts a comment to the PR, including links to the newly created Projects.
- name: Post Zeet comment
uses: zeet-co/kang@v0.3.1
args: comment --repo=${{ github.repository }} --token=${{ github.token }} --pr=${{ github.event.pull_request.number }} --env-name=${{ github.head_ref }}

  1. Make sure you modify the contents --ids parameter to include the RepoIDs of the Projects you want to include.
  2. 🎉 That's it! Commit the file and test it out by opening a new Pull Request
  3. While there is a live Ephemeral Environment, you'll see a kang Group in your Zeet Dashboard, with each environment name occupying its own SubGroup within. Feel free to make any changes to these, or otherwise test your environment!

Customizing Overrides

By default, the above Github Actions Workflow will simply duplicate your projects into a new environment. However, many teams want to make configuration changes to these newly created Projects as well - maybe you want to scale down the resources required, or change a URL to point services at each other. To support this, the start command takes an optional --overrides flag, which can be used to override any field on the newly created project. The overrides flag takes in a comma-separated list of statements in the following format: ${projectID}:field:value Nested fields are supported through dot-notation - i.e the foo environment variable can be set with


For a full list of fields that can have overrides applied to them, see the UpdateProjectInput documentation here. Below are a few examples of common overrides

Update an environment variable to a new hardcoded value

--overrides 1c6ea878-f92e-435e-a849-7bccfe7c6e5a:env.isEphemeral:true

Update resource usage to a new hardcoded value

--overrides 1c6ea878-f92e-435e-a849-7bccfe7c6e5a:cpu:0.1,1c6ea878-f92e-435e-a849-7bccfe7c6e5a:memory:1G

Update an environment variable to a value from another Project

Sometimes we don't know the exact value we want to provide - for example, if you want to make your new frontend always point to your new backend, but you don't yet know your backend's URL. In cases like this, Zeet can also resolve overrides that come from other Projects, like so:

--overrides '1c6ea878-f92e-435e-a849-7bccfe7c6e5a:env.otherEndpoint:c8c3a2a0-2349-41a3-871f-e81cac18f305:deployment.endpoints[0]'

In this example, the 1c6ea878-f92e-435e-a849-7bccfe7c6e5a project will have its otherEndpoint environment variable set to the c8c3a2a0-2349-41a3-871f-e81cac18f305 project's first endpoint

Override a project to another cluster

You may want to run the ephemeral environment in a different cluster than your production services. For this case, we can use the overrides to change the cluster for a new project.

To accomplish this, you will need the Zeet Cluster ID for the Cluster you'd like to deploy to. You ca find this in your Zeet dashboard, under the Cluster tab. Click on the Cluster you'd like to deploy to, and copy the Zeet Cluster ID.

Once you have your Zeet Cluster ID, simply add an override for the cluster field of the relevant project in your Github Actions Workflow file. For example:

--overrides 1c6ea878-f92e-435e-a849-7bccfe7c6e5a:cluster:4461ab27-26bc-4196-aa03-bbf6d4fa9908

Pass multiple overrides on different lines

As your environments get more complex, you may find it difficult to manage all the overrides you pass in on one line. Fear not, you can pass as many instances of --overrides as you'd like, each on their own line. Note that --overrides and --override are interchangeable!

start \
--name multiline-test \
--ids 23b77cb3-e56c-437e-9f69-1c91b7ba31d2,a9c58544-410c-436a-9ca2-774b8ad73f6a \
--overrides '23b77cb3-e56c-437e-9f69-1c91b7ba31d2:cpu:0.1' \
--override '23b77cb3-e56c-437e-9f69-1c91b7ba31d2:memory:1G'

Note that the above example is helpful if using the Kang CLI directly. If you'd like to use multi-line commands in Github Actions, you'll want to use a folded multi-line string, as follows:

uses: zeet-co/kang@v0.3.1
args: >
--name multiline-test
--ids 23b77cb3-e56c-437e-9f69-1c91b7ba31d2,a9c58544-410c-436a-9ca2-774b8ad73f6a
--overrides '23b77cb3-e56c-437e-9f69-1c91b7ba31d2:cpu:0.1'
--override '23b77cb3-e56c-437e-9f69-1c91b7ba31d2:memory:1G'

Include Database Credentials in overrides

If you include Database Projects in your ephemeral environments, you likely want to pass the credentials from your newly provisioned database to your application. In this case, you'll want to use databaseEnvs. The special databaseEnvs property maps to the Database Connection Info panel on your Database Project's Overview tab (see image below for example).

Note all of the variables displayed here are accessible under databaseEnvs, but we'll focus on DATABASE_URL. In this example, we're duplicating a Database as well as an application, and setting the env var DATABASE_URL on the application to the fully qualified connection string from the Database.

start \
--name db-test \
--ids 23b77cb3-e56c-437e-9f69-1c91b7ba31d2,a9c58544-410c-436a-9ca2-774b8ad73f6a \
--overrides 'a9c58544-410c-436a-9ca2-774b8ad73f6a:env.DATABASE_URL:23b77cb3-e56c-437e-9f69-1c91b7ba31d2:databaseEnvs.DATABASE_URL'

Customize the top-level Group name for your Ephemeral Environments

You may have noticed that all of your ephemeral environments are organized in your team using Groups - by default, kang will organize everything under a top-level kang Group, then a Sub-Group named after your environment (--name). If you'd like to customize the top-level Group name to something other than kang, simply pass --group-name when calling start and stop. For example:

start \
--ids [....] \
--name example-env \
--group-name ephemeral \
--overrides 1c6ea878-f92e-435e-a849-7bccfe7c6e5a:env.isEphemeral:true


Questions, comments, or concerns? Open an Issue and let's get it solved!