• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Terraform
  • Install
  • Tutorials
    • About the Docs
    • Configuration Language
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
    • CDK for Terraform
    • Provider Use
    • Plugin Development
    • Registry Publishing
    • Integration Program
  • Registry(opens in new tab)
  • Try Cloud(opens in new tab)
  • Sign up
Applications

Skip to main content
9 tutorials
  • Use Application Load Balancers for Blue-Green and Canary Deployments
  • Host a Static Website with S3 and Cloudflare
  • Deploy, Manage, and Scale an Application on Heroku
  • Deploy an Application to a DigitalOcean Droplet
  • Deploy Federated Multi-Cloud Kubernetes Clusters
  • Deploy Applications with CDK for Terraform
  • Manage Hosted Kafka with the Confluent Terraform Provider
  • Automate Monitoring with the Terraform Datadog Provider
  • Create Preview Environments with Terraform, GitHub Actions, and Vercel

  • Resources

  • Tutorial Library
  • Certifications
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  • Terraform Registry
    (opens in new tab)
  1. Developer
  2. Terraform
  3. Tutorials
  4. Applications
  5. Create Preview Environments with Terraform, GitHub Actions, and Vercel

Create Preview Environments with Terraform, GitHub Actions, and Vercel

  • 24min

  • Terraform CloudTerraform Cloud
  • TerraformTerraform

Continuous integration and delivery (CI/CD) lets you release more frequently by automating testing and other tasks, so you can ship improvements to your services sooner. Preview environments are temporary environments that your CI pipelines can create for new pull requests to demonstrate feature changes. This helps your team (developers, product, QA) discover bugs faster, and experiment with the latest features without manually checking-out the branch and running the application locally.

Vercel is a platform that deploys frontend frameworks and static websites instantaneously, scales them automatically, and generates preview environments. While you can use Vercel's Git integration to create preview environments with serverless backends, Terraform lets you handle more complex preview environment setups that use Vercel for the frontend and other services for the backend. This creates fully-featured applications that you can share with your stakeholders for review and testing.

Vercel frontend and backend deployment methods

In this tutorial, you will build a workflow for deploying preview environments, and test changes to HashiCups, a fictional coffee-shop application. To build the preview workflow, you will create reusable Terraform Cloud variable sets for your AWS and Vercel API credentials, setup and deploy the preview environments' shared resources, and set up the frontend preview environments repository. Then, you will test the workflow — which creates and destroys preview environments — by opening, merging, and closing pull requests.

Introduction to HashiCups

HashiCups is a demo application that lets you view and order customized HashiCorp branded coffee. The HashiCups application consists of a frontend React application and multiple backend services.

The HashiCups backend consists of a GraphQL backend, products API, a Postgres database, and a payments API. This tutorial uses a Docker compose file to bootstrap the backend services on an EC2 instance. The frontend application, running on Vercel, expects an HTTP-secured public API.

HashiCups frontend and backend services

Prerequisites

The tutorial assumes that you are familiar with the Terraform and Terraform Cloud plan and apply workflows. If you are new to Terraform itself, refer first to the Get Started tutorials. If you are new to Terraform Cloud, refer to the Get Started - Terraform Cloud tutorials.

For this tutorial, you will need:

  • the Terraform 1.1.4+ CLI installed locally.
  • an AWS account with AWS Credentials configured for use with Terraform.
  • a Terraform Cloud account
  • a GitHub account
  • a Vercel account

Create Vercel API token

The Terraform Vercel provider requires a personal account token for authentication. On the Vercel Token page, create a Vercel API token named learn-terraform.

Create a Vercel API token

Save this token in a safe place as Vercel will only display it once. You will create a Terraform Cloud variable set for this API token in the next step.

Set up Terraform Cloud

Next, you need to configure Terraform Cloud so that it can securely interact with GitHub, Vercel, and AWS on your behalf. This involves generating a Terraform Cloud token to give to GitHub, which it will use to trigger builds, and adding your Vercel token and AWS credentials to your Terraform Cloud workspace.

