fix: add pull request trigger for main branch in deployment workflow #2
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: Validate Deployment - Client Advisor (v2) | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| - demo | |
| - ve-pipelineupgrade | |
| schedule: | |
| - cron: "0 6,18 * * *" # Runs at 6:00 AM and 6:00 PM GMT | |
| workflow_dispatch: | |
| inputs: | |
| azure_location: | |
| description: 'Azure Location For Deployment' | |
| required: false | |
| default: 'australiaeast' | |
| type: choice | |
| options: | |
| - 'australiaeast' | |
| - 'centralus' | |
| - 'eastasia' | |
| - 'eastus2' | |
| - 'japaneast' | |
| - 'northeurope' | |
| - 'southeastasia' | |
| - 'uksouth' | |
| - 'eastus' | |
| resource_group_name: | |
| description: 'Resource Group Name (Optional - will generate unique name if not provided)' | |
| required: false | |
| default: '' | |
| type: string | |
| waf_enabled: | |
| description: 'Enable WAF (Well-Architected Framework) configuration' | |
| required: false | |
| default: false | |
| type: boolean | |
| cleanup_resources: | |
| description: 'Cleanup resources after deployment and testing' | |
| required: false | |
| default: true | |
| type: boolean | |
| run_e2e_tests: | |
| description: 'Run E2E tests after deployment' | |
| required: false | |
| default: true | |
| type: boolean | |
| build_docker_image: | |
| description: 'Build new Docker image (if false, uses existing image based on branch)' | |
| required: false | |
| default: false | |
| type: boolean | |
| existing_webapp_url: | |
| description: 'Existing WebApp URL to test (skips deployment if provided)' | |
| required: false | |
| default: '' | |
| type: string | |
| env: | |
| GPT_MIN_CAPACITY: 200 | |
| TEXT_EMBEDDING_MIN_CAPACITY: 80 | |
| BRANCH_NAME: ${{ github.head_ref || github.ref_name }} | |
| # For automatic triggers (push, schedule): force Non-WAF | |
| # For manual dispatch: use input values or defaults | |
| WAF_ENABLED: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.waf_enabled || false) || false }} | |
| CLEANUP_RESOURCES: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.cleanup_resources || true) || true }} | |
| RUN_E2E_TESTS: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.run_e2e_tests || true) || true }} | |
| BUILD_DOCKER_IMAGE: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.build_docker_image || false) || false }} | |
| jobs: | |
| docker-build: | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.build_docker_image == 'true' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| IMAGE_TAG: ${{ steps.generate_docker_tag.outputs.IMAGE_TAG }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Generate Unique Docker Image Tag | |
| id: generate_docker_tag | |
| run: | | |
| echo "🔨 Building new Docker image - generating unique tag..." | |
| # Generate unique tag for manual deployment runs | |
| TIMESTAMP=$(date +%Y%m%d-%H%M%S) | |
| RUN_ID="${{ github.run_id }}" | |
| BRANCH_NAME="${{ github.head_ref || github.ref_name }}" | |
| # Sanitize branch name for Docker tag (replace invalid characters with hyphens) | |
| CLEAN_BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g') | |
| UNIQUE_TAG="${CLEAN_BRANCH_NAME}-${TIMESTAMP}-${RUN_ID}" | |
| echo "IMAGE_TAG=$UNIQUE_TAG" >> $GITHUB_ENV | |
| echo "IMAGE_TAG=$UNIQUE_TAG" >> $GITHUB_OUTPUT | |
| echo "Generated unique Docker tag: $UNIQUE_TAG" | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Azure Container Registry | |
| uses: azure/docker-login@v2 | |
| with: | |
| login-server: ${{ secrets.ACR_LOGIN_SERVER }} | |
| username: ${{ secrets.ACR_USERNAME }} | |
| password: ${{ secrets.ACR_PASSWORD }} | |
| - name: Build and Push Docker Image | |
| id: build_push_image | |
| uses: docker/build-push-action@v6 | |
| env: | |
| DOCKER_BUILD_SUMMARY: false | |
| with: | |
| context: ./src/App | |
| file: ./src/App/WebApp.Dockerfile | |
| push: true | |
| tags: | | |
| ${{ secrets.ACR_LOGIN_SERVER }}/webapp:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }} | |
| ${{ secrets.ACR_LOGIN_SERVER }}/webapp:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}_${{ github.run_number }} | |
| - name: Verify Docker Image Build | |
| run: | | |
| echo "✅ Docker image successfully built and pushed" | |
| echo "Image tag: ${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}" | |
| echo "Run number: ${{ github.run_number }}" | |
| - name: Generate Docker Build Summary | |
| if: always() | |
| run: | | |
| # Extract ACR name from the secret | |
| ACR_NAME=$(echo "${{ secrets.ACR_LOGIN_SERVER }}" | cut -d'.' -f1) | |
| echo "## 🐳 Docker Build Job Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Job Status** | ${{ job.status == 'success' && '✅ Success' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Image Tag** | \`${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Registry** | \`${ACR_NAME}.azurecr.io\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Full Image Path** | \`${ACR_NAME}.azurecr.io/webapp:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Trigger** | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Branch** | ${{ env.BRANCH_NAME }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ job.status }}" == "success" ]]; then | |
| echo "### ✅ Build Details" >> $GITHUB_STEP_SUMMARY | |
| echo "- Docker image successfully built and pushed to ACR" >> $GITHUB_STEP_SUMMARY | |
| echo "- Generated unique tag: \`${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Build Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "- Docker build process encountered an error" >> $GITHUB_STEP_SUMMARY | |
| echo "- Check the docker-build job for detailed error information" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| deploy: | |
| if: always() && (github.event_name != 'workflow_dispatch' || github.event.inputs.existing_webapp_url == '' || github.event.inputs.existing_webapp_url == null) | |
| needs: [docker-build] | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }} | |
| WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }} | |
| DEPLOYMENT_SUCCESS: ${{ steps.deployment_status.outputs.SUCCESS }} | |
| AI_SERVICES_NAME: ${{ steps.get_ai_services_name.outputs.AI_SERVICES_NAME }} | |
| KEYVAULTS: ${{ steps.list_keyvaults.outputs.KEYVAULTS }} | |
| AZURE_LOCATION: ${{ steps.set_region.outputs.AZURE_LOCATION }} | |
| SOLUTION_PREFIX: ${{ steps.generate_solution_prefix.outputs.SOLUTION_PREFIX }} | |
| IMAGE_TAG: ${{ steps.determine_image_tag.outputs.IMAGE_TAG }} | |
| QUOTA_FAILED: ${{ steps.quota_failure_output.outputs.QUOTA_FAILED }} | |
| steps: | |
| - name: Display Workflow Configuration | |
| run: | | |
| echo "🚀 ===================================" | |
| echo "📋 WORKFLOW CONFIGURATION SUMMARY" | |
| echo "🚀 ===================================" | |
| echo "Trigger Type: ${{ github.event_name }}" | |
| echo "Branch: ${{ env.BRANCH_NAME }}" | |
| echo "" | |
| echo "Configuration Settings:" | |
| echo " • WAF Enabled: ${{ env.WAF_ENABLED }}" | |
| echo " • Run E2E Tests: ${{ env.RUN_E2E_TESTS }}" | |
| echo " • Cleanup Resources: ${{ env.CLEANUP_RESOURCES }}" | |
| echo " • Build Docker Image: ${{ env.BUILD_DOCKER_IMAGE }}" | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.azure_location }}" ]]; then | |
| echo " • Selected Azure Location: ${{ github.event.inputs.azure_location }}" | |
| else | |
| echo " • Azure Location: Will be determined by quota check" | |
| fi | |
| if [[ "${{ github.event.inputs.existing_webapp_url }}" != "" ]]; then | |
| echo " • Using Existing Webapp URL: ${{ github.event.inputs.existing_webapp_url }}" | |
| echo " • Skip Deployment: Yes" | |
| else | |
| echo " • Skip Deployment: No" | |
| fi | |
| echo "" | |
| if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then | |
| echo "ℹ️ Automatic Trigger: Using Non-WAF configuration" | |
| else | |
| echo "ℹ️ Manual Trigger: Using user-specified configuration" | |
| fi | |
| echo "🚀 ===================================" | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install ODBC Driver 18 for SQL Server | |
| run: | | |
| curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - | |
| sudo add-apt-repository "$(curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list)" | |
| sudo apt-get update | |
| sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 | |
| sudo apt-get install -y unixodbc-dev | |
| - name: Setup Azure CLI | |
| run: | | |
| curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash | |
| az --version # Verify installation | |
| - name: Login to Azure | |
| run: | | |
| az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} | |
| az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Run Quota Check | |
| id: quota-check | |
| run: | | |
| export AZURE_CLIENT_ID="${{ secrets.AZURE_CLIENT_ID }}" | |
| export AZURE_TENANT_ID="${{ secrets.AZURE_TENANT_ID }}" | |
| export AZURE_CLIENT_SECRET="${{ secrets.AZURE_CLIENT_SECRET }}" | |
| export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}" | |
| export GPT_MIN_CAPACITY="${{ env.GPT_MIN_CAPACITY }}" | |
| export TEXT_EMBEDDING_MIN_CAPACITY="${{ env.TEXT_EMBEDDING_MIN_CAPACITY }}" | |
| export AZURE_REGIONS="${{ vars.AZURE_REGIONS_CA }}" | |
| chmod +x infra/scripts/checkquota.sh | |
| if ! infra/scripts/checkquota.sh; then | |
| if grep -q "No region with sufficient quota found" infra/scripts/checkquota_ca.sh; then | |
| echo "QUOTA_FAILED=true" >> $GITHUB_ENV | |
| fi | |
| exit 1 | |
| fi | |
| - name: Set Quota Failure Output | |
| id: quota_failure_output | |
| if: env.QUOTA_FAILED == 'true' | |
| run: | | |
| echo "QUOTA_FAILED=true" >> $GITHUB_OUTPUT | |
| echo "Quota check failed - will notify via separate notification job" | |
| - name: Fail Pipeline if Quota Check Fails | |
| if: env.QUOTA_FAILED == 'true' | |
| run: exit 1 | |
| - name: Install Bicep CLI | |
| run: az bicep install | |
| - name: Set Deployment Region | |
| id: set_region | |
| run: | | |
| echo "Selected Region from Quota Check: $VALID_REGION" | |
| echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_ENV | |
| echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT | |
| # Override with user-selected location for manual triggers | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.azure_location }}" ]]; then | |
| USER_SELECTED_LOCATION="${{ github.event.inputs.azure_location }}" | |
| echo "Using user-selected Azure location: $USER_SELECTED_LOCATION" | |
| echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_ENV | |
| echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_OUTPUT | |
| else | |
| echo "Using location from quota check for automatic triggers: $VALID_REGION" | |
| fi | |
| - name: Generate Resource Group Name | |
| id: generate_rg_name | |
| run: | | |
| # Check if a resource group name was provided as input | |
| if [[ -n "${{ github.event.inputs.resource_group_name }}" ]]; then | |
| echo "Using provided Resource Group name: ${{ github.event.inputs.resource_group_name }}" | |
| echo "RESOURCE_GROUP_NAME=${{ github.event.inputs.resource_group_name }}" >> $GITHUB_ENV | |
| else | |
| echo "Generating a unique resource group name..." | |
| ACCL_NAME="ca" # Account name as specified | |
| SHORT_UUID=$(uuidgen | cut -d'-' -f1) | |
| UNIQUE_RG_NAME="arg-${ACCL_NAME}-${SHORT_UUID}" | |
| echo "RESOURCE_GROUP_NAME=${UNIQUE_RG_NAME}" >> $GITHUB_ENV | |
| echo "Generated RESOURCE_GROUP_NAME: ${UNIQUE_RG_NAME}" | |
| fi | |
| - name: Check and Create Resource Group | |
| id: check_create_rg | |
| run: | | |
| set -e | |
| echo "🔍 Checking if resource group '$RESOURCE_GROUP_NAME' exists..." | |
| rg_exists=$(az group exists --name $RESOURCE_GROUP_NAME) | |
| if [ "$rg_exists" = "false" ]; then | |
| echo "📦 Resource group does not exist. Creating new resource group '$RESOURCE_GROUP_NAME' in location '$AZURE_LOCATION'..." | |
| az group create --name $RESOURCE_GROUP_NAME --location $AZURE_LOCATION || { echo "❌ Error creating resource group"; exit 1; } | |
| echo "✅ Resource group '$RESOURCE_GROUP_NAME' created successfully." | |
| else | |
| echo "✅ Resource group '$RESOURCE_GROUP_NAME' already exists. Deploying to existing resource group." | |
| fi | |
| echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT | |
| - name: Generate Unique Solution Prefix | |
| id: generate_solution_prefix | |
| run: | | |
| set -e | |
| COMMON_PART="pslc" | |
| TIMESTAMP=$(date +%s) | |
| UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 3) | |
| UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}" | |
| echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV | |
| echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_OUTPUT | |
| echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}" | |
| - name: Determine Docker Image Tag | |
| id: determine_image_tag | |
| run: | | |
| if [[ "${{ env.BUILD_DOCKER_IMAGE }}" == "true" ]]; then | |
| # Use the tag from docker-build job if it was built | |
| if [[ "${{ needs.docker-build.result }}" == "success" ]]; then | |
| IMAGE_TAG="${{ needs.docker-build.outputs.IMAGE_TAG }}" | |
| echo "🏷️ Using newly built Docker image tag: $IMAGE_TAG" | |
| else | |
| echo "❌ Docker build failed but BUILD_DOCKER_IMAGE is true" | |
| exit 1 | |
| fi | |
| else | |
| echo "🏷️ Using existing Docker image based on branch..." | |
| BRANCH_NAME="${{ env.BRANCH_NAME }}" | |
| echo "Current branch: $BRANCH_NAME" | |
| # Determine image tag based on branch | |
| if [[ "$BRANCH_NAME" == "main" ]]; then | |
| IMAGE_TAG="latest_waf" | |
| echo "Using main branch - image tag: latest_waf" | |
| elif [[ "$BRANCH_NAME" == "dev" ]]; then | |
| IMAGE_TAG="dev" | |
| echo "Using dev branch - image tag: dev" | |
| elif [[ "$BRANCH_NAME" == "demo" ]]; then | |
| IMAGE_TAG="demo" | |
| echo "Using demo branch - image tag: demo" | |
| else | |
| IMAGE_TAG="latest_waf" | |
| echo "Using default for branch '$BRANCH_NAME' - image tag: latest_waf" | |
| fi | |
| echo "Using existing Docker image tag: $IMAGE_TAG" | |
| fi | |
| echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV | |
| echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_OUTPUT | |
| - name: Display Docker Image Tag | |
| run: | | |
| echo "=== Docker Image Information ===" | |
| echo "Docker Image Tag: ${{ steps.determine_image_tag.outputs.IMAGE_TAG }}" | |
| echo "Registry: ${{ secrets.ACR_LOGIN_SERVER }}" | |
| echo "Full Image: ${{ secrets.ACR_LOGIN_SERVER }}/webapp:${{ steps.determine_image_tag.outputs.IMAGE_TAG }}" | |
| echo "================================" | |
| - name: Deploy and extract values from deployment output | |
| id: get_output | |
| run: | | |
| set -e | |
| echo "Fetching deployment output..." | |
| # Install azd (Azure Developer CLI) - required by process_sample_data.sh | |
| curl -fsSL https://aka.ms/install-azd.sh | bash | |
| # Generate current timestamp in desired format: YYYY-MM-DDTHH:MM:SS.SSSSSSSZ | |
| current_date=$(date -u +"%Y-%m-%dT%H:%M:%S.%7NZ") | |
| DEPLOY_OUTPUT=$(az deployment group create \ | |
| --resource-group ${{ env.RESOURCE_GROUP_NAME }} \ | |
| --template-file infra/main.bicep \ | |
| --parameters location=${{ env.AZURE_LOCATION }} azureAiServiceLocation=${{ env.AZURE_LOCATION }} solutionName=${{ env.SOLUTION_PREFIX }} cosmosLocation=westus gptModelCapacity=${{ env.GPT_MIN_CAPACITY }} embeddingDeploymentCapacity=${{ env.TEXT_EMBEDDING_MIN_CAPACITY }} imageTag=${{ env.IMAGE_TAG }} createdBy="Pipeline" tags="{'SecurityControl':'Ignore','Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}" \ | |
| --query "properties.outputs" -o json) | |
| echo "Deployment output: $DEPLOY_OUTPUT" | |
| if [[ -z "$DEPLOY_OUTPUT" ]]; then | |
| echo "Error: Deployment output is empty. Please check the deployment logs." | |
| exit 1 | |
| fi | |
| export AI_FOUNDRY_RESOURCE_ID=$(echo "$DEPLOY_OUTPUT" | jq -r '.aI_FOUNDRY_RESOURCE_ID.value') | |
| echo "AI_FOUNDRY_RESOURCE_ID=$AI_FOUNDRY_RESOURCE_ID" >> $GITHUB_ENV | |
| export SEARCH_SERVICE_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.aI_SEARCH_SERVICE_NAME.value') | |
| echo "SEARCH_SERVICE_NAME=$SEARCH_SERVICE_NAME" >> $GITHUB_ENV | |
| export COSMOS_DB_ACCOUNT_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.cosmosdB_ACCOUNT_NAME.value') | |
| echo "COSMOS_DB_ACCOUNT_NAME=$COSMOS_DB_ACCOUNT_NAME" >> $GITHUB_ENV | |
| export STORAGE_ACCOUNT=$(echo "$DEPLOY_OUTPUT" | jq -r '.storagE_ACCOUNT_NAME.value') | |
| echo "STORAGE_ACCOUNT=$STORAGE_ACCOUNT" >> $GITHUB_ENV | |
| export STORAGE_CONTAINER=$(echo "$DEPLOY_OUTPUT" | jq -r '.storagE_CONTAINER_NAME.value') | |
| echo "STORAGE_CONTAINER=$STORAGE_CONTAINER" >> $GITHUB_ENV | |
| export KEYVAULT_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.keY_VAULT_NAME.value') | |
| echo "KEYVAULT_NAME=$KEYVAULT_NAME" >> $GITHUB_ENV | |
| export SQL_SERVER_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.sqldB_SERVER_NAME.value') | |
| echo "SQL_SERVER_NAME=$SQL_SERVER_NAME" >> $GITHUB_ENV | |
| export SQL_DATABASE=$(echo "$DEPLOY_OUTPUT" | jq -r '.sqldB_DATABASE.value') | |
| echo "SQL_DATABASE=$SQL_DATABASE" >> $GITHUB_ENV | |
| export CLIENT_ID=$(echo "$DEPLOY_OUTPUT" | jq -r '.managedidentitY_SQL_CLIENTID.value') | |
| echo "CLIENT_ID=$CLIENT_ID" >> $GITHUB_ENV | |
| export CLIENT_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.managedidentitY_SQL_NAME.value') | |
| echo "CLIENT_NAME=$CLIENT_NAME" >> $GITHUB_ENV | |
| export RG_NAME=$(echo "$DEPLOY_OUTPUT" | jq -r '.resourcE_GROUP_NAME.value') | |
| echo "RG_NAME=$RG_NAME" >> $GITHUB_ENV | |
| WEBAPP_URL=$(echo $DEPLOY_OUTPUT | jq -r '.weB_APP_URL.value') | |
| echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT | |
| WEB_APP_NAME=$(echo $DEPLOY_OUTPUT | jq -r '.weB_APP_NAME.value') | |
| echo "WEB_APP_NAME=$WEB_APP_NAME" >> $GITHUB_ENV | |
| echo "🔧 Disabling AUTH_ENABLED for the web app..." | |
| az webapp config appsettings set -g "$RG_NAME" -n "$WEB_APP_NAME" --settings AUTH_ENABLED=false | |
| sleep 30 | |
| - name: Deploy Infra and Import Sample Data | |
| run: | | |
| set -e | |
| az account set --subscription "${{ secrets.AZURE_SUBSCRIPTION_ID }}" | |
| echo "Running post-deployment script..." | |
| bash ./infra/scripts/add_cosmosdb_access.sh \ | |
| "${{ env.RG_NAME }}" \ | |
| "${{ env.COSMOS_DB_ACCOUNT_NAME }}" \ | |
| "${{ secrets.AZURE_CLIENT_ID }}" | |
| bash ./infra/scripts/copy_kb_files.sh \ | |
| "${{ env.STORAGE_ACCOUNT }}" \ | |
| "${{ env.STORAGE_CONTAINER }}" \ | |
| "" \ | |
| "${{ secrets.AZURE_CLIENT_ID }}" | |
| bash ./infra/scripts/run_create_index_scripts.sh \ | |
| "${{ env.KEYVAULT_NAME }}" \ | |
| "" \ | |
| "${{ secrets.AZURE_CLIENT_ID }}" \ | |
| "${{ env.RG_NAME }}" \ | |
| "${{ env.SQL_SERVER_NAME }}" \ | |
| "${{ env.SEARCH_SERVICE_NAME }}" \ | |
| "${{ env.AI_FOUNDRY_RESOURCE_ID}}" | |
| user_roles_json='[ | |
| {"clientId":"${{ env.CLIENT_ID }}","displayName":"${{ env.CLIENT_NAME }}","role":"db_datareader"}, | |
| {"clientId":"${{ env.CLIENT_ID }}","displayName":"${{ env.CLIENT_NAME }}","role":"db_owner"} | |
| ]' | |
| bash ./infra/scripts/add_user_scripts/create_sql_user_and_role.sh \ | |
| "${{ env.SQL_SERVER_NAME }}.database.windows.net" \ | |
| "${{ env.SQL_DATABASE }}" \ | |
| "$user_roles_json" \ | |
| "${{ secrets.AZURE_CLIENT_ID }}" | |
| echo "=== Post-Deployment Script Completed Successfully ===" | |
| - name: Get AI Services name and store in variable | |
| if: always() && steps.check_create_rg.outcome == 'success' | |
| id: get_ai_services_name | |
| run: | | |
| set -e | |
| echo "Getting AI Services name..." | |
| ai_services_name=$(az cognitiveservices account list -g ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv) | |
| if [ -z "$ai_services_name" ]; then | |
| echo "No AI Services resource found in the resource group." | |
| echo "AI_SERVICES_NAME=" >> $GITHUB_OUTPUT | |
| else | |
| echo "AI_SERVICES_NAME=${ai_services_name}" >> $GITHUB_OUTPUT | |
| echo "Found AI Services resource: $ai_services_name" | |
| fi | |
| - name: List KeyVaults and Store in Array | |
| if: always() && steps.check_create_rg.outcome == 'success' | |
| id: list_keyvaults | |
| run: | | |
| set -e | |
| echo "Listing all KeyVaults in the resource group ${{ env.RESOURCE_GROUP_NAME }}..." | |
| keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv) | |
| if [ -z "$keyvaults" ]; then | |
| echo "No KeyVaults found in resource group ${{ env.RESOURCE_GROUP_NAME }}." | |
| echo "KEYVAULTS=[]" >> $GITHUB_OUTPUT | |
| else | |
| echo "KeyVaults found: $keyvaults" | |
| # Format the list into an array with proper formatting (no trailing comma) | |
| keyvault_array="[" | |
| first=true | |
| for kv in $keyvaults; do | |
| if [ "$first" = true ]; then | |
| keyvault_array="$keyvault_array\"$kv\"" | |
| first=false | |
| else | |
| keyvault_array="$keyvault_array,\"$kv\"" | |
| fi | |
| done | |
| keyvault_array="$keyvault_array]" | |
| echo "KEYVAULTS=$keyvault_array" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Set Deployment Status | |
| id: deployment_status | |
| if: always() | |
| run: | | |
| if [ "${{ job.status }}" == "success" ]; then | |
| echo "SUCCESS=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "SUCCESS=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Logout | |
| if: always() | |
| run: az logout | |
| - name: Generate Deployment Job Summary | |
| if: always() | |
| run: | | |
| echo "## 🚀 Deployment Job Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Job Status** | ${{ job.status == 'success' && '✅ Success' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Resource Group** | \`${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Azure Region** | \`${{ steps.set_region.outputs.AZURE_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Solution Prefix** | \`${{ steps.generate_solution_prefix.outputs.SOLUTION_PREFIX }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Docker Image Tag** | \`${{ steps.determine_image_tag.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **WAF Enabled** | ${{ env.WAF_ENABLED == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Trigger** | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Branch** | ${{ env.BRANCH_NAME }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ job.status }}" == "success" ]]; then | |
| echo "### ✅ Deployment Details" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Web App URL**: [${{ steps.get_output.outputs.WEBAPP_URL }}](${{ steps.get_output.outputs.WEBAPP_URL }})" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Configuration**: ${{ env.WAF_ENABLED == 'true' && 'WAF' || 'Non-WAF' }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Successfully deployed to Azure with all resources configured" >> $GITHUB_STEP_SUMMARY | |
| echo "- Post-deployment scripts executed successfully" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Deployment Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "- Deployment process encountered an error" >> $GITHUB_STEP_SUMMARY | |
| echo "- Check the deploy job for detailed error information" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| e2e-test: | |
| if: always() && ((needs.deploy.result == 'success' && needs.deploy.outputs.WEBAPP_URL != '') || (github.event.inputs.existing_webapp_url != '' && github.event.inputs.existing_webapp_url != null)) && (github.event_name != 'workflow_dispatch' || github.event.inputs.run_e2e_tests == 'true' || github.event.inputs.run_e2e_tests == null) | |
| needs: [docker-build, deploy] | |
| uses: ./.github/workflows/test_automation.yml | |
| with: | |
| CA_WEB_URL: ${{ github.event.inputs.existing_webapp_url || needs.deploy.outputs.WEBAPP_URL }} | |
| secrets: inherit | |
| cleanup: | |
| if: always() && needs.deploy.result == 'success' && needs.deploy.outputs.RESOURCE_GROUP_NAME != '' && github.event.inputs.existing_webapp_url == '' && (github.event_name != 'workflow_dispatch' || github.event.inputs.cleanup_resources == 'true' || github.event.inputs.cleanup_resources == null) | |
| needs: [docker-build, deploy, e2e-test] | |
| runs-on: ubuntu-latest | |
| env: | |
| RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }} | |
| AI_SERVICES_NAME: ${{ needs.deploy.outputs.AI_SERVICES_NAME }} | |
| KEYVAULTS: ${{ needs.deploy.outputs.KEYVAULTS }} | |
| AZURE_LOCATION: ${{ needs.deploy.outputs.AZURE_LOCATION }} | |
| SOLUTION_PREFIX: ${{ needs.deploy.outputs.SOLUTION_PREFIX }} | |
| IMAGE_TAG: ${{ needs.deploy.outputs.IMAGE_TAG }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Setup Azure CLI | |
| run: | | |
| curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash | |
| az --version | |
| - name: Login to Azure | |
| run: | | |
| az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} | |
| az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Delete Docker Images from ACR | |
| if: github.event.inputs.existing_webapp_url == '' | |
| run: | | |
| set -e | |
| echo "🗑️ Cleaning up Docker images from Azure Container Registry..." | |
| # Determine the image tag to delete - check if docker-build job ran | |
| if [[ "${{ needs.docker-build.result }}" == "success" ]]; then | |
| IMAGE_TAG="${{ needs.docker-build.outputs.IMAGE_TAG }}" | |
| echo "Using image tag from docker-build job: $IMAGE_TAG" | |
| else | |
| IMAGE_TAG="${{ needs.deploy.outputs.IMAGE_TAG }}" | |
| echo "Using image tag from deploy job: $IMAGE_TAG" | |
| fi | |
| if [[ -n "$IMAGE_TAG" && "$IMAGE_TAG" != "latest_waf" && "$IMAGE_TAG" != "dev" && "$IMAGE_TAG" != "demo" ]]; then | |
| echo "Deleting Docker images with tag: $IMAGE_TAG" | |
| # Delete the main image | |
| echo "Deleting image: ${{ secrets.ACR_LOGIN_SERVER }}/webapp:$IMAGE_TAG" | |
| az acr repository delete --name $(echo "${{ secrets.ACR_LOGIN_SERVER }}" | cut -d'.' -f1) \ | |
| --image webapp:$IMAGE_TAG --yes || echo "Warning: Failed to delete main image or image not found" | |
| echo "✅ Docker images cleanup completed" | |
| else | |
| echo "⚠️ Skipping Docker image cleanup (using standard branch image: $IMAGE_TAG)" | |
| fi | |
| - name: Delete Bicep Deployment | |
| if: always() | |
| run: | | |
| set -e | |
| echo "Checking if resource group exists..." | |
| echo "Resource group name: ${{ env.RESOURCE_GROUP_NAME }}" | |
| if [ -z "${{ env.RESOURCE_GROUP_NAME }}" ]; then | |
| echo "Resource group name is empty. Skipping deletion." | |
| exit 0 | |
| fi | |
| rg_exists=$(az group exists --name "${{ env.RESOURCE_GROUP_NAME }}") | |
| if [ "$rg_exists" = "true" ]; then | |
| echo "Resource group exists. Cleaning..." | |
| az group delete \ | |
| --name "${{ env.RESOURCE_GROUP_NAME }}" \ | |
| --yes \ | |
| --no-wait | |
| echo "Resource group deletion initiated: ${{ env.RESOURCE_GROUP_NAME }}" | |
| else | |
| echo "Resource group does not exist." | |
| fi | |
| - name: Wait for resource deletion to complete | |
| if: always() | |
| run: | | |
| # Check if resource group name is available | |
| if [ -z "${{ env.RESOURCE_GROUP_NAME }}" ]; then | |
| echo "Resource group name is empty. Skipping resource check." | |
| exit 0 | |
| fi | |
| # List of keyvaults | |
| KEYVAULTS="${{ env.KEYVAULTS }}" | |
| # Remove the surrounding square brackets and quotes, if they exist | |
| stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g' | sed 's/"//g') | |
| # Convert the comma-separated string into an array | |
| IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults" | |
| echo "List of resources to check: ${resources_to_check[@]}" | |
| # Check if resource group still exists before listing resources | |
| rg_exists=$(az group exists --name "${{ env.RESOURCE_GROUP_NAME }}") | |
| if [ "$rg_exists" = "false" ]; then | |
| echo "Resource group no longer exists. Skipping resource check." | |
| exit 0 | |
| fi | |
| # Get the list of resources in YAML format | |
| resource_list=$(az resource list --resource-group "${{ env.RESOURCE_GROUP_NAME }}" --output yaml || echo "") | |
| # Maximum number of retries | |
| max_retries=3 | |
| # Retry intervals in seconds (30, 60, 120) | |
| retry_intervals=(30 60 120) | |
| # Retry mechanism to check resources | |
| retries=0 | |
| while true; do | |
| resource_found=false | |
| # Check if resource group still exists | |
| rg_exists=$(az group exists --name "${{ env.RESOURCE_GROUP_NAME }}") | |
| if [ "$rg_exists" = "false" ]; then | |
| echo "Resource group no longer exists. Exiting resource check." | |
| break | |
| fi | |
| # Iterate through the resources to check | |
| for resource in "${resources_to_check[@]}"; do | |
| # Skip empty resource names | |
| if [ -z "$resource" ]; then | |
| continue | |
| fi | |
| echo "Checking resource: $resource" | |
| if echo "$resource_list" | grep -q "name: $resource"; then | |
| echo "Resource '$resource' exists in the resource group." | |
| resource_found=true | |
| else | |
| echo "Resource '$resource' does not exist in the resource group." | |
| fi | |
| done | |
| # If any resource exists, retry | |
| if [ "$resource_found" = true ]; then | |
| retries=$((retries + 1)) | |
| if [ "$retries" -ge "$max_retries" ]; then | |
| echo "Maximum retry attempts reached. Exiting." | |
| break | |
| else | |
| # Wait for the appropriate interval for the current retry | |
| echo "Waiting for ${retry_intervals[$retries-1]} seconds before retrying..." | |
| sleep ${retry_intervals[$retries-1]} | |
| # Refresh resource list | |
| resource_list=$(az resource list --resource-group "${{ env.RESOURCE_GROUP_NAME }}" --output yaml || echo "") | |
| fi | |
| else | |
| echo "No resources found. Exiting." | |
| break | |
| fi | |
| done | |
| - name: Purging the Resources | |
| if: always() | |
| run: | | |
| set -e | |
| # Check if resource group name is available | |
| if [ -z "${{ env.RESOURCE_GROUP_NAME }}" ]; then | |
| echo "Resource group name is empty. Skipping resource purging." | |
| exit 0 | |
| fi | |
| # Purge AI Services | |
| if [ -z "${{ env.AI_SERVICES_NAME }}" ]; then | |
| echo "AI_SERVICES_NAME is not set. Skipping AI Services purge." | |
| else | |
| echo "Purging AI Services..." | |
| if [ -n "$(az cognitiveservices account list-deleted --query "[?name=='${{ env.AI_SERVICES_NAME }}']" -o tsv)" ]; then | |
| echo "AI Services '${{ env.AI_SERVICES_NAME }}' is soft-deleted. Proceeding to purge..." | |
| az cognitiveservices account purge --location "${{ env.AZURE_LOCATION }}" --resource-group "${{ env.RESOURCE_GROUP_NAME }}" --name "${{ env.AI_SERVICES_NAME }}" | |
| else | |
| echo "AI Services '${{ env.AI_SERVICES_NAME }}' is not soft-deleted. No action taken." | |
| fi | |
| fi | |
| # Ensure KEYVAULTS is properly formatted as a comma-separated string | |
| KEYVAULTS="${{ env.KEYVAULTS }}" | |
| # Check if KEYVAULTS is empty or null | |
| if [ -z "$KEYVAULTS" ] || [ "$KEYVAULTS" = "[]" ]; then | |
| echo "No KeyVaults to purge." | |
| exit 0 | |
| fi | |
| # Remove the surrounding square brackets and quotes, if they exist | |
| stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g' | sed 's/"//g') | |
| # Convert the comma-separated string into an array | |
| IFS=',' read -r -a keyvault_array <<< "$stripped_keyvaults" | |
| echo "Using KeyVaults Array..." | |
| for keyvault_name in "${keyvault_array[@]}"; do | |
| # Skip empty keyvault names | |
| if [ -z "$keyvault_name" ]; then | |
| continue | |
| fi | |
| echo "Processing KeyVault: $keyvault_name" | |
| # Check if the KeyVault is soft-deleted | |
| deleted_vaults=$(az keyvault list-deleted --query "[?name=='$keyvault_name']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}) | |
| # If the KeyVault is found in the soft-deleted state, purge it | |
| if [ "$(echo "$deleted_vaults" | jq length)" -gt 0 ]; then | |
| echo "KeyVault '$keyvault_name' is soft-deleted. Proceeding to purge..." | |
| az keyvault purge --name "$keyvault_name" --no-wait | |
| else | |
| echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken." | |
| fi | |
| done | |
| echo "Resource purging completed successfully" | |
| - name: Logout | |
| if: always() | |
| run: az logout | |
| - name: Generate Cleanup Job Summary | |
| if: always() | |
| run: | | |
| echo "## 🧹 Cleanup Job Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Job Status** | ${{ job.status == 'success' && '✅ Success' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Resource Group** | \`${{ env.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Azure Region** | \`${{ env.AZURE_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Solution Prefix** | \`${{ env.SOLUTION_PREFIX }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Docker Image Tag** | \`${{ env.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Trigger** | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Branch** | ${{ env.BRANCH_NAME }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ job.status }}" == "success" ]]; then | |
| echo "### ✅ Cleanup Details" >> $GITHUB_STEP_SUMMARY | |
| echo "- Successfully deleted Azure resource group: \`${{ env.RESOURCE_GROUP_NAME }}\`" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ env.IMAGE_TAG }}" != "latest_waf" && "${{ env.IMAGE_TAG }}" != "dev" && "${{ env.IMAGE_TAG }}" != "demo" ]]; then | |
| echo "- Removed custom Docker images from ACR with tag: \`${{ env.IMAGE_TAG }}\`" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "- Preserved standard Docker image (using branch tag: \`${{ env.IMAGE_TAG }}\`)" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "- All deployed resources have been successfully cleaned up" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Cleanup Failed" >> $GITHUB_STEP_SUMMARY | |
| echo "- Cleanup process encountered an error" >> $GITHUB_STEP_SUMMARY | |
| echo "- Manual cleanup may be required" >> $GITHUB_STEP_SUMMARY | |
| echo "- ⬇️ Check the cleanup job for detailed error information" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| send-notification: | |
| if: always() | |
| needs: [docker-build, deploy, e2e-test] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Send Quota Failure Notification | |
| if: needs.deploy.result == 'failure' && needs.deploy.outputs.QUOTA_FAILED == 'true' | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>We would like to inform you that the Client Advisor deployment has failed due to insufficient quota in the requested regions.</p><p><strong>Issue Details:</strong><br>• Quota check failed for GPT and Text Embedding models<br>• Required GPT Capacity: ${{ env.GPT_MIN_CAPACITY }}<br>• Required Text Embedding Capacity: ${{ env.TEXT_EMBEDDING_MIN_CAPACITY }}<br>• Checked Regions: ${{ vars.AZURE_REGIONS_CA }}</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Please resolve the quota issue and retry the deployment.</p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Deployment - Failed (Insufficient Quota)" | |
| } | |
| EOF | |
| ) | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send quota failure notification" | |
| - name: Send Deployment Failure Notification | |
| if: needs.deploy.result == 'failure' && needs.deploy.outputs.QUOTA_FAILED != 'true' | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| RESOURCE_GROUP="${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}" | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>We would like to inform you that the Client Advisor deployment process has encountered an issue and has failed to complete successfully.</p><p><strong>Deployment Details:</strong><br>• Resource Group: ${RESOURCE_GROUP}<br>• WAF Enabled: ${{ env.WAF_ENABLED }}</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Please investigate the deployment failure at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Deployment - Failed" | |
| } | |
| EOF | |
| ) | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send deployment failure notification" | |
| - name: Send Success Notification | |
| if: needs.deploy.result == 'success' && (needs.e2e-test.result == 'skipped' || needs.e2e-test.outputs.TEST_SUCCESS == 'true') | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| WEBAPP_URL="${{ needs.deploy.outputs.WEBAPP_URL || github.event.inputs.existing_webapp_url }}" | |
| RESOURCE_GROUP="${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}" | |
| # Create email body based on test result | |
| if [ "${{ needs.e2e-test.result }}" = "skipped" ]; then | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>We would like to inform you that the Client Advisor deployment has completed successfully.</p><p><strong>Deployment Details:</strong><br>• Resource Group: ${RESOURCE_GROUP}<br>• Web App URL: <a href='${WEBAPP_URL}'>${WEBAPP_URL}</a><br>• E2E Tests: Skipped (as configured)</p><p><strong>Configuration:</strong><br>• WAF Enabled: ${{ env.WAF_ENABLED }}</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Deployment - Success" | |
| } | |
| EOF | |
| ) | |
| else | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>We would like to inform you that the Client Advisor deployment and testing process has completed successfully.</p><p><strong>Deployment Details:</strong><br>• Resource Group: ${RESOURCE_GROUP}<br>• Web App URL: <a href='${WEBAPP_URL}'>${WEBAPP_URL}</a><br>• E2E Tests: Passed</p><p><strong>Configuration:</strong><br>• WAF Enabled: ${{ env.WAF_ENABLED }}</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Deployment - Test Automation - Success" | |
| } | |
| EOF | |
| ) | |
| fi | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send success notification" | |
| - name: Send Test Failure Notification | |
| if: needs.deploy.result == 'success' && needs.e2e-test.result != 'skipped' && needs.e2e-test.outputs.TEST_SUCCESS != 'true' | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| WEBAPP_URL="${{ needs.deploy.outputs.WEBAPP_URL || github.event.inputs.existing_webapp_url }}" | |
| RESOURCE_GROUP="${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}" | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>We would like to inform you that test automation process has encountered issues and failed to complete successfully.</p><p><strong>Deployment Details:</strong><br>• Resource Group: ${RESOURCE_GROUP}<br>• Web App URL: <a href='${WEBAPP_URL}'>${WEBAPP_URL}</a><br>• Deployment Status: ✅ Success<br>• E2E Tests: ❌ Failed</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Deployment - Test Automation - Failed" | |
| } | |
| EOF | |
| ) | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send test failure notification" | |
| - name: Send Existing URL Success Notification | |
| if: needs.deploy.result == 'skipped' && github.event.inputs.existing_webapp_url != '' && needs.e2e-test.result == 'success' && (needs.e2e-test.outputs.TEST_SUCCESS == 'true' || needs.e2e-test.outputs.TEST_SUCCESS == '') | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| EXISTING_URL="${{ github.event.inputs.existing_webapp_url }}" | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>The Client Advisor pipeline executed against the <strong>existing WebApp URL</strong> and testing process has completed successfully.</p><p><strong>Test Results:</strong><br>• Status: ✅ Passed<br>• Target URL: <a href='${EXISTING_URL}'>${EXISTING_URL}</a></p><p><strong>Deployment:</strong> Skipped</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Pipeline - Test Automation Passed (Existing URL)" | |
| } | |
| EOF | |
| ) | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send existing URL success notification" | |
| - name: Send Existing URL Test Failure Notification | |
| if: needs.deploy.result == 'skipped' && github.event.inputs.existing_webapp_url != '' && needs.e2e-test.result == 'failure' | |
| run: | | |
| RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| EXISTING_URL="${{ github.event.inputs.existing_webapp_url }}" | |
| EMAIL_BODY=$(cat <<EOF | |
| { | |
| "body": "<p>Dear Team,</p><p>The Client Advisor pipeline executed against the <strong>existing WebApp URL</strong> and the test automation has encountered issues and failed to complete successfully.</p><p><strong>Failure Details:</strong><br>• Target URL: <a href='${EXISTING_URL}'>${EXISTING_URL}</a><br>• Deployment: Skipped</p><p><strong>Run URL:</strong> <a href='${RUN_URL}'>${RUN_URL}</a></p><p>Best regards,<br>Your Automation Team</p>", | |
| "subject": "CA Pipeline - Test Automation Failed (Existing URL)" | |
| } | |
| EOF | |
| ) | |
| curl -X POST "${{ secrets.LOGIC_APP_URL }}" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$EMAIL_BODY" || echo "Failed to send existing URL test failure notification" |