A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.hashicorp.com/terraform/tutorials/aws/preview-environments-vercel below:

Create preview environments with Terraform, GitHub Actions, and Vercel | Terraform

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.

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 HCP Terraform 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.

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

For this tutorial, you will need:

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.

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

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

Create HCP Terraform team

In order for GitHub Actions to interact with HCP Terraform, you must create an HCP Terraform 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. HCP Terraform teams enable your organization to properly scope permissions.

Note

HCP Terraform 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 HCP Terraform organization's Teams page, found under Settings > Teams in the HCP Terraform UI.

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

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

Create HCP Terraform team API token

Click on the API tokens option in the left navigation, and then choose the Team Tokens tab.

Click Create a team token. Under Team, choose your learn-tf-preview-env team and choose an Expiration of 30 days. Click Create.

Click Copy token to copy the token string. Save this token in a safe place as HCP Terraform 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 HCP Terraform team API Token. This will let the Terraform CLI use your new team API token and use HCP Terraform.

~/.terraformrc

credentials "app.terraform.io" {
  token = "TOKEN"
}
Create HCP Terraform variable sets

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

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

Note

HCP Terraform 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.

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

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

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
}

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

In terraform.tf, replace hashicorp-training with your HCP Terraform organization name. Terraform will create a new workspace named hcup-be-shared in HCP Terraform 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 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 HCP Terraform...

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)

HCP Terraform has been successfully initialized!

You may now begin working with HCP Terraform. 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 HCP Terraform and filter on hcup- to find your newly created workspace.

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

$ terraform apply
Running apply in HCP Terraform. 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.

Fork the Learn Terraform Preview Environments repository.

Since this repository will use GitHub actions with HCP Terraform 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 HCP Terraform team API token you created in the previous step.

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."

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

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 HCP Terraform 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 HCP Terraform 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 HCP Terraform organization in the next step. The destroy step uses this environment variable to destroy the HCP Terraform 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.

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

  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.

The GitHub Action job defines the following steps:

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

  1. In main.tf, replace hashicorp-training with your HCP Terraform 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 HCP Terraform 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 HCP Terraform 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.

Next, commit your changes.

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

Finally, push your changes.

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

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.

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.

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

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

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

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

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.

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

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

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.

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.

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.

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.

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.

Click on Actions, then on the latest run.

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

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

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

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

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 HCP Terraform and HCP Terraform variable sets.

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


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4