Create Terraform Cloud team

In order for GitHub Actions to interact with Terraform Cloud, you must create a Terraform Cloud API token. While you could use your personal API token, it will have the same permissions as your user, which may span multiple organizations and workspaces. Terraform Cloud teams enable your organization to properly scope permissions.

Note: Terraform Cloud teams is a paid feature. If you do not have a paid account, create a personal API token by going to the Tokens page.

Visit your Terraform Cloud organization's Teams page, found under Settings > Teams in the Terraform Cloud UI.

Create a new team named learn-tf-preview-env.

Create new team named `learn-tf-preview-env` in Terraform Cloud

Then, grant the learn-tf-preview-env team permission to manage workspaces. Click Update team organization access to confirm your changes.

Grant team ability to manage workspaces

Create Terraform Cloud team API token

Scroll down to the Team API Token section and click Create a team token.

Create Team API token

Save this token in a safe place as Terraform Cloud will only display it once. You will add it to GitHub as a secret later in this tutorial.

Add the following to your Terraform configuration file, replacing TOKEN with your Terraform Cloud team API Token. This will let the Terraform CLI use your new team API token and use Terraform Cloud.

~/.terraformrc
credentials "app.terraform.io" {
  token = "TOKEN"
}

Create Terraform Cloud variable sets

Each pull request will create a new Terraform Cloud workspace to launch your preview environment. The easiest way to allow each of these workspaces to authenticate to AWS and Vercel is through Terraform Cloud’s reusable variable sets. Terraform Cloud variable sets let you centrally manage provider credentials and reuse them across workspaces.

Since GitHub Actions dynamically generates the Terraform Cloud workspaces for the preview environments, these variable sets must apply to all workspaces in the organization.

Note: Terraform Cloud applies global variable sets to every workspace, which may lead to credential leakage. Be mindful if you include credentials in global variables.

Create AWS Credentials variable sets

If you do not have a variable set containing your AWS credentials, follow the steps in the Create and Use a Variable Set tutorial to create one. Select Apply to all workspaces in this organization for the variable set scope.

Tip: If you have temporary AWS credentials, you must also add your AWS_SESSION_TOKEN as an environment variable to the variable set.

Create Vercel Credentials variable sets

Create a new variable set named Vercel Credentials. Select Apply to all workspaces in this organization for the variable set scope.

Create an environment variable named VERCEL_API_TOKEN and set it to your Vercel API token. Mark this variable as sensitive.

Create variable set for Vercel API token

Click Add variable and Create variable set to create your Vercel variable set.

Setup and deploy shared resources

The setup for this tutorial relies on two sets of resources across two repositories: one for the shared resources and the other for the temporary preview environments . Each temporary preview environment will share the same VPC, security group, TLS certificate, and Vercel project. The shared resources repository manages these resources.

Fork the Learn Terraform Preview Environments Shared repository.

Clone your fork of the learn-terraform-preview-environment-shared repository, replacing USERNAME with your own Github username.

$ git clone https://github.com/USERNAME/learn-terraform-preview-environment-shared

Navigate to the cloned repository.

$ cd learn-terraform-preview-environment-shared

Review shared resources

