DEV Community

Mary Mutua
Mary Mutua

Posted on

A Workflow for Deploying Application Code with Terraform

Day 20 of my Terraform journey focused on one practical question from Chapter 10 of Terraform: Up & Running by Yevgeniy Brikman:

How do we apply the same trusted release workflow used for application code to infrastructure code?

I walked through the full 7-step workflow using my Day 20 webserver cluster update, from local change to PR to deploy and cleanup.

Why this matters

Most teams already trust an app-code workflow:

  • branch
  • review
  • tests
  • merge
  • release
  • deploy

Terraform should follow the same discipline.

The big difference is that infrastructure changes can create, modify, or destroy real cloud resources, so review and execution controls matter even more.


Step 1: Use version control

I kept all Terraform code in Git and worked through a feature branch instead of changing main directly.

Example branch:

git checkout -b update-app-version-day20
Enter fullscreen mode Exit fullscreen mode

Goal: every infrastructure change is traceable, reviewable, and reversible.


Step 2: Run locally first

I made a small, intentional app change in Terraform by updating the user-facing response text from:

  • Hello from Day 20 v2 to
  • Hello from Day 20 v3

Then I generated a reviewed plan:

terraform -chdir=day_20/live/dev validate
terraform -chdir=day_20/live/dev plan -out=day20.tfplan
Enter fullscreen mode Exit fullscreen mode

Result:

  • validate passed
  • plan file saved (day20.tfplan)
  • summary showed expected create actions only (15 to add, 0 to change, 0 to destroy)

Key habit: do not apply unreviewed changes.


Step 3: Make and commit the change

After confirming the local plan, I committed on the feature branch and pushed for review.

git add .
git commit -m "Day 20: update app response to v3 and simulate deployment workflow"
git push origin update-app-version-day20
Enter fullscreen mode Exit fullscreen mode

Step 4: Submit for review (PR)

In the PR, I included the rendered plan output so reviewers could see exactly what Terraform would do before merge.

terraform -chdir=day_20/live/dev show -no-color day20.tfplan
Enter fullscreen mode Exit fullscreen mode

This is the infrastructure equivalent of reviewing a code diff, but with cloud-impact context.


Step 5: Run automated tests

For this workflow, unit tests ran via GitHub Actions on PR, and passed.

I also ran local module unit tests:

terraform -chdir=day_20/modules/services/webserver-cluster test
Enter fullscreen mode Exit fullscreen mode

Result:

  • 4 passed, 0 failed

Important note: native terraform test can live next to the module in .tftest.hcl.

You do not need a separate test/ folder for this layer.


Step 6: Merge and release

After checks passed, the PR merged into main.

Release tagging is the same idea as app releases:

git tag -a "v1.3.0" -m "Update app response to v3"
git push origin v1.3.0
Enter fullscreen mode Exit fullscreen mode

Tags make rollout points explicit and easier to audit.


Step 7: Deploy and verify

I applied the reviewed plan and verified the live result.

terraform -chdir=day_20/live/dev apply day20.tfplan
curl -s http://$(terraform -chdir=day_20/live/dev output -raw alb_dns_name)
Enter fullscreen mode Exit fullscreen mode

Live response:
Hello from Day 20 v3

Then I destroyed resources and verified cleanup to avoid cost leaks.


Where app and infra workflows align

Both workflows use:

  • Git branches
  • PR review
  • automated checks
  • merge + release tags
  • controlled deployment

This alignment is what makes Terraform adoption easier in teams.

Where they diverge

Infrastructure adds constraints app workflows usually do not have:

  1. State management

    Terraform state is critical and must be protected (not committed to Git).

  2. Plan-as-review artifact

    Reviewing .tf alone is not enough. Reviewers need plan output.

  3. Real cloud blast radius

    Tests and applies can create paid resources and cause outages if unmanaged.

  4. Trusted apply environment

    terraform apply should run from controlled environments with locking and auditability.


Terraform Cloud variable management: the hidden win

One of the most useful lessons is variable security in Terraform Cloud.

Instead of credentials on laptops, store:

  • AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as sensitive environment variables
  • Terraform inputs (cluster_name, instance_type, environment) as workspace variables

This gives:

  • safer secret handling
  • consistent runs
  • better audit trails
  • less โ€œworks on my machineโ€ behavior

Terraform Cloud private registry: another underrated feature

Many teams miss this.

By publishing internal modules (for example terraform-aws-webserver-cluster) to Terraform Cloud private registry, you get:

  • versioned internal modules
  • central documentation
  • consistent reuse across teams
  • cleaner source references

Example module source pattern:

source  = "app.terraform.io/<org>/webserver-cluster/aws"
version = "1.0.0"
Enter fullscreen mode Exit fullscreen mode

This is a big step from one-off copy-paste module usage to real platform engineering.


Final takeaway

Terraform works best when it follows the same release discipline as application code.

The 7-step workflow is not just process overhead. It is what makes infrastructure safer, reviewable, and team-friendly at scale.

Day 20 made that practical for me: plan-first review, automated checks, controlled merge, verified deploy, and explicit cleanup.


Code Reference

GitHub (Day 20):
๐Ÿ‘‰ Github Link


Follow My Journey

This is Day 20 of my 30-Day Terraform Challenge.

See you on Day 21 ๐Ÿš€

Top comments (0)