Continuously Validating Automation Scenarios with Terraform Test and GitHub Actions
I am speaking to all the Azure PMs out there. If you are responsible for an Azure Service, please take heed. Our customers are developers and operators of applications, workloads and platforms that are built on top of your Azure Service. They need to be able to use Infrastructure-as-Code not only to provision stuff to Azure but to manage it long term. If you want our customers to do more than kick the tires with your service for a few weeks in the portal than you better start paying more attention to Automation Scenarios — and fast!
Third-party Azure customers investing in your Azure Service need confidence that it will work consistently across expected and supported usage scenarios. By continuously validating key configuration scenarios with automated Terraform tests, you ensure that customers see a reliable, well-tested foundation worth their time and integration efforts.
I created a GitHub Action and Terraform Test template to fulfill this need by running automated, end-to-end Terraform tests against Azure Functions deployment scenarios.
This workflow validates common usage scenarios that Azure Functions customers care about, while also demonstrating that different configuration variants are supported and functional. By running this workflow continuously, we can transform a repository where we dump slowly atrophying code into a living demonstration of stability, reducing friction for Azure customers evaluating our offerings and looking to automate them using Terraform.
To support this, the workflow triggers not only on changes but also on a regular schedule, ensuring these scenarios are executed frequently, even when the code is not actively modified, catching environmental or dependency drift early.
on:
push:
paths:
- "src/terraform/flex-baseline/**"
pull_request:
paths:
- "src/terraform/flex-baseline/**"
workflow_dispatch:
schedule:
- cron: "0 3 * * *" # runs daily at 3 AM UTC to continuously validate baseline
We do a pretty narrow targeting of a single usage scenario — in this case Azure Functions with a Flex Consumption hosting option that uses Azure Storage Connection string to authenticate with Azure Blob Storage — not ideal from a security standpoint — but it works.
The workflow begins by building your Azure Functions app using .NET 8 in a clean environment, ensuring that any changes in your app do not break your deployment assumptions. It checks out your repository, sets up the .NET SDK, restores dependencies, builds and publishes the app, and packages it into a deployable zip artifact.
jobs:
build-dotnet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.x
- run: dotnet restore ./src/dotnet/8.0/FunctionApp1/FunctionApp1.sln
- run: dotnet build ./src/dotnet/8.0/FunctionApp1/FunctionApp1.sln --configuration Release
- run: dotnet publish ./src/dotnet/8.0/FunctionApp1/FunctionApp1/FunctionApp1.csproj --configuration Release --output ./publish
- run: zip -r dotnet-deployment.zip ./publish
- uses: actions/upload-artifact@v4
with:
name: dotnet-deployment
path: dotnet-deployment.zip
Once the application is packaged, the pipeline moves to infrastructure validation. It securely logs into Azure using OIDC to avoid hardcoded secrets while enabling secure, automated testing. Terraform is initialized, and your targeted Terraform tests are executed to confirm the Flex Consumption Plan baseline infrastructure behaves as intended under end-to-end scenarios that mirror customer usage.
terraform-test:
needs: [build-dotnet]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: azure/login@v2
with:
client-id: $
tenant-id: $
subscription-id: $
- uses: actions/download-artifact@v4
with:
name: dotnet-deployment
path: ./
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.12.x
- run: |
terraform init
terraform test -verbose -filter=tests/flex-baseline.tftest.hcl
By running these tests daily — or monthly, we can verify that our Terraform configuration for the Azure Functions Flex Consumption remains functional, regardless of upstream changes in Azure or Terraform dependencies. This continuous validation builds trust with your third-party customers, demonstrating that your code is actively maintained and production-ready.
More importantly, this approach shows customers that your infrastructure modules support different configuration variants reliably, allowing them to experiment and adopt different patterns with confidence. When customers see these tests passing consistently, it reassures them that their investment in your Azure Service will pay off, reducing their risk and accelerating their adoption.
Using this GitHub Action, you turn your repository into a living, continuously validated baseline for Azure Functions or whatever Azure Service you are responsible for, ensuring your customers experience stability, clarity, and confidence as they build on top of your work.