Skip to content

Initial commit: Azure Modern Data Platform with Microsoft Fabric #1

Initial commit: Azure Modern Data Platform with Microsoft Fabric

Initial commit: Azure Modern Data Platform with Microsoft Fabric #1

name: Deploy Infrastructure
on:
push:
branches:
- main
paths:
- 'infrastructure/**'
- '.github/workflows/deploy-infrastructure.yml'
pull_request:
branches:
- main
paths:
- 'infrastructure/**'
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy'
required: true
type: choice
options:
- dev
- test
- prod
action:
description: 'Terraform action to perform'
required: true
type: choice
options:
- plan
- apply
- destroy
env:
TERRAFORM_VERSION: '1.5.7'
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
jobs:
terraform-checks:
name: Terraform Validation
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Terraform Format Check
run: |
cd infrastructure/terraform
terraform fmt -check -recursive
- name: Terraform Init
run: |
cd infrastructure/terraform
terraform init -backend=false
- name: Terraform Validate
run: |
cd infrastructure/terraform
terraform validate
- name: TFLint
uses: terraform-linters/setup-tflint@v3
with:
tflint_version: latest
- name: Run TFLint
run: |
cd infrastructure/terraform
tflint --init
tflint
- name: Checkov Security Scan
uses: bridgecrewio/checkov-action@master
with:
directory: infrastructure/terraform
framework: terraform
output_format: sarif
output_file_path: checkov.sarif
- name: Upload Checkov results
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: checkov.sarif
terraform-plan:
name: Terraform Plan - ${{ matrix.environment }}
needs: terraform-checks
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'plan')
strategy:
matrix:
environment: [dev, test, prod]
environment:
name: ${{ matrix.environment }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Terraform Init
run: |
cd infrastructure/terraform
terraform init
- name: Terraform Plan
run: |
cd infrastructure/terraform
terraform plan \
-var-file=environments/${{ matrix.environment }}.tfvars \
-out=${{ matrix.environment }}.tfplan
- name: Upload Plan
uses: actions/upload-artifact@v3
with:
name: terraform-plan-${{ matrix.environment }}
path: infrastructure/terraform/${{ matrix.environment }}.tfplan
- name: Comment PR with Plan
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
with:
script: |
const output = `#### Terraform Plan - ${{ matrix.environment }} 📋
<details><summary>Show Plan</summary>
\`\`\`terraform
${{ steps.plan.outputs.stdout }}
\`\`\`
</details>
*Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
terraform-apply-dev:
name: Deploy to Development
needs: terraform-checks
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment:
name: dev
url: https://app.fabric.microsoft.com
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Terraform Init
run: |
cd infrastructure/terraform
terraform init
- name: Terraform Apply
run: |
cd infrastructure/terraform
terraform apply \
-var-file=environments/dev.tfvars \
-auto-approve
- name: Export Outputs
id: outputs
run: |
cd infrastructure/terraform
echo "fabric_url=$(terraform output -raw fabric_workspace_urls)" >> $GITHUB_OUTPUT
echo "api_url=$(terraform output -raw api_gateway_url)" >> $GITHUB_OUTPUT
- name: Update Deployment Status
uses: actions/github-script@v6
with:
script: |
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: context.payload.deployment.id,
state: 'success',
environment_url: '${{ steps.outputs.outputs.fabric_url }}',
description: 'Deployment successful'
});
terraform-apply-prod:
name: Deploy to Production
needs: terraform-checks
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'prod' && github.event.inputs.action == 'apply'
environment:
name: prod
url: https://app.fabric.microsoft.com
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Create Backup
run: |
# Backup current state before applying changes
az storage blob download \
--account-name tfstateplatform \
--container-name tfstate \
--name fabric-platform.tfstate \
--file fabric-platform-backup-$(date +%Y%m%d-%H%M%S).tfstate
- name: Terraform Init
run: |
cd infrastructure/terraform
terraform init
- name: Terraform Plan
run: |
cd infrastructure/terraform
terraform plan \
-var-file=environments/prod.tfvars \
-out=prod.tfplan
- name: Manual Approval Check
uses: trstringer/manual-approval@v1
with:
secret: ${{ github.TOKEN }}
approvers: platform-admins
minimum-approvals: 2
issue-title: "Production Deployment Approval Required"
issue-body: "Please review and approve the production deployment"
- name: Terraform Apply
run: |
cd infrastructure/terraform
terraform apply prod.tfplan
- name: Smoke Tests
run: |
# Run smoke tests to verify deployment
./scripts/smoke-tests.sh prod
- name: Notify Teams
if: always()
uses: jdcargile/ms-teams-notification@v1.3
with:
github-token: ${{ github.token }}
ms-teams-webhook-uri: ${{ secrets.TEAMS_WEBHOOK }}
notification-summary: "Production Deployment ${{ job.status }}"
notification-color: ${{ job.status == 'success' && '00FF00' || 'FF0000' }}
terraform-destroy:
name: Destroy Infrastructure
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'destroy'
environment:
name: ${{ github.event.inputs.environment }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Manual Approval for Destroy
uses: trstringer/manual-approval@v1
with:
secret: ${{ github.TOKEN }}
approvers: platform-admins
minimum-approvals: 2
issue-title: "Destroy Approval Required for ${{ github.event.inputs.environment }}"
issue-body: "Please confirm destruction of ${{ github.event.inputs.environment }} infrastructure"
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Terraform Init
run: |
cd infrastructure/terraform
terraform init
- name: Terraform Destroy
run: |
cd infrastructure/terraform
terraform destroy \
-var-file=environments/${{ github.event.inputs.environment }}.tfvars \
-auto-approve
cost-estimation:
name: Cost Estimation
needs: terraform-checks
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Infracost
uses: infracost/setup-infracost@v2
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Generate Infracost Report
run: |
cd infrastructure/terraform
infracost breakdown \
--path . \
--terraform-var-file environments/prod.tfvars \
--format json \
--out-file /tmp/infracost.json
- name: Post Infracost comment
uses: infracost/actions/comment@v1
with:
path: /tmp/infracost.json
behavior: update