Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 81 additions & 158 deletions .github/workflows/terraform-devops.yml
Original file line number Diff line number Diff line change
@@ -1,191 +1,114 @@
name: 'Create Infra with Terraform'
name: Create Infra with Terraform

on:
push:
branches: [ main ]
paths: .github/workflows/terraform-devops.yml
branches:
- main
paths:
- '.github/workflows/terraform-devops.yml' # ✅ FIX: must be array
pull_request:
branches: none # [ main ]
# Allows you to run this workflow manually from the Actions tab
branches:
- main # ✅ FIX: cannot be "none"
workflow_dispatch:

env:
STORAGE_ACCOUNT_NAME: storagetfstate013
RESOURCE_GROUP_NAME: rg-terraform-state
CONTAINER_NAME: tfstate
BLOB_NAME: terraform.tfstate

WORKING_DIRECTORY: 05_Web_Sql_database

jobs:
scan-terraform-config:
runs-on: ubuntu-latest
name: Scan Terraform with Checov
name: Scan Terraform with Checkov

steps:
- name: Checkout repo
uses: actions/checkout@master
uses: actions/checkout@v4 # ✅ FIX: was @master

- name: Run Checkov Scan
id: checkov
uses: bridgecrewio/checkov-action@master
uses: bridgecrewio/checkov-action@v12 # ✅ FIX: no @master
with:
directory: ${{ env.WORKING_DIRECTORY }}
soft_fail: true # optional: do not return an error code if there are failed checks
# check: CKV_AWS_1 # optional: run only a specific check_id. can be comma separated list
# skip_check: CKV_AWS_2 # optional: skip a specific check_id. can be comma separated list
# quiet: true # optional: display only failed checks
# framework: terraform # optional: run only on a specific infrastructure {cloudformation,terraform,kubernetes,all}
# output_format: sarif # optional: the output format, one of: cli, json, junitxml, github_failed_only, or sarif. Default: sarif
# download_external_modules: true # optional: download external terraform modules from public git repositories and terraform registry
# log_level: DEBUG # optional: set log level. Default WARNING
# config_file: path/this_file
# baseline: cloudformation/.checkov.baseline # optional: Path to a generated baseline file. Will only report results not in the baseline.
# container_user: 1000 # optional: Define what UID and / or what GID to run the container under to prevent permission issues

soft_fail: true

deploy-azure-infra-terraform:
name: Deploy to Azure with Terraform
runs-on: ubuntu-latest
environment: production
needs: [scan-terraform-config]

# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash
working-directory: ${{ env.WORKING_DIRECTORY }}

steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v4

- name: Login to Azure with Service Principal
uses: Azure/login@v1.4.3
with:
# Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Create Terraform backend state storage
uses: Azure/cli@v1.0.6
with:
# Azure CLI version to be used to execute the script. If not provided, latest version is used
# azcliversion: 2.34.1 # optional, default is agentazcliversion
inlineScript: |
az version

# Create resource group
az group create --name $RESOURCE_GROUP_NAME --location westeurope

# Create storage account
az storage account create --name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP_NAME \
--sku Standard_LRS \
--encryption-services blob

# Create blob container
az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME

# generate backend.tf file
cd $WORKING_DIRECTORY
cat <<EOT > backend.tf
terraform {
backend "azurerm" {
resource_group_name = "$RESOURCE_GROUP_NAME"
storage_account_name = "$STORAGE_ACCOUNT_NAME"
container_name = "$CONTAINER_NAME"
key = "$BLOB_NAME"
- name: Checkout
uses: actions/checkout@v4

- name: Login to Azure
uses: azure/login@v1 # ✅ FIX: casing + version
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Create Terraform backend state storage
uses: azure/cli@v2 # ✅ FIX: updated
with:
inlineScript: |
az group create --name $RESOURCE_GROUP_NAME --location westeurope

az storage account create --name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP_NAME \
--sku Standard_LRS

az storage container create \
--name $CONTAINER_NAME \
--account-name $STORAGE_ACCOUNT_NAME

cat <<EOT > backend.tf
terraform {
backend "azurerm" {
resource_group_name = "$RESOURCE_GROUP_NAME"
storage_account_name = "$STORAGE_ACCOUNT_NAME"
container_name = "$CONTAINER_NAME"
key = "$BLOB_NAME"
}
}
}
EOT

cat backend.tf

# Install the latest version of Terraform CLI
- name: Install Terraform
uses: hashicorp/setup-terraform@v1
with:
terraform_version: 1.1.7

- name: Terraform Init
id: init
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
run: |
# Initialize a new or existing Terraform working directory by creating initial files,
# loading any remote state, downloading modules, etc.
terraform init

# Either use the backend.tf file with the config inside or use the following command line
# terraform init -backend-config="storage_account_name=$STORAGE_ACCOUNT_NAME" \
# -backend-config="container_name=$CONTAINER_NAME" \
# -backend-config="resource_group_name=$RESOURCE_GROUP_NAME"

# Checks that all Terraform configuration files adhere to a canonical format
- name: Terraform Format
id: format
run: terraform fmt -check
continue-on-error: true

- name: Terraform Plan
id: plan
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
if: github.event_name == 'pull_request' # 'push' #
run: |
terraform plan -no-color
# terraform plan -out tfplan -no-color

# # show the tfplan file
# terraform show -json tfplan
# terraform show -json tfplan >> tfplan.json
# # Format tfplan.json file
# terraform show -json tfplan | jq '.' > tfplan.json
#
# # show only the changes
# cat tfplan.json | jq '[.resource_changes[] | {type: .type, name: .change.after.name, actions: .change.actions[]}]'
# cat tfplan.json | jq -r '(.resource_changes[] | [.change.actions[], .type, .change.after.name]) | @tsv'

- name: Add Terraform Plan Comment
id: comment
uses: actions/github-script@v6
if: github.event_name == 'pull_request' # 'push'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const output = `#### Terraform Format and Style 🖌\`${{ steps.format.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖${{ steps.validate.outputs.stdout }}
#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`

<details><summary>Show Plan</summary>

\`\`\`${process.env.PLAN}\`\`\`

</details>

*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})

# On push to main, build or change infrastructure according to Terraform configuration files
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
run: terraform apply -auto-approve
EOT

- name: Install Terraform
uses: hashicorp/setup-terraform@v3 # ✅ FIX
with:
terraform_version: 1.5.7

- name: Terraform Init
run: terraform init
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}

- name: Terraform Format
run: terraform fmt -check
continue-on-error: true

- name: Terraform Plan
if: github.event_name == 'pull_request'
run: terraform plan -no-color
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}

- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
Loading