How to Automate Parallel Test Environments with Terraform and GitHub Actions


Recently, someone on LinkedIn came to me with a question. They wanted to spin up parallel environments of their product running in production for release testing. At any given time, there could be up to five parallel environments running at once, so this setup goes beyond a typical staging environment, and blue-green deployments wouldn’t quite fit their needs. Here is a potential solution I proposed.

They are using GitHub Actions and Terraform, so we could trigger an automated script to spin up a parallel environment when a branch is created and tear it down when the branch is deleted. For example, when the branch env/1.2.3 is created, we could spin up the environment and create a DNS record like 1-2-3.example.com that points to it. Similarly, when we delete the branch env/1.2.3, we could trigger GitHub Actions to destroy that workspace.

How would we accomplish this? By creating unique Terraform workspaces.

Alternatively, you could do this as a module inside your main Terraform workspace, but that would require manually updating your main Terraform configuration and risk impacting your core infrastructure. If it's set up as a separate workspace, you could easily have a script create a brand-new workspace that references existing resources via a Terraform “data” block.

What would the module contain? Here’s the basic flow (sorry, I don’t have a fancy graphic at this moment):

Route53 -> ALB Listener -> Target Group -> ECS Service -> Task Definition

Originally, my LinkedIn contact mentioned spinning up a single task, but that approach is slightly tougher. If you booted the task in a public VPC, you could point Route53 at the task’s IP, but if the task dies because of a bug, the whole setup breaks. There’s nothing in GitHub Actions to monitor the task’s health and restart it.

If we use an ECS Service with an ALB/Target Group, however, it will automatically boot up another task and route traffic to it. Since we are charged per task rather than per service, it’s better to use Terraform to provision an ECS service.

We do get charged hourly for each ALB, but we only need one ALB with multiple listeners. In this scenario, the root Terraform workspace would create the ALB, and each parallel environment workspace would reference that ALB via a data block.

You would still need to build and tag the ECR image, but that doesn’t require a Terraform resource. I assume that since they are already using ECR, they have an existing process for building and tagging images that could be adapted for specific build versions.

I hope this helps anyone facing a similar problem. If you have any questions, please don’t hesitate to reach out.

This version focuses on making the explanation flow more clearly and removing minor redundancies or typos. Let me know if you have any other preferences!