Skip to content

Commit 3744604

Browse files
add ci/cd updates
1 parent 526364f commit 3744604

File tree

6 files changed

+137
-3
lines changed

6 files changed

+137
-3
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: Terraform CI/CD
2+
3+
on:
4+
pull_request:
5+
branches: [deploy]
6+
push:
7+
branches: [deploy]
8+
9+
permissions:
10+
id-token: write # Required for Azure OIDC
11+
contents: write # Needed to commit manifest updates
12+
pull-requests: write # Needed to open PRs
13+
14+
env:
15+
TF_VAR_application_name: ${{ vars.APPLICATION_NAME }}
16+
TF_VAR_application_oauth_client_id: ${{ secrets.APPLICATION_OAUTH_CLIENT_ID }}
17+
TF_VAR_application_oauth_client_secret: ${{ secrets.APPLICATION_OAUTH_CLIENT_SECRET }}
18+
TF_VAR_location: ${{ vars.AZURE_LOCATION }}
19+
TF_VAR_execution_mode: ci
20+
ACR_NAME: ${{ vars.ACR_NAME }}
21+
22+
jobs:
23+
terraform:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
# Checkout repo
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
31+
# Install Terraform
32+
- name: Setup Terraform
33+
uses: hashicorp/setup-terraform@v2
34+
with:
35+
terraform_version: 1.10.5
36+
37+
# Temporarily remove repo provider configuration
38+
- name: Disable repo azurerm provider
39+
working-directory: terraform/azure
40+
run: mv providers.tf providers.tf.bak
41+
42+
# Create CI-only backend + OIDC provider
43+
- name: Create CI Azure backend/provider
44+
working-directory: terraform/azure
45+
run: |
46+
cat <<EOF > azure_ci.tf
47+
terraform {
48+
backend "azurerm" {}
49+
}
50+
51+
provider "azurerm" {
52+
features {}
53+
}
54+
EOF
55+
56+
- name: Configure Azure OIDC environment
57+
run: |
58+
echo "ARM_USE_OIDC=true" >> $GITHUB_ENV
59+
echo "ARM_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}" >> $GITHUB_ENV
60+
echo "ARM_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}" >> $GITHUB_ENV
61+
echo "ARM_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}" >> $GITHUB_ENV
62+
63+
- name: Azure Login
64+
uses: azure/login@v1
65+
with:
66+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
67+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
68+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
69+
70+
- name: Login to ACR
71+
run: |
72+
TOKEN=$(az acr login --name ${{ env.ACR_NAME }} --expose-token --output tsv --query accessToken)
73+
docker login -u 00000000-0000-0000-0000-000000000000 --password-stdin ${{ env.ACR_NAME }}.azurecr.io <<< $TOKEN
74+
75+
- name: Terraform Init
76+
working-directory: terraform/azure
77+
run: |
78+
terraform init -upgrade -reconfigure\
79+
-backend-config="resource_group_name=${{ vars.AZURE_RG }}" \
80+
-backend-config="storage_account_name=${{ vars.AZURE_STORAGE_ACCOUNT }}" \
81+
-backend-config="container_name=${{ vars.AZURE_CONTAINER }}" \
82+
-backend-config="key=${{ vars.AZURE_TFSTATE_KEY }}" \
83+
-backend-config="use_oidc=true"
84+
85+
- name: Debug backend values
86+
run: |
87+
terraform state pull | head -20
88+
echo "RG=${{ vars.AZURE_RG }}"
89+
echo "SA=${{ vars.AZURE_STORAGE_ACCOUNT }}"
90+
echo "CONTAINER=${{ vars.AZURE_CONTAINER }}"
91+
echo "KEY=${{ vars.AZURE_TFSTATE_KEY }}"
92+
93+
# Terraform plan (PR only)
94+
- name: Terraform Plan
95+
if: github.event_name == 'pull_request'
96+
working-directory: terraform/azure
97+
run: terraform plan -out=tfplan
98+
99+
# Terraform apply (merge to main only)
100+
- name: Terraform Apply
101+
if: github.event_name == 'push'
102+
working-directory: terraform/azure
103+
run: |
104+
terraform plan -out=tfplan
105+
terraform apply -auto-approve tfplan
106+
107+
# Cleanup CI-only files
108+
- name: Cleanup CI Terraform files
109+
working-directory: terraform/azure
110+
run: |
111+
rm -f azure_ci.tf
112+
mv providers.tf.bak providers.tf

terraform/azure/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module "manifest" {
6161
"${basename(dirname(var.manifest_files_paths[count.index]))}.${basename(var.manifest_files_paths[count.index])}"
6262
])
6363

64+
execution_mode = var.execution_mode
6465
client_id = local.application_oauth_client_id
6566
client_secret = local.application_oauth_client_secret
6667
base_url = local.application_service_url

terraform/azure/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,9 @@ variable "tags" {
276276
description = "A map of the tags to apply to various resources"
277277
default = {}
278278
}
279+
280+
variable "execution_mode" {
281+
description = "Execution mode: 'local' or 'ci'"
282+
type = string
283+
default = "local"
284+
}

terraform/common/modules/template/main.tf

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ locals {
2525
]...
2626
)
2727
])
28-
29-
output_file_path = nonsensitive(local_sensitive_file.this.filename != "/dev/null" ? local_sensitive_file.this.filename : "")
3028
}
3129

3230
resource "local_sensitive_file" "this" {
31+
count = var.execution_mode == "local" ? 1 : 0
3332
content = local.output_file_content
3433
filename = local.enabled ? var.output_file_path : "/dev/null"
3534
}
35+
36+
output "manifest_file_path" {
37+
description = "The intended output file path"
38+
value = var.output_file_path
39+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
output "output_file_path" {
22
description = "The absolute path to the output file"
3-
value = local.output_file_path
3+
value = var.output_file_path
44
}

terraform/common/modules/template/variables.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
variable "execution_mode" {
2+
description = "Controls whether Terraform writes manifests to disk (local) or only renders them (ci)"
3+
type = string
4+
default = "local"
5+
6+
validation {
7+
condition = contains(["local", "ci"], var.execution_mode)
8+
error_message = "execution_mode must be 'local' or 'ci'."
9+
}
10+
}
11+
112
variable "input_file_path" {
213
description = "The absolute path to the input file. If it doesn't exist, the module will not do anything"
314
type = string

0 commit comments

Comments
 (0)