Create Preview Environments from your GitHub pipeline

Sorin Dumitrescu
8 min readJan 15, 2024

--

Preview Environments are dynamic environments, short-lived and disposable, created specifically for a given feature, so:

  • testing can be performed in isolation and in parallel, before merging
  • feedback can be given by any person within the team.
Preview Environments — illustration

The easiest way to create environments is to use an Environments-as-a-Service platform to handle the orchestration, Bunnyshell.

Contents of this article

This article showcases how you can integrate Preview Environments in a Github workflow, by using GitHub Actions and the Bunnyshell CLI. We will go through the lifecycle of a Preview Environment and see how it gets:

  • created
  • stopped
  • started
  • deleted

In a previous article, we also explored how you can achieve 1-click Preview Environments by leveraging Bunnyshell’s integration with GitHub, with no need to configure anything on the repository side.

Also, if you want to find out more about the encompassing concept of Environments-as-a-Service (or EaaS), you can explore this EaaS introductory article. In short, EaaS helps software development teams easily create environments, so their working paradigm changes for the better, as they can now use short-lived, disposable environments in a reproducible manner.

Real-world Example

How Sylius Creates Automatic Preview Environments

Sylius is a popular Open Source Headless eCommerce Platform for mid-market and enterprise brands that need custom solutions, used by more than 7k merchants. GitHub numbers confirm its popularity: 7.6k stars and 2.1k forks.

They use Bunnyshell to create a dedicated isolated environment for each Pull Request, used for:

  • Code reviews with a running application
  • Testing features and fixes
  • Getting feedback from the community
Example of a Pull Request from Sylius

Each Pull Request creates a dedicated environment, which will be stopped automatically after 4 hours, but can be started again through just a simple comment in the Pull Request, with the text /bns:start. Upon merging or closing the Pull Request, the environment is automatically deleted, to free up resources.

By opening the URL for the php component, from the GitHub Pull Request comment posted by Bunnyshell, you will be able to see the replica of the Sylius project, having included changes from the source branch, and running with its separate database and file storage.

Sylius preview — Homepage

This is achieved by defining some GitHub workflows, which in turn leverage some reusable GitHub workflows created and maintained by Bunnyshell.

Sylius’ .github/workflows folder — Bunnyshell workflows highlighted

See the workflows in action

To keep things as simple as possible, we will look at a very simple demo repository.

Triggering the automatic creation and deployment of a new environment is done by a Github workflow defined in the repository, in the file located at .github/workflows/bunnyshell_deploy-preview-env.yaml .

