diff --git a/.github/workflows/terraform-devops.yml b/.github/workflows/terraform-devops.yml index e086086..242b0a9 100644 --- a/.github/workflows/terraform-devops.yml +++ b/.github/workflows/terraform-devops.yml @@ -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 < 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 < 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 }}\` - -
Show Plan - - \`\`\`${process.env.PLAN}\`\`\` - -
- - *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 }}