Redeploy site #216
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Terraform CI/CD | |
| on: | |
| push: | |
| branches: [ master ] | |
| pull_request: | |
| branches: [ master ] | |
| permissions: | |
| contents: read | |
| id-token: write | |
| 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 }} | |
| jobs: | |
| terraform: | |
| name: Terraform | |
| runs-on: ubuntu-latest | |
| environment: qa | |
| steps: | |
| - name: 📦 Checkout code | |
| uses: actions/checkout@v3 | |
| - name: ⚙️ Setup Terraform | |
| uses: hashicorp/setup-terraform@v2 | |
| with: | |
| terraform_version: 1.5.0 | |
| - name: 🔐 Azure Login with Service Principal | |
| uses: azure/login@v1 | |
| with: | |
| creds: >- | |
| { | |
| "clientId": "${{ secrets.ARM_CLIENT_ID }}", | |
| "clientSecret": "${{ secrets.ARM_CLIENT_SECRET }}", | |
| "subscriptionId": "${{ secrets.ARM_SUBSCRIPTION_ID }}", | |
| "tenantId": "${{ secrets.ARM_TENANT_ID }}" | |
| } | |
| - name: 🧪 Verify Azure login | |
| run: az account show | |
| - name: 🏗️ Ensure Terraform remote backend exists | |
| run: | | |
| az group create --name soft-tfstate-rg --location eastus | |
| az storage account create \ | |
| --name softsastate \ | |
| --resource-group soft-tfstate-rg \ | |
| --location eastus \ | |
| --sku Standard_LRS \ | |
| --encryption-services blob | |
| az storage container create \ | |
| --name tfstate \ | |
| --account-name softsastate | |
| - name: 📥 Terraform Init | |
| run: | | |
| terraform -chdir=infra init \ | |
| -backend-config="resource_group_name=soft-tfstate-rg" \ | |
| -backend-config="storage_account_name=softsastate" \ | |
| -backend-config="container_name=tfstate" \ | |
| -backend-config="key=terraform.tfstate" | |
| - name: 🧹 Optional Unlock (if lock is active) | |
| run: | | |
| terraform -chdir=infra init | |
| LOCK_FILE=".terraform/terraform.tfstate.lock.info" | |
| if [ -f "infra/$LOCK_FILE" ]; then | |
| LOCK_ID=$(jq -r '.ID' "infra/$LOCK_FILE") | |
| echo "🔓 Lock found: $LOCK_ID. Attempting to unlock..." | |
| terraform -chdir=infra force-unlock -force "$LOCK_ID" | |
| else | |
| echo "✅ No lock file found. Continuing..." | |
| fi | |
| - name: 🧹 Terraform Format | |
| run: | | |
| terraform -chdir=infra fmt -check -diff -recursive -no-color || true | |
| - name: 📝 Generate terraform.tfvars | |
| run: | | |
| cat > infra/terraform.tfvars <<EOF | |
| subscription_id = "${{ secrets.ARM_SUBSCRIPTION_ID }}" | |
| client_id = "${{ secrets.ARM_CLIENT_ID }}" | |
| client_secret = "${{ secrets.ARM_CLIENT_SECRET }}" | |
| tenant_id = "${{ secrets.ARM_TENANT_ID }}" | |
| allowed_ssh_ip = "${{ secrets.MY_IP_ADDRESS }}" | |
| mysql_user = "${{ secrets.MYSQL_USER }}" | |
| mysql_admin_password = "${{ secrets.MYSQL_ADMIN_PASSWORD }}" | |
| ssh_public_key = "${{ secrets.VM_SSH_PUB_KEY }}" | |
| EOF | |
| - name: 🔍 Terraform Validate | |
| run: terraform -chdir=infra validate | |
| - name: 📋 Terraform Plan | |
| run: terraform -chdir=infra plan -input=false -var-file=terraform.tfvars | |
| - name: 🚀 Terraform Apply | |
| if: github.ref == 'refs/heads/master' | |
| run: terraform -chdir=infra apply -auto-approve -input=false -var-file=terraform.tfvars | |
| # - name: 📄 Generate Terraform outputs | |
| # run: | | |
| # terraform -chdir=infra output -json > infra/tf_outputs.json | |
| # echo "✅ tf_outputs.json generated" | |
| - name: 📄 Generate Terraform outputs | |
| run: | | |
| "$TERRAFORM_CLI_PATH/terraform-bin" -chdir=infra output -json > infra/tf_outputs.json | |
| # - name: 🐛 Debug Terraform outputs | |
| # run: | | |
| # cat infra/tf_outputs.json | |
| - name: 📦 Upload inventory.ini as artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: inventory | |
| path: ansible/inventory.ini | |
| - name: 📤 Export Terraform outputs to GitHub ENV | |
| run: | | |
| echo "📥 Exporting variables to GitHub ENV..." | |
| echo "APP_SERVICE_NAME=$(jq -r '.app_service_name.value' infra/tf_outputs.json)" >> $GITHUB_ENV | |
| echo "RESOURCE_GROUP_NAME=$(jq -r '.resource_group_name.value' infra/tf_outputs.json)" >> $GITHUB_ENV | |
| echo "LB_API_URL=$(jq -r '.lb_api_url.value' infra/tf_outputs.json)" >> $GITHUB_ENV | |
| echo "LB_API_PORT=$(jq -r '.api_public_port.value' infra/tf_outputs.json)" >> $GITHUB_ENV | |
| - name: 🔧 Compose LB API URL | |
| run: | | |
| echo "LB_API_URL=${LB_API_URL}:${LB_API_PORT}" >> $GITHUB_ENV | |
| - name: 🗃️ Run Script Configure Jumpbox | |
| run: | | |
| chmod +x ./ansible/configure-jumpbox.sh | |
| # Get outputs from Terraform | |
| JUMP_HOST=$(terraform -chdir=infra output -raw control_node_public_ip | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | tail -n1) | |
| JUMP_USER=$(terraform -chdir=infra output -raw ssh_user | grep -Eo '^[a-zA-Z0-9]+' | tail -n1) | |
| SSH_KEY_CONTENT="${{ secrets.VM_SSH_KEY }}" | |
| ANSIBLE_DIR=./ansible | |
| REMOTE_DIR=/home/${JUMP_USER}/ansible-setup | |
| ./ansible/configure-jumpbox.sh "$JUMP_HOST" "$JUMP_USER" "$SSH_KEY_CONTENT" "$ANSIBLE_DIR" "$REMOTE_DIR" | |
| - name: 🛢️ Run Script Deploy Database | |
| run: | | |
| chmod +x ./ansible/deploy-db-from-local.sh | |
| # ✅ Ejecuta y guarda el resultado de terraform output | |
| # Get clean DB_HOST - Ultimate reliable method | |
| DB_HOST=$(terraform -chdir=infra output -raw mysql_fqdn 2>&1 | grep -oE '[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -n1) | |
| # echo "Extracted DB_HOST='$DB_HOST'" | |
| # Fallback if raw output fails | |
| if [ -z "$DB_HOST" ]; then | |
| DB_HOST=$(terraform -chdir=infra output mysql_fqdn | grep -oE '[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -n1) | |
| # echo "Fallback extracted DB_HOST='$DB_HOST'" | |
| fi | |
| # Final validation | |
| if [[ ! "$DB_HOST" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then | |
| echo "ERROR: Could not extract valid DB_HOST" | |
| echo "Raw terraform output:" | |
| terraform -chdir=infra output mysql_fqdn | |
| exit 1 | |
| fi | |
| DB_USER="${{ secrets.MYSQL_USER }}" | |
| DB_PASS="${{ secrets.MYSQL_ADMIN_PASSWORD }}" | |
| DB_NAME="movie_analyst" | |
| JUMP_HOST=$(terraform -chdir=infra output -raw control_node_public_ip | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | tail -n1) | |
| JUMP_USER=$(terraform -chdir=infra output -raw ssh_user | grep -Eo '^[a-zA-Z0-9]+' | tail -n1) | |
| ./ansible/deploy-db-from-local.sh "$DB_HOST" "$DB_USER" "$DB_PASS" "$DB_NAME" "$JUMP_HOST" "$JUMP_USER" | |
| - name: 🧩 Run Script Deploy API from Jumpbox to VMs | |
| run: | | |
| chmod +x ./ansible/deploy-api-jumpbox-to-vms.sh | |
| # Get clean DB_HOST - Ultimate reliable method | |
| DB_HOST=$(terraform -chdir=infra output -raw mysql_fqdn 2>&1 | grep -oE '[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -n1) | |
| # echo "Extracted DB_HOST='$DB_HOST'" | |
| # Fallback if raw output fails | |
| if [ -z "$DB_HOST" ]; then | |
| DB_HOST=$(terraform -chdir=infra output mysql_fqdn | grep -oE '[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | head -n1) | |
| # echo "Fallback extracted DB_HOST='$DB_HOST'" | |
| fi | |
| # Final validation | |
| if [[ ! "$DB_HOST" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then | |
| echo "ERROR: Could not extract valid DB_HOST" | |
| echo "Raw terraform output:" | |
| terraform -chdir=infra output mysql_fqdn | |
| exit 1 | |
| fi | |
| JUMP_HOST=$(terraform -chdir=infra output -raw control_node_public_ip | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | tail -n1) | |
| JUMP_USER=$(terraform -chdir=infra output -raw ssh_user | grep -Eo '^[a-zA-Z0-9]+' | tail -n1) | |
| DB_USER="${{ secrets.MYSQL_USER }}" | |
| DB_PASS="${{ secrets.MYSQL_ADMIN_PASSWORD }}" | |
| DB_NAME="movie_analyst" | |
| # echo "=== Final Variables ===" | |
| # echo "DB_HOST: $DB_HOST" | |
| # echo "JUMP_HOST: $JUMP_HOST" | |
| # echo "JUMP_USER: $JUMP_USER" | |
| ./ansible/deploy-api-jumpbox-to-vms.sh "$DB_HOST" "$DB_USER" "$DB_PASS" "$DB_NAME" "$JUMP_HOST" "$JUMP_USER" | |
| - name: Deploy Frontend | |
| run: | | |
| chmod +x ./ansible/deploy-frontend.yml | |
| echo "Using values:" | |
| echo "APP_SERVICE_NAME=$APP_SERVICE_NAME" | |
| echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" | |
| echo "LB_API_URL=$LB_API_URL" | |
| ansible-playbook ansible/deploy-frontend.yml -i localhost, | |
| env: | |
| APP_SERVICE_NAME: ${{ env.APP_SERVICE_NAME }} | |
| RESOURCE_GROUP_NAME: ${{ env.RESOURCE_GROUP_NAME }} | |
| LB_API_URL: ${{ env.LB_API_URL }} | |
| - name: 🌐 Show frontend URL | |
| run: | | |
| echo "✅ Your frontend is deployed and available at:" | |
| echo "https://${APP_SERVICE_NAME}.azurewebsites.net" | |
| env: | |
| APP_SERVICE_NAME: ${{ env.APP_SERVICE_NAME }} |