Skip to content

Fixed extraction

Fixed extraction #158

Workflow file for this run

name: Terraform CI/CD
on:
push:
branches: [ simplify ]
pull_request:
branches: [ simplify ]
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/simplify'
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
- name: 📦 Upload inventory.ini as artifact
uses: actions/upload-artifact@v4
with:
name: inventory
path: ansible/inventory.ini
- 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: Get Terraform outputs
id: tf
run: |
cd infra
# Get raw JSON output (with error handling)
if ! terraform output -json > outputs.json; then
echo "::error::Terraform output command failed"
exit 1
fi
# Verify JSON is valid
if ! jq empty outputs.json; then
echo "::error::Invalid JSON output from Terraform"
cat outputs.json
exit 1
fi
# Extract values with strict validation
APP_NAME=$(jq -r '.app_service_name.value // empty' outputs.json)
RG_NAME=$(jq -r '.resource_group_name.value // empty' outputs.json)
API_URL=$(jq -r '.lb_api_url.value // empty' outputs.json)
# Verify all values exist
if [[ -z "$APP_NAME" || -z "$RG_NAME" || -z "$API_URL" ]]; then
echo "::error::Missing required outputs from Terraform"
jq . outputs.json
exit 1
fi
# Sanitize values (remove any special characters)
APP_NAME=$(echo "$APP_NAME" | tr -cd '[:alnum:]-_')
RG_NAME=$(echo "$RG_NAME" | tr -cd '[:alnum:]-_')
API_URL=$(echo "$API_URL" | tr -cd '[:alnum:]:/.')
echo "webapp_name=${APP_NAME}" >> $GITHUB_OUTPUT
echo "resource_group=${RG_NAME}" >> $GITHUB_OUTPUT
echo "api_url=${API_URL}" >> $GITHUB_OUTPUT
echo "✅ Verified outputs:"
echo "APP: ${APP_NAME}"
echo "RG: ${RG_NAME}"
echo "API: ${API_URL}"
shell: bash
- name: Deploy Frontend
run: |
ansible-playbook ./ansible/deploy-frontend.yml \
-e "app_service_name=${{ steps.tf.outputs.webapp_name }}" \
-e "resource_group_name=${{ steps.tf.outputs.resource_group }}" \
-e "lb_api_url=${{ steps.tf.outputs.api_url }}" \
-e "frontend_src_dir=$GITHUB_WORKSPACE/src/movie-analyst-ui"