Automating AWS Resource Deployment with GitHub Actions and Terraform
Introduction
In previous articles, we have discussed about Terraform
and explored various DevOps strategies for automating deployments on AWS
.
- How to deploy a serverless website with Terraform
- How to Add CI/CD to my CDK Project
- How to Add CI/CD to my SAM Project
Now, we’ll automate the deployment of Terraform projects using GitHub Actions
. Regardless of what you need to deploy, this approach enables efficient, automated Terraform-based infrastructure deployments.
You can find the repository created for this article here aws-terraform-github-actions-deployment.
This same approach can be used to deploy any AWS resource!
What is GitHub Actions?
GitHub Actions is an automation tool within GitHub that allows you to create workflows triggered by GitHub events, such as pushes or pull requests. It’s commonly used for CI/CD pipelines to automate tasks like testing, building, and deploying applications.
How GitHub Actions works with Terraform
When using GitHub Actions to deploy Terraform resources, the typical workflow involves:
- Triggering workflows based on changes in the repository.
- Setting up AWS credentials using GitHub Secrets.
- Running Terraform commands (e.g.,
terraform plan
,terraform apply
) to manage infrastructure.
Prerequisites
Before getting started, make sure you have:
- AWS Credentials: An IAM user with access keys and permissions to deploy Terraform resources in the AWS Account.
- GitHub Repository: A GitHub repository to store your Terraform configuration.
I’ll use this repository: aws-terraform-github-actions-deployment
- Configure remote backend for Terraform State (Optional): You can use an S3 bucket and DynamoDB table to manage state locking.
- Terraform Installed Locally it’s recommended for testing locally before committing.
Step 1: Prepare the Terraform Code
Create your Terraform code. In this example, we will deploy a simple AWS Budget resource, but you can deploy anything using Terraform.
First, create a main.tf
file with the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
provider "aws" {
region = "eu-west-1"
}
# Customize with your own S3 bucket and DynamoDB table if you want to use a Remote Backend for State
terraform {
backend "s3" {
bucket = "terraform-tfstate-playingaws-poc" # Update it
key = "poc/terraform-github-actions.tfstate" # Update it
region = "eu-west-1" # Update it
dynamodb_table = "terraform-lock" # Update it
encrypt = true
}
}
resource "aws_budgets_budget" "zero_spend_budget" {
name = "ZeroSpendBudget"
budget_type = "COST"
limit_amount = "0.1"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 0
threshold_type = "ABSOLUTE_VALUE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["alcalex@gmail.com"]
}
}
If you don’t include the backend configuration, by default, Terraform state is stored locally in the GitHub runner. This means that in subsequent executions, you could encounter state inconsistencies, so it’s recommended to use a remote backend. {: .prompt-warning }
If you include the backend configuration but you have not created the S3 bucket and the DynamoDB table in the first place, you will receive an error in the pipeline execution.
Feel free to customize the example, as the focus of this article is on the deployment process, not the specific resource.
Step 2: Configure GitHub Actions for Terraform Deployment
Now that we have the Terraform code, let’s set up GitHub Actions
to automate its deployment.
Create the workflow file in your GitHub repository at .github/workflows/terraform-deploy.yml
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
name: Deploy Terraform
on:
push:
branches:
- main
jobs:
terraform:
name: Deploy Terraform Job
runs-on: ubuntu-latest
steps:
# Pulls the latest version of your code from the GitHub repository
- name: Checkout code
uses: actions/checkout@v2
# Installs Terraform on the GitHub runner
- name: Set up Terraform
uses: hashicorp/setup-terraform@v3
# Configures your AWS access by using the credentials stored in GitHub Secrets
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${ { secrets.AWS_ACCESS_KEY_ID } }
aws-secret-access-key: ${ { secrets.AWS_SECRET_ACCESS_KEY } }
aws-region: "eu-west-1"
# Initialize terraform
- name: Initialize Terraform
run: terraform init
# Execute the terraform plan
- name: Terraform Plan
run: terraform plan
# Deploy terraform changes
- name: Terraform Apply
run: terraform apply -auto-approve
# Destroy terraform resources (uncomment lines below)
# - name: Terraform Destroy
# run: terraform destroy -auto-approve
Step 3: Configuring AWS Credentials in GitHub
To allow GitHub Actions to deploy resources in your AWS account, you need to store your AWS credentials in GitHub Secrets.
- Go to your repository’s settings.
- Navigate to Secrets and Variables > Actions.
- Add the following secrets:
This ensures that your AWS credentials are securely available to the GitHub Actions workflow.
While your repository might be public, your AWS credentials remain secure by being stored in the encrypted Secrets section.
GitHub also has built-in
Secrets Detection
to prevent accidental exposure. {: .prompt-warning }
Step 4: Testing the Setup
Push your Terraform code and GitHub Actions configuration to the main branch.
GitHub Actions will trigger automatically, and you can monitor the deployment under the Actions tab of your repository.
If the deployment succeeds, your AWS Budget (or whatever Terraform resource you define) will be applied automatically.
Now, each time you push changes to the repository, the pipeline will be triggered, and if you have no done changes, the pipeline will finish with this message:
Conclusion
By using GitHub Actions
to deploy Terraform resources, you can fully automate your infrastructure management processes
. The combination of Terraform and GitHub Actions creates a powerful CI/CD pipeline, allowing you to deploy infrastructure changes automatically.
Although we used an AWS Budget resource in this example, you can apply the same process to any other AWS resource supported by Terraform.
Next steps
- Manual Approval for terraform apply: Add a manual approval step to review the terraform plan output
- Include Security Tools: Integrate tools like tflint and checkov to lint and check for security issues
- Automate Testing: Use unit testing frameworks like terratest to validate your Terraform code before deployment