This repository contains Terraform configuration to deploy shared resources that your preview environments will use:

  1. The vpc module deploys a VPC and subnets. Terraform will provision your backend preview environments in this VPC.

  2. The aws_security_group.hashicups-backend allows ingress traffic on ports :443 and :8080, and allows all egress traffic for access to the HashiCups backend preview environment.

    main.tf
    resource "aws_security_group" "hashicups-backend" {
      name   = "hashicups-backend"
      vpc_id = module.vpc.vpc_id
    
      ingress {
        from_port   = 443
        to_port     = 443
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      ingress {
        from_port   = 8080
        to_port     = 8080
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
  3. The tls_private_key, tls_self-signed_cert, and aws_acm_certificate resources generate and upload a self-signed certificate to AWS. The HashiCups frontend expects an HTTPS-secured backend. This self signed certificate enables the load balancer for each backend preview environment to serve traffic through HTTPS.

  4. The vercel_project resource creates a Vercel project named hashicups. This project is preconfigured to use the React framework.

    main.tf
    resource "vercel_project" "hashicups" {
      name      = "hashicups"
      framework = "create-react-app"
    }
    

The outputs.tf file defines outputs for these resources. This allows the preview environment workspaces to reference them through the terraform_remote_state data source.

outputs.tf
output "vpc_id" {
  value = module.vpc.vpc_id
}

output "public_subnets" {
  value = module.vpc.public_subnets
}

output "hashicups_security_group_id" {
  value = aws_security_group.hashicups-backend.id
}

output "ssl_cert_arn" {
  value = aws_acm_certificate.cert.arn
}

output "vercel_project_id" {
    value = vercel_project.hashicups.id
}

Update shared resources configuration

Before you can use this configuration, you must update it to point to your Terraform Cloud organization.

In terraform.tf, replace hashicorp-training with your Terraform Cloud organization name. Terraform will create a new workspace named hcup-be-shared in Terraform Cloud and use it to create and manage your shared sources.

terraform.tf
terraform {
  cloud {
    hostname = "app.terraform.io"
    organization = "hashicorp-training"
    workspaces {
      name = "hcup-be-shared"
    }
  }
}

Initialize shared resources

Initialize the Terraform configuration.

$ terraform init
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 3.11.0 for vpc...
- vpc in .terraform/modules/vpc

Initializing Terraform Cloud...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/tls from the dependency lock file
- Installing hashicorp/aws v3.74.0...
- Installed hashicorp/aws v3.74.0 (signed by HashiCorp)
- Installing hashicorp/tls v3.1.0...
- Installed hashicorp/tls v3.1.0 (signed by HashiCorp)

Terraform Cloud has been successfully initialized!

You may now begin working with Terraform Cloud. Try running "terraform plan" to
see any changes that are required for your infrastructure.

If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.

Navigate to Terraform Cloud and filter on hcup- to find your newly created workspace.

The `hcup-be-shared` workspace is present in Terraform Cloud

Deploy shared resources

Apply the configuration. Respond yes to the prompt to deploy the shared resources.

$ terraform apply
Running apply in Terraform Cloud. Output will stream here. Pressing Ctrl-C
will cancel the remote apply if it's still pending. If the apply started it
will stop streaming the logs, but will not stop the apply running remotely.

Preparing the remote apply...

To view this run in a browser, visit:
https://app.terraform.io/app/hashicorp-training/hcup-be-shared/runs/run-REDACTED

Waiting for the plan to start...

Terraform v1.1.4
on linux_amd64
Configuring remote state backend...
Initializing Terraform configuration...

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

## ...

Plan: 18 to add, 0 to change, 0 to destroy.

## ...

Do you want to perform these actions in workspace "hcup-be-shared"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

## ...

Apply complete! Resources: 18 added, 0 changed, 0 destroyed.

Outputs:

hashicups_security_group_id = "sg-095d6f82a01674c21"
public_subnets = [
  "subnet-006b8db212954996c",
  "subnet-0849d3d30fc3a10b6",
]
ssl_cert_arn = "arn:aws:acm:us-east-2:656261198433:certificate/REDACTED"
vpc_id = "vpc-0e9b2217c3caf5086"

Enable remote state sharing

Your preview environments need to access the hcup-be-shared workspace's state to reference its outputs.

Navigate to the hcup-be-shared workspace, then select Settings > General.

In the Remote state sharing section, select Share with all workspaces in this organization. Click Save settings.

Note: Terraform will enable any workspace in the organization to access this workspace's state. Be mindful when you enable this option since it may expose sensitive state.

Enable remote state sharing on `hcup-be-shared` workspace

Set up preview environment repository

Fork the Learn Terraform Preview Environments repository.

Since this repository will use GitHub actions with Terraform Cloud to deploy preview environments, you must create repository action secrets and enable GitHub actions.

Create repository action secrets

In your forked repository, navigate to Settings. In the Secrets menu on the left sidebar, select Actions. Create a repository secret named TFC_API_TOKEN and set it to the Terraform Cloud team API token you created in the previous step.

Create Terraform Cloud API Token secrets in forked preview environment repository

Enable GitHub Actions

Navigate to the "Actions" tab and enable the pre-configured workflow by clicking "I understand my workflows, go ahead and enable them."

Enable workflow actions in GitHub fork

Clone forked preview environment repository

Clone your fork of the learn-terraform-preview-environment repository, replacing USERNAME with your own Github username.

$ git clone https://github.com/USERNAME/learn-terraform-preview-environment

Navigate to the cloned repository.

$ cd learn-terraform-preview-environment

Review preview environment repository

The learn-terraform-preview-environment repository contains:

  1. The HashiCups frontend application.
  2. The HashiCups preview environment backend Terraform configuration.
  3. The GitHub Action that triggers the preview environment creation during pull requests.

This section will primarily focus on the Terraform configuration and the GitHub Action.

Review Terraform resources

The main.tf file contains the terraform block, which specifies the Terraform Cloud organization to run in. The workspaces block is a placeholder — the GitHub Action will replace this with a new workspace name for each run's preview environment and operations.

main.tf
terraform {
  cloud {
    hostname     = "app.terraform.io"
    organization = "hashicorp-training"
    workspaces {
      tags = ["hashicupsBackend"]
    }
  }

  required_providers {
    vercel = {
      source  = "vercel/vercel"
      version = "0.1.0"
    }
  }
}

This file also defines the preview-env Terraform module, which contains the configuration to deploy the EC2 instance, load balancers, and Vercel deployment associated with your preview environment.

main.tf
module "preview-env" {
   source  = "./preview-env"
   is_prod = var.is_prod
}

The module takes one input: is_prod. If is_prod is set to true, Terraform will not deploy the backend preview environment resources and instead update the production Vercel deployment.

This configuration also returns two outputs: the lb_dns_name, which corresponds to the backend URL, and the preview_url, which corresponds to the Vercel deployment.

Next, navigate to the preview-env directory, which contains the following:

  1. The main.tf file defines aws_instance.hashicups-backend, the EC2 instance containing the HashiCups backend. This EC2 instance references the subnets and security groups from hcup-be-shared, the shared resources workspace.

    preview-env/main.tf
    resource "aws_instance" "hashicups-backend" {
      count                       = var.is_prod ? 0 : 1
      ami                         = data.aws_ami.ubuntu.id
      instance_type               = "t2.micro"
      subnet_id                   = data.terraform_remote_state.shared.outputs.public_subnets[0]
      vpc_security_group_ids      = [data.terraform_remote_state.shared.outputs.hashicups_security_group_id]
      associate_public_ip_address = true
      user_data                   = data.template_file.user_data.rendered
    
      tags = {
        Name = terraform.workspace
      }
    }
    

    Notice the count meta-argument. Terraform will not create an EC2 instance containing the HashiCups backend if is_prod is true.

    Tip: The setup-hashicups.yaml file contains the user data script to provision the EC2 instance with the HashiCups backend.

  2. The loadbalancer.tf file defines an application load balancer and directs traffic to the EC2 instance. Since the HashiCups backend must run on HTTPS, it uses a self-signed certificate sourced from the hcup-be-shared workspace. The resources in this file use terraform.workspace as a name so you can more easily determine which workspace manages them. AWS uses the load balancer name as part of its URL, so the endpoint will contain the Terraform Cloud workspace name.

  3. The vercel.tf file defines the Vercel deployment. The vercel_project_directory.frontend resource packages everything in the current directory to send to Vercel. The public_api_url local value returns the backend API url if the load balancer exists.

    The vercel_deployment resource creates the Vercel frontend deployment. This resource defines an environment variable named NEXT_PUBLIC_PUBLIC_API_URL and sets it to the preview environment backend. Vercel will build the HashiCups frontend with this environment variable, connecting the frontend to the preview environment backend.

    preview-env/vercel.tf
    resource "vercel_deployment" "frontend" {
      project_id = data.vercel_project.fe.id
      files      = data.vercel_project_directory.frontend.files
      production = var.is_prod
      environment = {
        NEXT_PUBLIC_PUBLIC_API_URL = var.is_prod ? "" : local.public_api_url
      }
    }
    
  4. The outputs.tf file defines three outputs. The lb_dns_name and public_ip point to the HashiCups backend. The preview_url is the deployment URL containing the HashiCups frontend.

Review GitHub Actions

GitHub Actions add continuous integration to your repository, enabling you to automate your processes. A GitHub Action workflow is an automated process consisting of multiple steps.

Open .github/workflows/vercel.yml, which defines a GitHub Action workflow for building and destroying preview environments.

This workflow only runs when you push to the main branch, or if someone creates or closes a pull request.

.github/workflows/vercel.yml
name: "Build and Deploy Preview Environment"

on:
  push:
    branches:
      - main
  pull_request:
    types: [opened, closed]

This workflow defines a preview-environment job with two environment variables and eight steps.

  1. The tfcWorkspaceName environment variable is set to the branch name prefixed by hcup-be. The GitHub Action will update the Terraform configuration to use this workspace name.

  2. The tfcOrg environment variable defaults to hashicorp-training – you will update this to your Terraform Cloud organization in the next step. The destroy step uses this environment variable to destroy the Terraform Cloud workspace once you close the pull request.

.github/workflows/vercel.yml
jobs:
  preview-environment:
    name: "Build and Deploy Preview Environment"
    runs-on: ubuntu-latest
    env:
      tfcWorkspaceName: hcup-be-${{ github.head_ref }}
      tfcOrg: hashicorp-training
    steps:

The steps define all actions in the workflow. This workflow takes one of three paths depending on the GitHub event that triggered it. As a result, each trigger will not run every step in the action.

  1. When someone creates a new pull request, this GitHub Action will create the preview environment by running the steps in the diagram below.

    Create preview environment process with steps

  2. When someone closes a pull request, the GitHub Action will delete the existing preview environment by running the steps in the diagram below.

    Destroy preview environment process with steps

  3. When someone merges the pull request into the main branch, this GitHub Action will build and deploy the frontend into production by running the steps in the diagram below.

    Build and deploy production process with steps

The GitHub Action job defines the following steps:

  • Checkout checks out the current commit.

    .github/workflows/vercel.yml
    - name: Checkout
      uses: actions/checkout@v2
    
  • Setup Terraform uses setup-terraform to retrieve the Terraform CLI and loads the TFC_API_TOKEN as an environment variable, enabling the Terraform CLI to authenticate to Terraform Cloud.

    .github/workflows/vercel.yml
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        cli_config_credentials_token: ${{ secrets.TFC_API_TOKEN }}
    
  • Terraform Init, create TFC workspace updates main.tf to use the workspace name defined by tfcWorkspaceName (which contains your Git branch name). It then initializes the configuration, creating the Terraform Cloud workspace. This step only runs during pull requests.

    .github/workflows/vercel.yml
    - name: Terraform Init, create TFC workspace
      id: init-workspace
      if: github.event_name == 'pull_request'
      run: |
        sed -i 's/tags = \["hashicupsBackend"\]/name = "'$tfcWorkspaceName'"/g' main.tf
        terraform init -input=false
    
  • Build and deploy preview environment applies the configuration, building and deploying both the backend and frontend preview environments. This step only runs during open pull requests.

    .github/workflows/vercel.yml
    - name: Build and deploy preview environment
      if: github.event_name == 'pull_request' && github.event.action != 'closed'
      id: build-deploy-preview-environment
      run: |
        terraform apply -auto-approve
    
  • Terraform output returns the outputs of the previous run. This output contains the URL for the backend API and the Vercel deployment. This step only runs during open pull requests.

    .github/workflows/vercel.yml
    - name: Terraform Output
      id: output
      if: github.event_name == 'pull_request' && github.event.action != 'closed'
      run: |
        terraform output -no-color
      continue-on-error: true
    
  • Create comment with Terraform output creates a comment in the pull request with the Terraform output. This makes it easier for you to navigate to the backend and frontend URL. This step only runs during open pull requests.

    .github/workflows/vercel.yml
    - name: Create comment with Terraform output
      uses: actions/github-script@0.9.0
      if: github.event_name == 'pull_request' && github.event.action != 'closed'
      env:
        OUTPUT: "${{ steps.output.outputs.stdout }}"
      with:
        github-token: ${{ secrets.GITHUB_TOKEN }}
        script: |
          const output = `#### Preview Environment Outputs 🖌
          \`\`\`
          ${process.env.OUTPUT}
          \`\`\`
          `
          github.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: output
          })
    
  • Destroy preview environment destroys the resources in the Terraform Cloud workspace, then ndestroys the workspace itself using the Terraform Cloud API. This step only runs when someone closes the pull request, which includes merging a pull request.

    .github/workflows/vercel.yml
    - name: Destroy preview environment
      if: github.event.action == 'closed'
      id: destroy-preview-environment
      run: |
        terraform destroy -auto-approve
        curl --header "Authorization: Bearer ${{ secrets.TFC_API_TOKEN }}" --header "Content-Type: application/vnd.api+json" --request DELETE "https://app.terraform.io/api/v2/organizations/${tfcOrg}/workspaces/${tfcWorkspaceName}"
    
  • Build and deploy Prod Environment updates the Terraform Cloud workspace in main.tf to hcup-frontend-vercel. Then, it initializes the configuration and applies the configuration with the is_prod variable set to true. This step only runs when someone pushes to the main branch. This includes merging a pull request into main.

    .github/workflows/vercel.yml
    - name: Build and deploy Prod Environment
      id: build-deploy-prod-environment
      if: github.ref == 'refs/heads/main' && github.event_name == 'push'
      run: |
        sed -i 's/tags = \["hashicupsBackend"\]/name = "hcup-frontend-vercel"/g' main.tf
        terraform init -input=false
        terraform apply -auto-approve -var="is_prod=true"
    

Update configuration

Before you can use this configuration, you must update the configuration in three places to point to your Terraform Cloud organization and Vercel project.

  1. In main.tf, replace hashicorp-training with your Terraform Cloud organization name.

    main.tf
    terraform {
      cloud {
        hostname = "app.terraform.io"
        organization = "hashicorp-training"
        workspaces {
          tags = ["hashicupsBackend"]
        }
      }
      ## …
    }
    
  2. In preview-env/main.tf, replace hashicorp-training with your Terraform Cloud organization name.

    preview-env/main.tf
    data "terraform_remote_state" "shared" {
      backend = "remote"
    
      config = {
        organization = "hashicorp-training"
        workspaces = {
          name = "hcup-be-shared"
        }
      }
    }
    
  3. In .github/workflows/vercel.yml, replace hashicorp-training with your Terraform Cloud organization name.

    .github/workflows/vercel.yml
    name: "Build and Deploy Preview Environment"
    
    on:
      push:
        branches:
          - main
      pull_request:
    
    jobs:
      preview-environment:
        name: "Build and Deploy Preview Environment"
        runs-on: ubuntu-latest
        env:
          tfcWorkspaceName: hcup-be-'${{ github.head_ref }}'
          tfcOrg: hashicorp-training
        steps:
    

You must commit and push your changes to version control.

First, add your configuration changes.

$ git add .

Next, commit your changes.

$ git commit -m "Update Vercel project name and TFC organization name"

Finally, push your changes.

$ git push

Since you are pushing directly to the main branch, the GitHub Action will trigger to build and deploy the production frontend in Vercel.

GitHub actions builds and deploys production frontend in Vercel

Create preview environment

In this step, you will create a pull request that contains a change to the frontend. This will trigger the GitHub action to create a preview environment.

In src/components/Header.js, on line 62, add <h1 class="font-bold py-4">HashiCups</h1> before </header>. This will render HashiCups after the HashiCorp logo in the frontend.

src/components/Header.js
  <header>
    ## ...
    <div className="absolute left-0 top-0">
      <Image src="/images/demo.svg" height={88} width={88} loader={imageLoader} unoptimized />
    </div>
    <h1 class="font-bold py-4">HashiCups</h1>
  </header>

Now, you will push your changes in a new branch to create a pull request. This emulates the development workflow.

Create a new branch named update-frontend for your changes.

$ git checkout -b "update-frontend"
Switched to a new branch 'update-frontend'

Add the configuration changes.

$ git add .

Then, commit the changes.

$ git commit -m "Add HashiCups to header"

Finally, push the changes.

$ git push --set-upstream origin update-frontend
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 16 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 531 bytes | 531.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
remote: 
remote: Create a pull request for 'update-frontend' on GitHub by visiting:
remote:      https://github.com/USERNAME/learn-terraform-preview-environment/pull/new/update-frontend
remote: 
To ssh://github.com/USERNAME/learn-terraform-preview-environment
 * [new branch]      update-frontend -> update-frontend
Branch 'update-frontend' set up to track remote branch 'update-frontend' from 'origin'.

Next, generate a pull request from the update-frontend branch. From the base repository drop-down, choose your forked repository and main branch. Click Create pull request.

Open pull request for `update-frontend` branch

The pull request automatically triggers the GitHub action. Click on Details to follow the GitHub Action.

Pull request for `update-frontend` branch. This pages shows the GitHub Action running

When GitHub Action runs the build step, it displays a Terraform Cloud link so you can access the run from Terraform Cloud.

Detailed GitHub Action for `update-frontend` branch that shows each step

Once the Terraform Cloud run completes, the GitHub action will add a comment to the pull request containing the Terraform outputs.

GitHub Action adds a new commit to pull request containing Terraform outputs

Notice that the load balancer DNS name contains the branch name, update-frontend.

Verify preview environment

First, go to lb_dns_name, the backend URL, and accept the self-signed certificate. You must accept the self-signed certificate for the HashiCups frontend to successfully communicate with the backend.

Accept preview environment backend's self-signed certificate

Then, navigate to the Vercel deployment URL. Notice that "HashiCups" appears in the header, reflecting the changes you made in the pull request.

HashiCups frontend with the changes from `update-frontend`

Open the developer tools console. You will find the frontend displays the API it's connected to.

API: https://hcup-be-update-frontend-162136954.us-east-2.elb.amazonaws.com

Merge pull request

When you merge a pull request, you want to build and deploy the latest version into production and destroy the preview environment associated with the pull request.

Navigate to your pull request for update-frontend then click Merge pull request to merge your changes into the main branch.

Merge pull request for `update-frontend` branch

Click on the Actions tab. Notice that merging the pull request triggers two GitHub Action runs.

  1. The run for update-frontend deletes the preview environment resources and workspace associated with the pull request.
  2. The run for main builds the frontend for production and deploys it to Vercel.

View two triggered GitHub Actions from merging the pull request into the `main` branch

Create another preview environment

In this section, you will open another pull request with new changes to create a second, isolated preview environment.

In src/components/Header.js, on line 62, add <h1 class="font-bold py-4">HashiCups #2</h1> before </header>.

src/components/Header.js
  <header>
    ## ...
    <div className="absolute left-0 top-0">
      <Image src="/images/demo.svg" height={88} width={88} loader={imageLoader} unoptimized />
    </div>
    <h1 class="font-bold py-4">HashiCups #2</h1>
  </header>

Create a new branch named update-frontend-2 for your changes.

$ git checkout -b "update-frontend-2"
Switched to a new branch 'update-frontend-2'

Add your configuration changes.

$ git add .

Then, commit your changes.

$ git commit -m "Add HashiCups #2 to header"

Finally, push your changes.

$ git push --set-upstream origin update-frontend-2
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 16 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 531 bytes | 531.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
remote: 
remote: Create a pull request for 'update-frontend-2' on GitHub by visiting:
remote:      https://github.com/USERNAME/learn-terraform-preview-environment/pull/new/update-frontend-2
remote: 
To ssh://github.com/USERNAME/learn-terraform-preview-environment
 * [new branch]      update-frontend-2 -> update-frontend-2
Branch 'update-frontend-2' set up to track remote branch 'update-frontend-2' from 'origin'.

Next, create a pull request from the update-frontend-2 branch. From the base repository drop-down, choose your forked repository and main branch. Click Create pull request.

Once the GitHub Action completes, it will post the outputs for your new preview environment in a comment on your pull request.

lb_dns_name = "https://hcup-be-update-frontend-2-364349130.us-east-2.elb.amazonaws.com"
preview_url = "https://hashicups-o19jfa6ei.vercel.app"

Notice that the load balancer DNS name contains the branch name, update-frontend-2. Accept the backend API's self-signed certificate before navigating to the preview URL.

Your UI will reflect the changes in your update-frontend-2 branch. This preview environment is completely isolated and independent. Changes to this preview environment will not affect other preview environments.

Close pull request

When you close a pull request, you no longer need to review its preview environments. Close the pull request for your update-frontend-2 branch.

Close pull request for `update-frontend-2

Click on Actions, then on the latest run.

View triggered GitHub Action when pull request closes

Notice that the GitHub Action runs the destroy workflow, deleting the resources in the preview workspace and the workspace itself.

Detailed GitHub Action steps for closed pull request

Clean up your infrastructure

Before moving on, destroy the resources and Terraform Cloud workspaces you created for this tutorial. The resources and Terraform Cloud workspaces associated with the pull requests were deleted in the Close pull request and Merge pull request sections.

In Terraform Cloud, go to the hcup-be-shared and hcup-frontend-vercel workspaces, queue a destroy plan, and apply it. Then, delete the workspaces from Terraform Cloud.

For more detailed guidance on destroying resources in Terraform Cloud, reference the Destroy Resources and Workspaces tutorial.

Next steps

Over the course of this tutorial, you set up, created, and destroyed preview environments for HashiCups. In the process, you learned how to automate dynamic Terraform workspace runs in your CI/CD pipelines with Terraform Cloud and Terraform Cloud variable sets.

For more information on topics covered in this tutorial, check out the following resources.

  • Learn how to automate Terraform Cloud workspaces, variables, run triggers and more in the Automate Terraform Cloud Workflow tutorial.
  • Learn how to release applications in a rolling upgrade with near-zero downtime in the Use Application Load Balancers for Blue-Green and Canary Deployments
  • Learn how to deploy an application to Kubernetes with TypeScript in the Deploy Applications with CDK for Terraform
 Previous
 Next Collection

This tutorial also appears in:

  •  
    22 tutorials
    Collaborate using Terraform Cloud
    Collaborate on infrastructure with Terraform Cloud. Follow these tutorials to migrate state from local storage and take a deeper look at Terraform Cloud operations, including VCS integration, workspace configuration, and remote runs.
    • Terraform
  •  
    14 tutorials
    Manage AWS Services
    Use the AWS provider to manage AWS services with Terraform. Configure IAM policy documents, deploy serverless functions with Lambda, use application load balancers to schedule near-zero downtime releases, manage RDS and more.
    • Terraform
  •  
    11 tutorials
    Automate Terraform
    Automate Terraform with Terraform Cloud and integrate it with third-party CI/CD tools such as GitHub Actions and CircleCI.
    • Terraform

On this page

  1. Create Preview Environments with Terraform, GitHub Actions, and Vercel
  2. Prerequisites
  3. Set up Terraform Cloud
  4. Setup and deploy shared resources
  5. Set up preview environment repository
  6. Clone forked preview environment repository
  7. Review preview environment repository
  8. Update configuration
  9. Create preview environment
  10. Verify preview environment
  11. Merge pull request
  12. Create another preview environment
  13. Close pull request
  14. Clean up your infrastructure
  15. Next steps
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)