name: Bunnyshell - Deploy Preview Environment
on:
pull_request:
types: [ opened, reopened, synchronize ]
branches:
- '*'
paths-ignore:
- "*.md"
issue_comment:
types: [ created, edited ]
jobs:
deploy:
name: Deploy Environment
uses: bunnyshell/workflows/.github/workflows/prepare-and-deploy-env.yaml@v2
with:
pr-number: ${{ github.event.number || github.event.issue.number }}
git-ref: refs/pull/${{ github.event.number || github.event.issue.number }}/head
allowed-users: ${{ vars.BUNNYSHELL_ALLOWED_USERS }}
restricted-files: |
.bunnyshell/*
project-id: ${{ vars.BUNNYSHELL_PROJECT_ID }}
cluster-id: ${{ vars.BUNNYSHELL_CLUSTER_ID }}
env-name: "Demo PR #${{ github.event.number || github.event.issue.number }}"
bunnyshell-yaml-path: .bunnyshell/templates/preview/bunnyshell.yaml
comment-on-pr: true
deploy-as-stopped: false
secrets:
bunnyshell-access-token: ${{ secrets.BUNNYSHELL_ACCESS_TOKEN }}

You need to define 4 parameters to instruct Bunnyshell on where to create and deploy the environment:

  • the access token for Bunnyshell (as a secret) — after logging in to Bunnyshell, click Profile > Access token and copy that value; or simply open this link.
  • the Bunnyshell Project ID — public ID, like ezXJKO6a43
  • the Kubernetes Cluster ID — public ID, like 7A4GeLx3bk
  • the list of users allowed to deploy environments with different configurations — either * for all users, or a JSON list for specific users, like. ["githubUsername1", "githubUsername2"]
GitHub repository settings — defining the needed variables

Next, we will go through the lifetime of a Preview Environment, to see how you can use one.

1. Create the Pull Request — and the environment

When creating a Pull Request, the deploy action will be triggered.

GitHub — Pull Request —running the action

A comment will appear regarding the real-time status of the operation: first, it will announce that a Preview Environment will be created, then it will add URLs pointing to Bunnyshell, to see the environment and its current-running pipeline.

GitHub — Pull Request comment — in progress

Opening the Bunnyshell URLs, you will be able to see the environment and its pipeline, with real-time build & deployment logs.

Bunnyshell — Environment details and pipeline

Finally, once the environment deployment is finished, you will be able to:

  • open application URLs from the Pull Request comment
  • see the completed pipeline’s logs
  • control the environment directly from the Pull Request, by leaving a comment to stop, start, deploy, or delete the environment
GitHub — Pull Request comment — deployed

The environment page from Bunnyshell will also get updated and opening the frontend application will allow you to see the working application and preview the backend-made changes (adding the ID to the book title).

Bunnyshell environment + Application preview

2. Stop the environment

Stopping the environment is as simple as leaving a comment in the Pull Request with the message /bns:stop. You will see the Bunnyshell comment being updated with the message that the environment was stopped.

GitHub Pull Request comment + Associated Action

3. Start the environment

Starting the environment is as simple as leaving a comment in the Pull Request with the message /bns:start. You will see the Bunnyshell comment being updated with the message that the environment is deployed, and the application URLs.

GitHub Pull Request comment + Associated Action

4. Merge or Close the Pull Request — and delete the environment

An environment is no longer needed for a Pull Request if it is no longer open (was either merged or closed), so Bunnyshell will delete the associated environment as well.

GitHub Pull Request comment + Associated Action

The same outcome of deleting the environment can also be achieved manually, by leaving a comment with the text /bns:delete.

Practical scenarios

Below, we will briefly see a few common use cases.

A. Prevent auto-deployment when modifying impactful files

When changing sensitive files, such as the environment definition (bunnyshell.yaml) itself, or other infrastructure-related configuration files, credentials, etc, you probably want to prevent auto-deployment and require manual approval from a trusted user.

The workflows define two properties that help with this: restricted-files and allowed-users.

Upon detecting changes in the restricted files list (or pattern list), the automatic deployment is halted, and a manual comment is required to continue, from one of the users in the allowed-users property.

GitHub Pull Request comment + Associated Action (restricted deployment)

After leaving a comment with the text /bns:deploy (by one of the allowed users) the deployment will pass the verification stage and happen as any other deployment.

GitHub Pull Request comment + Associated Action (resumed deployment)

B. Troubleshoot a failed deployment

Whenever a deployment fails, you will also see this in the Pull Request comment, along with the links to the Bunnyshell environment and logs.

GitHub Pull Request comment + Bunnyshell environment details

Opening the logs will reveal the failed job, and failed step within the job. In this case, the new Dockerfile does not exist, but any other error will be revealed the same way.

Bunnyshell deployment logs — failed deployment

C. Create environments as stopped to save compute resources

If pickup times for Code Reviews or testing are long, you don’t want to have the compute resources reserved for these Preview Environments. A deploy-as-stopped parameter exists, which will essentially perform a stop after the deployment has been completed successfully.

Starting the environments is considerably faster than a build + deploy workflow — in the tens of seconds, compared to minutes when building and deploying.

This is what an environment looks like after being deployed with thedeploy-as-stopped: true parameter. It is very similar to the “deployed” comment — it just adds another URL to the stop’s pipeline logs.

To start the environment, simply leave a comment in the Pull Request with the text /bns:start .

GitHub Pull Request comment + Associated Action

And the environment will be up and running in less than a minute.

Running environment

D. Handle public repositories and fork-based workflows

For public repositories, the GitHub token injected in the forked repo when cloning the repository has read-only permissions, meaning it cannot post Pull Request comments.

For this reason, the workflow must be split into 2 parts, but fortunately, the demo repository contains an example for this scenario as well:

  • first, to generate the bunnyshell.yaml — “Prepare
  • second, to create the environment and make the deployment — “Deploy

Conclusion

I hope you found the concept of Preview Environments useful, and that seeing a concrete implementation based on pipelines gave you a few ideas on how you could benefit from using them, either in code reviews, manual/automated testing, or improving collaboration.

--

--

Sorin Dumitrescu

Driving change in the DX space, with a background in web development and high-traffic applications and a passion for efficiency in technology and processes.