Nov 02, 2023
9 min read

Deploy Preview Environments on Koyeb for GitHub Pull Requests

Introduction

Preview environments are dynamic, temporary environments deployed from specific branches of your application in response to repository events. They are a simple way to test and collaborate on versions of your applications before deploying to production.

In this tutorial, we will explain how to automatically deploy your application using GitHub Actions each time a pull request is made for your GitHub repository.

By the end of this guide, you will have:

  • A workflow that automatically deploys the branches from your pull requests.
  • A workflow that automatically deletes the preview environment when the pull request is merged or closed.

Requirements

To successfully follow and complete this guide, you need:

  • A GitHub account to host your repositories and configure the pull request preview integration.
  • A Koyeb account to deploy and run the preview environments for each pull request.

Steps

To complete this guide and configure preview environments to your project, you need to follow these steps:

  1. Fork the example application
  2. Create a Koyeb personal access token
  3. Add the Koyeb personal access token as a repository secret
  4. Test the preview environment deployment
  5. Test the preview environment cleanup

Fork the example application

To demonstrate how to set up preview environments for a GitHub repository, we'll work with an example repository containing a basic Node.js web app built with Express. The application responds to requests with a simple "hello world" message.

To get started, visit the preview environments example repository and fork it into your account.

The main application code is found in the app.py file, but for our purposes, the GitHub Actions workflow files are more relevant. In the .github/workflows directory are two files: deploy-preview.yaml and cleanup-preview.yaml.

Understanding the preview environment deployment workflow

The deploy-preview.yaml file contains the following contents:

name: Deploy preview environment on Koyeb

on:
  pull_request:
    branches:
      - main

jobs:
  deploy_preview:
    runs-on: ubuntu-latest
    concurrency:
      group: '${{ github.head_ref }}'
      cancel-in-progress: true
    steps:
      - name: Install and configure the Koyeb CLI
        uses: koyeb-community/koyeb-actions@v2
        with:
          api_token: '${{ secrets.KOYEB_API_TOKEN }}'

      - name: Build and deploy the application to Koyeb
        uses: koyeb/action-git-deploy@v1
        with:
          git-branch: ${{ github.head_ref }}
          app-name: 'expressjs-pr-${{ github.head_ref }}'
          service-name: ${{ github.head_ref }}
          service-ports: '3000:http'
          service-routes: '/:3000'

Let's take a look at what this configuration describes.

After naming the workflow, the on.pull_requests.branches structure dictates that this workflow should only automatically trigger for pull requests events against the repositories "main" branch. If your project had a different primary branch or if you wanted to act on pull requests targeting additional branches, you could modify this value.

Next, in the jobs array, there's a single job called deploy_preview that runs the deployment. Inside it specifies that the job should be run by a Ubuntu container and it sets up a concurrency group to make sure that only one workflow is run at a time.

The actual workflow steps are fairly simple. First, it installs the Koyeb CLI using the koyeb-community/koyeb-actions action. You may notice that this step references a secret called KOYEB_API_TOKEN. You will have to configure this for your fork later on.

The second step builds and deploys the pull request branch on Koyeb using the koyeb/action-git-deploy action. The pull request branch name can be found in the github.head_ref context object. We use this to specify the branch to deploy and to name the Koyeb App and Service. The remaining lines configure the port and routing that the application expects.

To summarize, this workflow will automatically run whenever a pull request is created, re-opened, or updated. When triggered, it will deploy a new preview environment with the pull request branch.

Understanding the preview environment cleanup workflow

The cleanup-preview.yaml file contains the following contents:

name: Cleanup preview environments on Koyeb

on:
  pull_request:
    types:
      - closed

jobs:
  cleanup_preview:
    runs-on: ubuntu-latest
    steps:
      - name: Install and configure the Koyeb CLI
        uses: koyeb-community/koyeb-actions@v2
        with:
          api_token: '${{ secrets.KOYEB_API_TOKEN }}'

      - name: Cleanup Koyeb application
        uses: koyeb/action-git-deploy/cleanup@v1
        with:
          app-name: 'expressjs-pr-${{ github.head_ref }}'

This workflow is fairly similar to the last one. After naming the workflow, it targets pull requests events, but unlike last time, this workflow only triggers when a pull request is closed.

The cleanup_preview job installs the Koyeb CLI as before and again uses the KOYEB_API_TOKEN to authenticate. Afterwards, it uses the koyeb/action-git-deploy/cleanup action to delete the Koyeb app. We pass it the same App name construction used in the deployment file so that it can target the correct App.

