Skip to content

Commit f3115ed

Browse files
authored
feat(iac): migrate to terraform (#61)
1 parent 4ec8a51 commit f3115ed

10 files changed

Lines changed: 415 additions & 293 deletions

File tree

.github/workflows/bicep.yml

Lines changed: 0 additions & 107 deletions
This file was deleted.

.github/workflows/terraform.yml

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
name: Terraform CI/CD
2+
3+
on:
4+
push:
5+
branches: ['main']
6+
paths:
7+
- 'infra/**'
8+
- '.github/workflows/terraform.yml'
9+
pull_request:
10+
types: [opened, synchronize, reopened]
11+
branches: ['main']
12+
paths:
13+
- 'infra/**'
14+
- '.github/workflows/terraform.yml'
15+
16+
permissions:
17+
contents: read
18+
pull-requests: write
19+
id-token: write
20+
21+
env:
22+
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
23+
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
24+
ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
25+
ARM_USE_AZUREAD: true
26+
ARM_USE_OIDC: true
27+
28+
jobs:
29+
plan:
30+
if: github.event_name == 'push' || github.event_name == 'pull_request'
31+
runs-on: ubuntu-latest
32+
name: Plan
33+
environment: production
34+
outputs:
35+
exitcode: ${{ steps.plan.outputs.exitcode }}
36+
37+
concurrency:
38+
group: ${{ github.workflow }}
39+
cancel-in-progress: false
40+
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@v5
44+
45+
- name: Set up Terraform
46+
uses: hashicorp/setup-terraform@v3
47+
with:
48+
terraform_wrapper: false
49+
50+
- name: Login to Azure
51+
uses: azure/login@v2
52+
with:
53+
client-id: ${{ env.ARM_CLIENT_ID }}
54+
subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
55+
tenant-id: ${{ env.ARM_TENANT_ID }}
56+
57+
- name: Initialize configuration
58+
run: terraform -chdir=infra init -input=false
59+
60+
- name: Verify formatting
61+
run: terraform -chdir=infra fmt -check -recursive
62+
63+
- name: Validate configuration
64+
run: terraform -chdir=infra validate
65+
66+
- name: Build plan
67+
id: plan
68+
run: |
69+
export exitcode=0
70+
terraform -chdir=infra plan -detailed-exitcode -out=tfplan || export exitcode=$?
71+
72+
echo "exitcode=$exitcode" >> $GITHUB_OUTPUT
73+
74+
if [ $exitcode -eq 1 ]; then
75+
exit 1
76+
else
77+
exit 0
78+
fi
79+
80+
- name: Publish plan
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: tfplan-${{ github.run_id }}
84+
path: infra/tfplan
85+
86+
- name: Build summary
87+
id: build-summary
88+
run: |
89+
TF_PLAN=$(terraform -chdir=infra show -no-color tfplan)
90+
91+
delimiter="$(openssl rand -hex 8)"
92+
echo "summary<<${delimiter}" >> $GITHUB_OUTPUT
93+
echo "## Terraform Plan" >> $GITHUB_OUTPUT
94+
echo "<details><summary>Click to expand</summary>" >> $GITHUB_OUTPUT
95+
echo "" >> $GITHUB_OUTPUT
96+
echo '```terraform' >> $GITHUB_OUTPUT
97+
echo "$TF_PLAN" >> $GITHUB_OUTPUT
98+
echo '```' >> $GITHUB_OUTPUT
99+
echo "</details>" >> $GITHUB_OUTPUT
100+
echo "${delimiter}" >> $GITHUB_OUTPUT
101+
102+
- name: Publish summary
103+
env:
104+
SUMMARY: ${{ steps.build-summary.outputs.summary }}
105+
run: echo "$SUMMARY" >> $GITHUB_STEP_SUMMARY
106+
107+
- name: Push summary to PR
108+
if: github.event_name == 'pull_request'
109+
uses: actions/github-script@v7
110+
env:
111+
SUMMARY: "${{ steps.build-summary.outputs.summary }}"
112+
with:
113+
github-token: ${{ secrets.GITHUB_TOKEN }}
114+
script: |
115+
const body = `${process.env.SUMMARY}`;
116+
github.rest.issues.createComment({
117+
issue_number: context.issue.number,
118+
owner: context.repo.owner,
119+
repo: context.repo.repo,
120+
body: body
121+
})
122+
123+
apply:
124+
needs: plan
125+
if: github.event_name == 'push' && needs.plan.outputs.exitcode == 2
126+
runs-on: ubuntu-latest
127+
name: Apply
128+
environment: production
129+
130+
concurrency:
131+
group: ${{ github.workflow }}
132+
cancel-in-progress: false
133+
134+
steps:
135+
- name: Checkout repository
136+
uses: actions/checkout@v5
137+
138+
- name: Set up Terraform
139+
uses: hashicorp/setup-terraform@v3
140+
with:
141+
terraform_wrapper: false
142+
143+
- name: Login to Azure
144+
uses: azure/login@v2
145+
with:
146+
client-id: ${{ env.ARM_CLIENT_ID }}
147+
subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
148+
tenant-id: ${{ env.ARM_TENANT_ID }}
149+
150+
- name: Initialize configuration
151+
run: terraform -chdir=infra init -input=false
152+
153+
- name: Download plan
154+
uses: actions/download-artifact@v4
155+
with:
156+
name: tfplan-${{ github.run_id }}
157+
path: infra
158+
159+
- name: Apply plan
160+
run: terraform -chdir=infra apply -auto-approve tfplan

.gitignore

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,54 @@ FodyWeavers.xsd
398398

399399
# JetBrains Rider
400400
*.sln.iml
401+
402+
## Ignore Terraform temporary files, plan output, state files,
403+
## and other sensitive files for local development.
404+
##
405+
## Get latest from https://github.com/github/gitignore/blob/main/Terraform.gitignore
406+
407+
# Local .terraform directories
408+
.terraform/
409+
410+
# .tfstate files
411+
*.tfstate
412+
*.tfstate.*
413+
414+
# Crash log files
415+
crash.log
416+
crash.*.log
417+
418+
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
419+
# password, private keys, and other secrets. These should not be part of version
420+
# control as they are data points which are potentially sensitive and subject
421+
# to change depending on the environment.
422+
*.tfvars
423+
*.tfvars.json
424+
425+
# Ignore override files as they are usually used to override resources locally and so
426+
# are not checked in
427+
override.tf
428+
override.tf.json
429+
*_override.tf
430+
*_override.tf.json
431+
432+
# Ignore transient lock info files created by terraform apply
433+
.terraform.tfstate.lock.info
434+
435+
# Include override files you do wish to add to version control using negated pattern
436+
# !example_override.tf
437+
438+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
439+
# example: *tfplan*
440+
*tfplan*
441+
442+
# Ignore CLI configuration files
443+
.terraformrc
444+
terraform.rc
445+
446+
# Optional: ignore graph output files generated by `terraform graph`
447+
# *.dot
448+
449+
# Optional: ignore plan files saved before destroying Terraform configuration
450+
# Uncomment the line below if you want to ignore planout files.
451+
# planout

infra/.terraform.lock.hcl

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)