How to Terraform AWS via PR Comments (And You Can DIY!*)
Tags: githubhack23, terraform, devops, opensource
Published: 2023-05-22 19:40:18

## What I Built

For **#GitHubHack23**, I'm happy to share a reusable workflow that enables you to plan and apply changes to Terraform with PR comments: for a CLI-like experience on the web.

It's powered by GitHub Actions to maximize compatibility and minimize maintenance for **DIY deployments** of infrastructure as code (IaC). Includes tailored support for Codespaces to simplify remote development access.

Best suited for DevOps and Platform engineers who want to **empower their teams** to self-service Terraform without the overhead of self-hosting runners, containers or VMs.

### Category Submission

DIY Deployments: This reusable workflow leverages a combination of GitHub Actions and custom scripts. It automates continuous integration and continuous deployment (CI/CD) pipelines to **promote collaboration** over Terraform configuration changes in a remote environment.

### App Link

\*[Terraform with Comments — Reusable Workflow](https://github.com/devsectop/tf-via-pr/blob/main/.github/workflows/tf.yml).

To use this workflow, copy the following snippet into ".github/workflows/terraform.yml" file in your repository. Replace the contents of `env_vars` with environment variables required by your Terraform configuration (e.g., `AWS` credentials or `TF_VAR` variables).

```yml
on:
  issue_comment:
    types: [created, edited]
  pull_request:
    types: [synchronize]

jobs:
  terraform:
    uses: devsectop/tf-via-pr/.github/workflows/tf.yml@main
    secrets:
      env_vars: |
        AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}
```

- The `@main` suffix can be replaced with a specific release tag/SHA to pin your workflow to that version: hardening your CI/CD **pipeline security**.
- The optional `env_vars` input lets you pass in environment variables as key-value pairs while masking sensitive values from logs.

### Screenshots

[![Workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h74ms7wysdezwp4055qo.gif)](https://github.com/rdhar/terraform-with-comments/assets/19497993/48de830a-1cfb-4278-9ca3-be39ad2f7cb8)

### Description

The following example demonstrates the PR comments required to provision resources in multiple workspaces with different input variables, followed by targeted destruction.

```bash
#1 PR Comment: Plan configuration in a workspace with input variable file.
-terraform=plan -chdir=stacks/sample_instance -workspace=dev -var-file=env/dev.tfvars

#2 PR Comment: Apply configuration in a workspace with input variable file.
-terraform=apply -chdir=stacks/sample_instance -workspace=dev -var-file=env/dev.tfvars

#3 PR Comment: Plan destruction of a targeted resource in a workspace with input variable file.
-terraform=plan -destroy -target=aws_instance.sample -chdir=stacks/sample_instance -workspace=dev -var-file=env/dev.tfvars

#4 PR Comment: Apply destruction of a targeted resource in a workspace with input variable file.
-terraform=apply -destroy -target=aws_instance.sample -chdir=stacks/sample_instance -workspace=dev -var-file=env/dev.tfvars
```

The following CLI arguments are supported simultaneously, supplied in any order:

- `auto-approve`: Flag to skip confirmation before applying the plan.
- `backend-config`: Path to backend configuration file(s).
- `chdir`: Path to a directory containing Terraform configuration files.
- `destroy`: Flag to destroy resources managed by Terraform.
- `parallelism`: Number of concurrent operations to run.
- `replace`: List of resource addresses to replace.
- `target`: List of resource addresses to target.
- `var-file`: Path to variable file(s).
- `workspace`: Name of Terraform workspace to select.

### Link to Source Code

{% github devsectop/tf-via-pr %}

### Permissive License

[Apache License 2.0](https://github.com/devsectop/tf-via-pr/blob/main/LICENSE).

## Background

While designing AWS architecture solutions, I needed a way to automate Terraform provisioning across multiple environments with GitOps. This would promote team-wide collaboration over infrastructure changes, which is located in the same place where code lives: GitHub. In the same vein, [dev container](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers) implementation offers a **tailored development environment** in a virtual codespace, complete with: tools, extensions and runtimes.

I was inspired by [Atlantis](https://www.runatlantis.io)'s approach to Terraform PR automation. However, I wanted to avoid the overhead of self-hosting and securing a VM for each project. Instead, I preferred to re-use GitHub's CI/CD platform as it is **scalable and compatible** with various repositories, lowering the barrier to entry.

### How I Built It

1. I learned about the differences between [reusable workflows and composite actions](https://github.blog/2022-02-10-using-reusable-workflows-github-actions/). Thus, I opted for a reusable workflow as it allows more **granular control** over workflow execution: from managing `concurrency` of queued workflows to running jobs in parallel with `strategy.matrix`.

1. I wrote a [custom script](https://github.com/devsectop/tf-via-pr/blob/main/.github/workflows/tf.yml#L31-L49) to parse PR comments as input commands to interface with Terraform CLI, returning the output as bot comments. Each step of the workflow relies on GitHub Actions, including [actions/github-script](https://github.com/actions/github-script) to interact with GitHub's API (while brushing up on my JavaScript!).

1. I discovered a [novel method](https://github.com/devsectop/tf-via-pr/blob/main/.github/workflows/tf.yml#L88-L95) to pass any number of environment variables to the reusable workflow as secrets. This prevents sensitive values from being exposed in the logs, while enabling you to **customize the workflow** to your Terraform configuration.

### Additional Resources/Info

When working with GitHub Actions, I'm often reminded of this quotation:

> "If I have seen further, it is by standing upon the shoulders of giants."
>
> _— Sir Isaac Newton_

This rings true for my experience with the open-source community that has enabled me to build this reusable workflow. I hope it will help you to **build your own solutions**, too!

---

All forms of contribution are very welcome and deeply appreciated for fostering open-source software.

- Please [create a PR](https://github.com/devsectop/tf-via-pr/pulls) to contribute changes you'd like to see.
- Please [raise an issue](https://github.com/devsectop/tf-via-pr/issues) to discuss proposed changes or report unexpected behavior.
- Please [open a discussion](https://github.com/devsectop/tf-via-pr/discussions) to share ideas about where you'd like to see this project go.
- Please [consider becoming a stargazer](https://github.com/devsectop/tf-via-pr/stargazers) if you find this project useful.