In summary, this workflow will automatically run whenever a pull request is merged in or closed. When triggered, it will delete the preview environment based on the branch name.

Create a Koyeb personal access token

In order to deploy and manage resources on Koyeb, your GitHub repository needs a token that authorizes it to do so.

To get started, in the Koyeb control panel, click your user icon in the top right corner and click Account settings. Click the Personal Access Tokens item in the left-hand menu.

Give your new token a recognizable name and a useful description and the click Create API Access Token. Copy the token value and store it in a safe location so that we can use it in the next step. This value cannot be retrieved later, so the token will need to be recreated if you lose it.

Add the Koyeb personal access token as a repository secret

In your fork of the example application on GitHub, click the Settings tab and select Secrets and variables and then Actions. Click New repository secret to add a new secret.

Fill in the secret creation form with the following:

  • Name: KOYEB_API_TOKEN (must match the secret value from the workflow files)
  • Value: The Koyeb personal access token you generated as the secret value.

Click Add secret when you are finished.

Next, click the Actions tab for the forked repository. You'll see a disclaimer since about how GitHub Actions have been disabled for the fork until you evaluate the workflow files:

Enable GitHub Actions

If you're comfortable running the workflow files defined in the repository, click I understand my workflows, go ahead and enable them. GitHub Actions can now run on your fork.

Test the preview environment deployment

With the workflow files present and the Koyeb API token configured, your forked repository now has everything it needs to deploy and manage preview environments for pull requests.

To test the preview environment workflow, clone your fork from GitHub onto your local computer:

git clone git@github.com:<YOUR_GITHUB_ORG>/example-preview-environments.git

Move into the repository directory and switch to a new branch for your changes:

cd example-preview-environments
git switch -c change_message

Open the main app.js application file and modify the message to something different:

const express = require('express')
const app = express()
const port = process.env.PORT || 3000

app.get('/', (req, res) => {
  res.send('<h1>Hello, world!</h1>') // [!code --]
  res.send('<h1>Hello, from a different branch!</h1>') // [!code ++]
})

app.listen(port, () => {
  console.log(`App listening on port ${port}`)
})

Save and close the file when you're finished. Next, add and commit your changes and push them up to your fork:

git add :/
git commit -m 'Change greeting message'
git push origin change_message

In your fork on GitHub, open a new pull request based on the new branch:

Note: In this scenario, remember to make the pull request against your own main branch instead of the koyeb repository you forked from.

Open pull request on GitHub

After a moment, you should see the GitHub Action beginning to work in the checks at the bottom of the pull request:

Pull request checks

If you click the Details link associated with the check or view the Actions tab at the top of the repository, you can track the deployment through the GitHub Actions interface.

GitHub deploy action

If you visit the Koyeb control panel, you should see a new Koyeb App and Service being deployed for the pull request branch:

Koyeb new PR deployment

You can follow along through the build and deployment processes to see the progress. When the deployment is live, click the Public URL for the service:

Koyeb public URL

You should see the updated message text from the pull request branch:

Updated application message

The preview environment successfully built and deployed the pull request branch.

Test the preview environment cleanup

Next, you can test the preview environment cleanup workflow.

In your GitHub fork, close or merge the pull request (either will trigger the workflow). If you click the Actions tab of the repository, you should see the cleanup workflow being processed:

Cleanup workflow processing

If you visit the Koyeb control panel, you should see the Koyeb App and Service for your pull request branch being deleted automatically:

Koyeb app deletion

This confirms that the cleanup workflow is able to spin down our preview environments correctly.

Conclusion

In this tutorial, we showed how you can combine GitHub Actions and Koyeb to automatically deploy and manage preview environments based on your project's pull requests. We covered how to design workflow files that target pull request events on GitHub, how to pass the correct information to Koyeb to deploy the appropriate branches, and how to delete the resources once the pull request is closed.

By using and expanding on these workflows, you can easily integrate preview environments for your pull requests into your CI/CD pipelines. This helps you test all changes in a realistic environment prior to merging them into your main production branch. You can use this as a basis for building more sophisticated implementations that comment on the pull request thread with the preview environment details, notify slack channels, and more.


Deploy AI apps to production in minutes

Koyeb is a developer-friendly serverless platform to deploy apps globally. No-ops, servers, or infrastructure management.
All systems operational
© Koyeb