From 1242dcbd4133a524871001d799bd22c13b662cf9 Mon Sep 17 00:00:00 2001
From: Vemarthula-Microsoft
Date: Wed, 17 Sep 2025 20:34:37 +0530
Subject: [PATCH 01/40] Enhance deploy workflow with new branch and region
logic
Updated the deploy workflow to include a new branch for triggering the pipeline and modified the region selection logic for Azure resources based on quota availability.
---
.github/workflows/deploy.yml | 64 ++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index be98168f..e0598d17 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,17 +1,18 @@
name: Deploy-Test-Cleanup Pipeline
on:
- workflow_run:
- workflows: ["Build Docker and Optional Push"]
- types:
- - completed
- branches:
- - main
- - dev
- - demo
- schedule:
- - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
- workflow_dispatch:
+ workflow_run:
+ workflows: ["Build Docker and Optional Push"]
+ types:
+ - completed
+ branches:
+ - main
+ - dev
+ - demo
+ - vee-pipeline-fixes
+ schedule:
+ - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
+ workflow_dispatch:
env:
GPT_MIN_CAPACITY: 150
@@ -36,22 +37,28 @@ jobs:
run: |
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
- - name: Run Quota Check
- id: quota-check
+ - name: Select Region with Sufficient OpenAI Quota
+ id: select_region
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 AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
- chmod +x scripts/checkquota.sh
- if ! scripts/checkquota.sh; then
- # If quota check fails due to insufficient quota, set the flag
- if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
- echo "QUOTA_FAILED=true" >> $GITHUB_ENV
+ regions=("eastus2" "francecentral" "westus3" "southcentralus")
+ required_quota=150
+ selected_region=""
+ for region in "${regions[@]}"; do
+ available_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].limit" -o tsv)
+ used_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].used" -o tsv)
+ if [[ $((available_quota - used_quota)) -ge $required_quota ]]; then
+ selected_region="$region"
+ break
fi
- exit 1 # Fail the pipeline if any other failure occurs
+ done
+ if [[ -z "$selected_region" ]]; then
+ echo "No region with sufficient quota found."
+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
+ exit 1
+ else
+ echo "Selected region: $selected_region"
+ echo "SELECTED_REGION=$selected_region" >> $GITHUB_ENV
+ echo "selected_region=$selected_region" >> $GITHUB_OUTPUT
fi
- name: Send Notification on Quota Failure
@@ -94,7 +101,7 @@ jobs:
rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
if [ "$rg_exists" = "false" ]; then
echo "Resource group does not exist. Creating..."
- az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location northcentralus || { echo "Error creating resource group"; exit 1; }
+ az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location ${{ env.SELECTED_REGION }} || { echo "Error creating resource group"; exit 1; }
else
echo "Resource group already exists."
fi
@@ -132,11 +139,12 @@ jobs:
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="eastus" \
+ aiDeploymentsLocation="${{ env.SELECTED_REGION }}" \
useWafAlignedArchitecture=false \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline"
+
- name: Assign Contributor role to Service Principal
if: always()
run: |
@@ -356,7 +364,7 @@ jobs:
# Purge OpenAI Resource
echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.SELECTED_REGION }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
From 97750c9a69a549a0dbd805c1ffe397f4fc46a72b Mon Sep 17 00:00:00 2001
From: Vemarthula-Microsoft
Date: Thu, 18 Sep 2025 06:36:21 +0530
Subject: [PATCH 02/40] Update deploy workflow for Azure OpenAI integration
---
.github/workflows/deploy.yml | 67 ++++--------------------------------
1 file changed, 6 insertions(+), 61 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index e0598d17..c7abbba8 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -6,9 +6,6 @@ on:
types:
- completed
branches:
- - main
- - dev
- - demo
- vee-pipeline-fixes
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
@@ -37,6 +34,10 @@ jobs:
run: |
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ - name: Install Azure OpenAI Extension
+ run: |
+ az extension add --upgrade -n openai
+
- name: Select Region with Sufficient OpenAI Quota
id: select_region
run: |
@@ -154,7 +155,6 @@ jobs:
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
-
- name: Get Deployment Output and extract Values
id: get_output
run: |
@@ -202,22 +202,15 @@ jobs:
set -e
echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az monitor log-analytics workspace list command to get the workspace name
log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
-
if [ -z "$log_analytics_workspace_name" ]; then
echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
else
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
fi
-
echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az resource list command to get the OpenAI resource name
openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
-
if [ -z "$openai_resource_name" ]; then
echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
exit 1
@@ -233,17 +226,12 @@ jobs:
set -e
echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
-
- # Get the list of KeyVaults in the specified resource group
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 ${RESOURCE_GROUP_NAME}."
echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
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
@@ -255,8 +243,6 @@ jobs:
fi
done
keyvault_array="$keyvault_array]"
-
- # Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
@@ -283,50 +269,28 @@ jobs:
run: |
set -e
- # Purge Log Analytics Workspace
echo "Purging the Log Analytics Workspace..."
if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
else
echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
fi
-
echo "Log analytics workspace resource purging completed successfully"
-
- name: Wait for resource deletion to complete
if: always()
run: |
-
- # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
-
- # Remove the surrounding square brackets, if they exist
stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
-
- # Convert the comma-separated string into an array
IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
-
- # Append new resources to the array
resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
-
echo "List of resources to check: ${resources_to_check[@]}"
-
- # 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
-
- # Get the list of resources in YAML format again on each retry
resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
-
- # Iterate through the resources to check
for resource in "${resources_to_check[@]}"; do
echo "Checking resource: $resource"
if echo "$resource_list" | grep -q "name: $resource"; then
@@ -336,15 +300,12 @@ jobs:
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" -gt "$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]}
fi
@@ -353,44 +314,30 @@ jobs:
break
fi
done
-
+
- name: Purging the Resources
if: always()
run: |
set -e
-
echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
-
- # Purge OpenAI Resource
echo "Purging the OpenAI Resource..."
if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.SELECTED_REGION }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
fi
-
- # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
-
- # Remove the surrounding square brackets, if they exist
stripped_keyvaults=$(echo "$KEYVAULTS" | 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
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..."
- # Purge the KeyVault
if az keyvault purge --name "$keyvault_name" --no-wait; then
- echo "Successfully purged KeyVault '$keyvault_name'."
+ echo "Successfully purged KeyVault '$keyvault_name'."
else
echo "Failed to purge KeyVault '$keyvault_name'."
fi
@@ -404,14 +351,12 @@ jobs:
if: failure() || needs.deploy.result == 'failure'
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
-
EMAIL_BODY=$(cat <Dear Team,
We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
}
EOF
)
-
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
From 292587579324e7211a504d92ac86f658a7a5bfb3 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 07:52:44 +0530
Subject: [PATCH 03/40] pipeline changes
---
.github/workflows/build-docker-images.yml | 4 +-
.github/workflows/deploy.yml | 125 +++++++++++++++-------
.github/workflows/test.yml | 8 +-
3 files changed, 94 insertions(+), 43 deletions(-)
diff --git a/.github/workflows/build-docker-images.yml b/.github/workflows/build-docker-images.yml
index 7519d620..df6213c6 100644
--- a/.github/workflows/build-docker-images.yml
+++ b/.github/workflows/build-docker-images.yml
@@ -7,12 +7,14 @@ on:
- dev
- demo
- hotfix
+ - vee-pipeline-fixes
pull_request:
branches:
- main
- dev
- demo
- hotfix
+ - vee-pipeline-fixes
types:
- opened
- ready_for_review
@@ -39,5 +41,5 @@ jobs:
password_secret: ${{ matrix.password_secret }}
app_name: ${{ matrix.app_name }}
dockerfile: ${{ matrix.dockerfile }}
- push: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' }}
+ push: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' || github.ref_name == 'vee-pipeline-fixes' }}
secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index c7abbba8..dac5b994 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,15 +1,15 @@
name: Deploy-Test-Cleanup Pipeline
on:
- workflow_run:
- workflows: ["Build Docker and Optional Push"]
- types:
- - completed
- branches:
- - vee-pipeline-fixes
- schedule:
- - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
- workflow_dispatch:
+ workflow_run:
+ workflows: ["Build Docker and Optional Push"]
+ types:
+ - completed
+ branches:
+ - vee-pipeline-fixes
+ schedule:
+ - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
+ workflow_dispatch:
env:
GPT_MIN_CAPACITY: 150
@@ -34,32 +34,22 @@ jobs:
run: |
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
- - name: Install Azure OpenAI Extension
+ - name: Run Quota Check
+ id: quota-check
run: |
- az extension add --upgrade -n openai
-
- - name: Select Region with Sufficient OpenAI Quota
- id: select_region
- run: |
- regions=("eastus2" "francecentral" "westus3" "southcentralus")
- required_quota=150
- selected_region=""
- for region in "${regions[@]}"; do
- available_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].limit" -o tsv)
- used_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].used" -o tsv)
- if [[ $((available_quota - used_quota)) -ge $required_quota ]]; then
- selected_region="$region"
- break
+ 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 AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
+ chmod +x scripts/checkquota.sh
+ if ! scripts/checkquota.sh; then
+ # If quota check fails due to insufficient quota, set the flag
+ if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
fi
- done
- if [[ -z "$selected_region" ]]; then
- echo "No region with sufficient quota found."
- echo "QUOTA_FAILED=true" >> $GITHUB_ENV
- exit 1
- else
- echo "Selected region: $selected_region"
- echo "SELECTED_REGION=$selected_region" >> $GITHUB_ENV
- echo "selected_region=$selected_region" >> $GITHUB_OUTPUT
+ exit 1 # Fail the pipeline if any other failure occurs
fi
- name: Send Notification on Quota Failure
@@ -102,7 +92,7 @@ jobs:
rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
if [ "$rg_exists" = "false" ]; then
echo "Resource group does not exist. Creating..."
- az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location ${{ env.SELECTED_REGION }} || { echo "Error creating resource group"; exit 1; }
+ az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location northcentralus || { echo "Error creating resource group"; exit 1; }
else
echo "Resource group already exists."
fi
@@ -140,12 +130,11 @@ jobs:
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="${{ env.SELECTED_REGION }}" \
+ aiDeploymentsLocation="eastus" \
useWafAlignedArchitecture=false \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline"
-
- name: Assign Contributor role to Service Principal
if: always()
run: |
@@ -155,6 +144,7 @@ jobs:
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+
- name: Get Deployment Output and extract Values
id: get_output
run: |
@@ -202,15 +192,22 @@ jobs:
set -e
echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az monitor log-analytics workspace list command to get the workspace name
log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
+
if [ -z "$log_analytics_workspace_name" ]; then
echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
else
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
fi
+
echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az resource list command to get the OpenAI resource name
openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
+
if [ -z "$openai_resource_name" ]; then
echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
exit 1
@@ -226,12 +223,17 @@ jobs:
set -e
echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
+
+ # Get the list of KeyVaults in the specified resource group
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 ${RESOURCE_GROUP_NAME}."
echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
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
@@ -243,6 +245,8 @@ jobs:
fi
done
keyvault_array="$keyvault_array]"
+
+ # Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
@@ -269,28 +273,50 @@ jobs:
run: |
set -e
+ # Purge Log Analytics Workspace
echo "Purging the Log Analytics Workspace..."
if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
else
echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
fi
+
echo "Log analytics workspace resource purging completed successfully"
+
- name: Wait for resource deletion to complete
if: always()
run: |
+
+ # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
+
+ # Remove the surrounding square brackets, if they exist
stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+
+ # Convert the comma-separated string into an array
IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
+
+ # Append new resources to the array
resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
+
echo "List of resources to check: ${resources_to_check[@]}"
+
+ # 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
+
+ # Get the list of resources in YAML format again on each retry
resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
+
+ # Iterate through the resources to check
for resource in "${resources_to_check[@]}"; do
echo "Checking resource: $resource"
if echo "$resource_list" | grep -q "name: $resource"; then
@@ -300,12 +326,15 @@ jobs:
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" -gt "$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]}
fi
@@ -314,30 +343,44 @@ jobs:
break
fi
done
-
+
- name: Purging the Resources
if: always()
run: |
set -e
+
echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
+
+ # Purge OpenAI Resource
echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.SELECTED_REGION }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
fi
+
+ # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
+
+ # Remove the surrounding square brackets, if they exist
stripped_keyvaults=$(echo "$KEYVAULTS" | 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
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..."
+ # Purge the KeyVault
if az keyvault purge --name "$keyvault_name" --no-wait; then
- echo "Successfully purged KeyVault '$keyvault_name'."
+ echo "Successfully purged KeyVault '$keyvault_name'."
else
echo "Failed to purge KeyVault '$keyvault_name'."
fi
@@ -351,12 +394,14 @@ jobs:
if: failure() || needs.deploy.result == 'failure'
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
}
EOF
)
+
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
@@ -365,4 +410,4 @@ jobs:
if: always()
run: |
az logout
- echo "Logged out from Azure."
+ echo "Logged out from Azure."
\ No newline at end of file
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 34a2f24d..4870ae15 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,6 +6,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
pull_request:
types:
- opened
@@ -16,6 +17,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
jobs:
# frontend_tests:
@@ -87,13 +89,15 @@ jobs:
if [ -z "$(find src/tests/backend -type f -name '*_test.py')" ]; then
echo "No backend test files found, skipping backend tests."
echo "skip_backend_tests=true" >> $GITHUB_ENV
+ echo "skip_backend_tests=true" >> $GITHUB_OUTPUT
else
echo "Backend test files found, running tests."
echo "skip_backend_tests=false" >> $GITHUB_ENV
+ echo "skip_backend_tests=false" >> $GITHUB_OUTPUT
fi
- name: Run Backend Tests with Coverage
- if: env.skip_backend_tests == 'false'
+ if: steps.check_backend_tests.outputs.skip_backend_tests == 'false'
run: |
cd src
pytest --cov=. --cov-report=term-missing --cov-report=xml
@@ -101,6 +105,6 @@ jobs:
- name: Skip Backend Tests
- if: env.skip_backend_tests == 'true'
+ if: steps.check_backend_tests.outputs.skip_backend_tests == 'true'
run: |
echo "Skipping backend tests because no test files were found."
From e8582e2c256dd21643263b9568e820749f891d53 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 08:37:42 +0530
Subject: [PATCH 04/40] latest changes adding branach name
---
.github/workflows/build-docker.yml | 2 ++
.github/workflows/deploy.yml | 4 +++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml
index 55da1c59..943107a7 100644
--- a/.github/workflows/build-docker.yml
+++ b/.github/workflows/build-docker.yml
@@ -59,6 +59,8 @@ jobs:
echo "tagname=demo" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref_name }}" == "hotfix" ]]; then
echo "tagname=hotfix" >> $GITHUB_OUTPUT
+ elif [[ "${{ github.ref_name }}" == "vee-pipeline-fixes" ]]; then
+ echo "tagname=vee-pipeline-fixes" >> $GITHUB_OUTPUT
else
echo "tagname=default" >> $GITHUB_OUTPUT
fi
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index dac5b994..13409fa7 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -120,6 +120,8 @@ jobs:
IMAGE_TAG="dev"
elif [[ "${{ env.BRANCH_NAME }}" == "demo" ]]; then
IMAGE_TAG="demo"
+ elif [[ "${{ env.BRANCH_NAME }}" == "vee-pipeline-fixes" ]]; then
+ IMAGE_TAG="vee-pipeline-fixes"
else
IMAGE_TAG="latest"
fi
@@ -194,7 +196,7 @@ jobs:
echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
# Run the az monitor log-analytics workspace list command to get the workspace name
- log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
+ log_analytics_workspace_name=$(az monitor.log-analytics.workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
if [ -z "$log_analytics_workspace_name" ]; then
echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
From fe0119bedb3c9a3de01b1953db7e9c7d76368cdc Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 08:56:56 +0530
Subject: [PATCH 05/40] pipeline changes
---
.github/workflows/deploy.yml | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 13409fa7..57eb6362 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -126,13 +126,17 @@ jobs:
IMAGE_TAG="latest"
fi
+ # Prefer quota-selected region if available
+ EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}"
+ echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
+
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="eastus" \
+ aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
useWafAlignedArchitecture=false \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
@@ -356,7 +360,7 @@ jobs:
# Purge OpenAI Resource
echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.VALID_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
From 91665a2edc7d9f9eb7369adab6d7f868220eccc9 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 09:18:18 +0530
Subject: [PATCH 06/40] fixing of deploy cleanup failure
---
.github/workflows/deploy.yml | 103 +++++++++++++----------------------
1 file changed, 38 insertions(+), 65 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 57eb6362..715266ab 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -21,6 +21,7 @@ jobs:
outputs:
RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }}
+ SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
@@ -126,9 +127,9 @@ jobs:
IMAGE_TAG="latest"
fi
- # Prefer quota-selected region if available
EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}"
echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
+ echo "selected_ai_region=$EFFECTIVE_AI_REGION" >> $GITHUB_OUTPUT
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
@@ -181,6 +182,7 @@ jobs:
runs-on: ubuntu-latest
env:
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
+ AI_REGION: ${{ needs.deploy.outputs.SELECTED_AI_REGION }}
steps:
- name: Setup Azure CLI
run: |
@@ -195,31 +197,22 @@ jobs:
if: always()
id: get_azure_resources
run: |
-
set -e
echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az monitor log-analytics workspace list command to get the workspace name
- log_analytics_workspace_name=$(az monitor.log-analytics.workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
-
- if [ -z "$log_analytics_workspace_name" ]; then
- echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
- else
+ log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv || true)
+ if [ -n "$log_analytics_workspace_name" ]; then
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
- echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
+ echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
+ else
+ echo "No Log Analytics workspace found."
fi
-
echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az resource list command to get the OpenAI resource name
- openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
-
- if [ -z "$openai_resource_name" ]; then
- echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
- exit 1
- else
+ openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv || true)
+ if [ -n "$openai_resource_name" ]; then
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
- echo "OpenAI resource name: ${openai_resource_name}"
+ echo "OpenAI resource name: ${openai_resource_name}"
+ else
+ echo "No OpenAI resource found."
fi
- name: List KeyVaults and Store in Array
@@ -256,22 +249,10 @@ jobs:
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
- - name: Delete Bicep Deployment
+ - name: Delete Bicep Deployment (defer RG deletion to end)
if: always()
run: |
- set -e
- echo "Checking if resource group exists..."
- rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
- if [ "$rg_exists" = "true" ]; then
- echo "Resource group exist. Cleaning..."
- az group delete \
- --name ${{ env.RESOURCE_GROUP_NAME }} \
- --yes \
- --no-wait
- echo "Resource group deleted... ${{ env.RESOURCE_GROUP_NAME }}"
- else
- echo "Resource group does not exists."
- fi
+ echo "Skipping early RG deletion to allow purges to run first."
- name: Purge log analytics workspace
if: always()
@@ -353,48 +334,28 @@ jobs:
- name: Purging the Resources
if: always()
run: |
-
set -e
-
echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
-
- # Purge OpenAI Resource
- echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.VALID_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
- echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
- else
- echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
+ if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
+ echo "Purging the OpenAI Resource (soft-delete) in region ${{ env.AI_REGION }}..."
+ az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge skipped or failed."
fi
-
- # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
-
- # Remove the surrounding square brackets, if they exist
stripped_keyvaults=$(echo "$KEYVAULTS" | 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
- 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
+ kv_trim=$(echo "$keyvault_name" | sed 's/\"//g' | xargs)
+ [ -z "$kv_trim" ] && continue
+ echo "Processing KeyVault: $kv_trim"
+ deleted_vaults=$(az keyvault list-deleted --query "[?name=='$kv_trim']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
if [ "$(echo "$deleted_vaults" | jq length)" -gt 0 ]; then
- echo "KeyVault '$keyvault_name' is soft-deleted. Proceeding to purge..."
- # Purge the KeyVault
- if az keyvault purge --name "$keyvault_name" --no-wait; then
- echo "Successfully purged KeyVault '$keyvault_name'."
- else
- echo "Failed to purge KeyVault '$keyvault_name'."
- fi
+ echo "KeyVault '$kv_trim' soft-deleted. Purging..."
+ az keyvault purge --name "$kv_trim" --no-wait || echo "Failed to purge KeyVault '$kv_trim'"
else
- echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
+ echo "KeyVault '$kv_trim' not soft-deleted. Skipping."
fi
done
- echo "Resource purging completed successfully"
+ echo "Resource purging completed"
- name: Send Notification on Failure
if: failure() || needs.deploy.result == 'failure'
@@ -412,6 +373,18 @@ jobs:
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
+ - name: Final Resource Group Deletion
+ if: always()
+ run: |
+ set -e
+ rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
+ if [ "$rg_exists" = true ]; then
+ echo "Deleting resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+ az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "RG delete command issued."
+ else
+ echo "Resource group already gone."
+ fi
+
- name: Logout from Azure
if: always()
run: |
From f2e029524d56ee07a99db07c422e439178560129 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 09:33:35 +0530
Subject: [PATCH 07/40] fixing cleanup deployment failure
---
.github/workflows/deploy.yml | 182 +++++++++--------------------------
1 file changed, 48 insertions(+), 134 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 715266ab..417ed1ad 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -198,164 +198,85 @@ jobs:
id: get_azure_resources
run: |
set -e
- echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+ echo "Collecting resource identifiers from RG ${{ env.RESOURCE_GROUP_NAME }} before deletion..."
log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv || true)
if [ -n "$log_analytics_workspace_name" ]; then
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
- echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
- else
- echo "No Log Analytics workspace found."
fi
- echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv || true)
if [ -n "$openai_resource_name" ]; then
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
- echo "OpenAI resource name: ${openai_resource_name}"
- else
- echo "No OpenAI resource found."
fi
+ keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
+ if [ -n "$keyvaults" ]; then
+ 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_ENV; fi
+ echo "Snapshot complete."
- - name: List KeyVaults and Store in Array
+ - name: Delete Resource Group (primary deletion)
if: always()
- id: list_keyvaults
run: |
-
set -e
- echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
-
- # Get the list of KeyVaults in the specified resource group
- 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 ${RESOURCE_GROUP_NAME}."
- echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
- 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]"
-
- # Output the formatted array and save it to the environment variable
- echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
- fi
+ echo "Initiating deletion of RG ${{ env.RESOURCE_GROUP_NAME }}..."
+ az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "Delete command issued."
- - name: Delete Bicep Deployment (defer RG deletion to end)
+ - name: Wait for RG deletion propagation
if: always()
run: |
- echo "Skipping early RG deletion to allow purges to run first."
+ set -e
+ echo "Polling for RG deletion..."
+ max_retries=15
+ sleep_interval=20
+ for i in $(seq 1 $max_retries); do
+ exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }} || echo true)
+ if [ "$exists" = false ]; then
+ echo "Resource group deleted (confirmed)."
+ break
+ fi
+ echo "RG still exists (attempt $i). Waiting $sleep_interval s..."
+ sleep $sleep_interval
+ done
- - name: Purge log analytics workspace
+ - name: Purge soft-deleted OpenAI (if any)
if: always()
- id: log_analytics_workspace
run: |
-
set -e
- # Purge Log Analytics Workspace
- echo "Purging the Log Analytics Workspace..."
- if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
- echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
+ if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
+ echo "Attempting purge of soft-deleted OpenAI: ${{ env.OPENAI_RESOURCE_NAME }} in region ${{ env.AI_REGION }}"
+ az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge not available yet or failed (non-fatal)."
else
- echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
+ echo "No OpenAI resource recorded to purge."
fi
- echo "Log analytics workspace resource purging completed successfully"
-
-
- - name: Wait for resource deletion to complete
+ - name: Purge soft-deleted KeyVaults (if any)
if: always()
run: |
-
- # List of keyvaults
+ set -e
KEYVAULTS="${{ env.KEYVAULTS }}"
-
- # Remove the surrounding square brackets, if they exist
- stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
-
- # Convert the comma-separated string into an array
- IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
-
- # Append new resources to the array
- resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
-
- echo "List of resources to check: ${resources_to_check[@]}"
-
- # 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
-
- # Get the list of resources in YAML format again on each retry
- resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
-
- # Iterate through the resources to check
- for resource in "${resources_to_check[@]}"; do
- 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" -gt "$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]}
- fi
+ stripped=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+ IFS=',' read -r -a kvs <<< "$stripped"
+ for raw in "${kvs[@]}"; do
+ kv=$(echo "$raw" | sed 's/\"//g' | xargs)
+ [ -z "$kv" ] && continue
+ echo "Checking soft-delete state for KeyVault: $kv"
+ deleted=$(az keyvault list-deleted --query "[?name=='$kv']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
+ if [ "$(echo "$deleted" | jq length)" -gt 0 ]; then
+ echo "Purging KeyVault $kv ..."
+ az keyvault purge --name "$kv" --no-wait || echo "Failed to purge $kv (non-fatal)"
else
- echo "No resources found. Exiting."
- break
+ echo "KeyVault $kv not soft-deleted; skipping."
fi
done
-
- - name: Purging the Resources
+
+ - name: Purge Log Analytics Workspace (best-effort)
if: always()
run: |
set -e
- echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
- if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
- echo "Purging the OpenAI Resource (soft-delete) in region ${{ env.AI_REGION }}..."
- az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge skipped or failed."
+ if [ -n "${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" ]; then
+ echo "Attempting to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} (best-effort)"
+ az monitor log-analytics workspace delete --force --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --resource-group ${{ env.RESOURCE_GROUP_NAME }} --yes --verbose || echo "Workspace purge not applicable or already gone."
+ else
+ echo "No Log Analytics workspace recorded."
fi
- KEYVAULTS="${{ env.KEYVAULTS }}"
- stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
- IFS=',' read -r -a keyvault_array <<< "$stripped_keyvaults"
- for keyvault_name in "${keyvault_array[@]}"; do
- kv_trim=$(echo "$keyvault_name" | sed 's/\"//g' | xargs)
- [ -z "$kv_trim" ] && continue
- echo "Processing KeyVault: $kv_trim"
- deleted_vaults=$(az keyvault list-deleted --query "[?name=='$kv_trim']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
- if [ "$(echo "$deleted_vaults" | jq length)" -gt 0 ]; then
- echo "KeyVault '$kv_trim' soft-deleted. Purging..."
- az keyvault purge --name "$kv_trim" --no-wait || echo "Failed to purge KeyVault '$kv_trim'"
- else
- echo "KeyVault '$kv_trim' not soft-deleted. Skipping."
- fi
- done
- echo "Resource purging completed"
- name: Send Notification on Failure
if: failure() || needs.deploy.result == 'failure'
@@ -376,14 +297,7 @@ jobs:
- name: Final Resource Group Deletion
if: always()
run: |
- set -e
- rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
- if [ "$rg_exists" = true ]; then
- echo "Deleting resource group ${{ env.RESOURCE_GROUP_NAME }}..."
- az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "RG delete command issued."
- else
- echo "Resource group already gone."
- fi
+ echo "Final RG delete step retained for idempotency; primary deletion already initiated."
- name: Logout from Azure
if: always()
From ebf397f8e5f7cd17e45022afdabb53f765a576b9 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 10:15:47 +0530
Subject: [PATCH 08/40] azure template trigger
---
.github/workflows/azure-dev-validation.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index d5378b5b..38c1ac64 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- main
+ - vee-pipeline-fixes
permissions:
contents: read
id-token: write
@@ -31,4 +32,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 3: Print the result of the validation
- name: Print result
- run: cat ${{ steps.validation.outputs.resultFile }}
+ run: cat ${{ steps.validation.outputs.resultFile }}
From f3144548ecb8efcb8f91b04ac17c5ff9c33023ce Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 10:25:18 +0530
Subject: [PATCH 09/40] azure template validation fix
---
.github/workflows/azure-dev-validation.yml | 89 ++++++++++++++--------
1 file changed, 59 insertions(+), 30 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 38c1ac64..e5d1413d 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -1,35 +1,64 @@
-name: Azure Template Validation
-on:
-# workflow_dispatch:
- push:
- branches:
- - main
- - vee-pipeline-fixes
+name: Azure Template Validation
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - vee-pipeline-fixes
permissions:
contents: read
id-token: write
pull-requests: write
-jobs:
- template_validation_job:
- runs-on: ubuntu-latest
+jobs:
+ template_validation_job:
+ runs-on: ubuntu-latest
+ # Using an environment named 'production' may require approvals; adjust if that caused prior failures.
environment: production
- name: Template validation
- steps:
- # Step 1: Checkout the code from your repository
- - name: Checkout code
- uses: actions/checkout@v4
- # Step 2: Validate the Azure template using microsoft/template-validation-action
- - name: Validate Azure Template
- uses: microsoft/template-validation-action@Latest
- id: validation
- env:
- AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
- AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
- AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
- AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # Step 3: Print the result of the validation
- - name: Print result
- run: cat ${{ steps.validation.outputs.resultFile }}
+ name: Template validation
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Azure Login
+ uses: azure/login@v1
+ with:
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+
+ - name: Validate Azure Template
+ id: validation
+ uses: microsoft/template-validation-action@main
+ env:
+ # These env vars are optional for the action but retained in case the action consumes them.
+ AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
+ AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
+ AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Print validation result
+ if: always()
+ run: |
+ if [ -n "${{ steps.validation.outputs.resultFile }}" ] && [ -f "${{ steps.validation.outputs.resultFile }}" ]; then
+ echo "--- Validation Result File ---"
+ cat "${{ steps.validation.outputs.resultFile }}"
+ else
+ echo "Result file not found (output: '${{ steps.validation.outputs.resultFile }}')." >&2
+ fi
+
+ - name: Fail if validation errors detected
+ run: |
+ file='${{ steps.validation.outputs.resultFile }}'
+ if [ ! -f "$file" ]; then
+ echo "No validation result file produced; failing." >&2
+ exit 1
+ fi
+ # Heuristic: look for common error markers.
+ if grep -Ei '"(status|level)" *: *"error"' "$file" || grep -Ei '\b(error|failed)\b' "$file"; then
+ echo "Errors detected in template validation output." >&2
+ exit 1
+ fi
+ echo "No blocking errors detected in validation output."
From 6302ffc0a8eb4ac609f7bba98d2f30c60dbff134 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 10:45:45 +0530
Subject: [PATCH 10/40] test template validation
---
.github/workflows/azure-dev-validation.yml | 68 +++++++++++++++++-----
1 file changed, 54 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index e5d1413d..3c810b3c 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -12,53 +12,93 @@ permissions:
jobs:
template_validation_job:
runs-on: ubuntu-latest
- # Using an environment named 'production' may require approvals; adjust if that caused prior failures.
- environment: production
+ environment: validation
name: Template validation
steps:
- name: Checkout code
uses: actions/checkout@v4
- - name: Azure Login
+ - name: Pre-flight secret check
+ id: secret_check
+ run: |
+ missing=0
+ for var in AZURE_CLIENT_ID AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID; do
+ if [ -z "${{ secrets[format('{0}', var)] }}" ]; then
+ echo "::error::Required secret $var is missing." >&2
+ missing=1
+ fi
+ done
+ if [ "$missing" -eq 1 ]; then
+ echo "Missing required secrets. Failing early." >&2
+ exit 1
+ fi
+ echo "All required auth secrets present (client secret not required for OIDC)."
+
+ - name: Azure Login (OIDC)
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ - name: Debug Azure context
+ run: |
+ az account show || echo "Could not show account (ensure privileges)" >&2
+ echo "Listing bicep version (if installed):"; az bicep version || true
+ echo "Listing repo root:"; ls -1 . || true
+ echo "Infra directory content:"; ls -1 infra || true
+
- name: Validate Azure Template
id: validation
uses: microsoft/template-validation-action@main
env:
- # These env vars are optional for the action but retained in case the action consumes them.
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
- AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ continue-on-error: true
+
+ - name: Capture validation output
+ id: capture
+ run: |
+ out="${{ steps.validation.outputs.resultFile }}"
+ if [ -n "$out" ] && [ -f "$out" ]; then
+ cp "$out" validation-result.json
+ else
+ echo '{"warning":"No resultFile produced by action"}' > validation-result.json
+ fi
+ echo "result_path=validation-result.json" >> $GITHUB_OUTPUT
- name: Print validation result
if: always()
run: |
- if [ -n "${{ steps.validation.outputs.resultFile }}" ] && [ -f "${{ steps.validation.outputs.resultFile }}" ]; then
- echo "--- Validation Result File ---"
- cat "${{ steps.validation.outputs.resultFile }}"
- else
- echo "Result file not found (output: '${{ steps.validation.outputs.resultFile }}')." >&2
- fi
+ echo "--- validation-result.json ---"
+ cat validation-result.json || echo "No validation-result.json present" >&2
+
+ - name: Upload validation result artifact
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: validation-result
+ path: validation-result.json
+ retention-days: 7
- name: Fail if validation errors detected
run: |
- file='${{ steps.validation.outputs.resultFile }}'
+ file='validation-result.json'
if [ ! -f "$file" ]; then
echo "No validation result file produced; failing." >&2
exit 1
fi
- # Heuristic: look for common error markers.
if grep -Ei '"(status|level)" *: *"error"' "$file" || grep -Ei '\b(error|failed)\b' "$file"; then
echo "Errors detected in template validation output." >&2
+ cat "$file"
+ exit 1
+ fi
+ # Also treat underlying action non-zero exit as failure even if heuristic passes.
+ if [ "${{ steps.validation.outcome }}" = "failure" ]; then
+ echo "Underlying validation action reported failure (steps.validation.outcome)." >&2
exit 1
fi
echo "No blocking errors detected in validation output."
From 4e412588d339239970be70926e35070e41b445ef Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 11:02:52 +0530
Subject: [PATCH 11/40] deploy yml file changes for template validation
---
.github/workflows/deploy.yml | 73 ++++++++++++++++++++++++++----------
1 file changed, 54 insertions(+), 19 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 417ed1ad..b16954f2 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -24,7 +24,7 @@ jobs:
SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Azure CLI
run: |
@@ -38,19 +38,33 @@ jobs:
- name: Run Quota Check
id: quota-check
run: |
+ set -e
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_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
export GPT_MIN_CAPACITY="${{ env.GPT_MIN_CAPACITY }}"
export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
chmod +x scripts/checkquota.sh
- if ! scripts/checkquota.sh; then
- # If quota check fails due to insufficient quota, set the flag
- if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
- echo "QUOTA_FAILED=true" >> $GITHUB_ENV
- fi
- exit 1 # Fail the pipeline if any other failure occurs
+ echo "Running quota script..."
+ # Capture stdout & stderr
+ if ! bash -c './scripts/checkquota.sh' | tee quota.out; then
+ echo "Quota script exited non-zero." >&2
+ fi
+ echo "--- Quota Script Output (truncated) ---"
+ head -100 quota.out || true
+ # Parse VALID_REGION if present
+ REGION_LINE=$(grep -E '^VALID_REGION=' quota.out || true)
+ if [ -n "$REGION_LINE" ]; then
+ echo "$REGION_LINE" >> $GITHUB_ENV
+ echo "Captured $REGION_LINE"
+ fi
+ if grep -qi 'No region with sufficient quota found' quota.out; then
+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
+ echo "Quota failure detected: no region with sufficient quota." >&2
+ fi
+ if ! grep -q '^VALID_REGION=' quota.out; then
+ echo "WARNING: VALID_REGION not found; will fallback later." >&2
fi
- name: Send Notification on Quota Failure
@@ -75,6 +89,14 @@ jobs:
- name: Install Bicep CLI
run: az bicep install
+ - name: Install jq
+ run: |
+ if ! command -v jq >/dev/null 2>&1; then
+ sudo apt-get update -y
+ sudo apt-get install -y jq
+ fi
+ jq --version
+
- name: Generate Resource Group Name
id: generate_rg_name
run: |
@@ -127,10 +149,14 @@ jobs:
IMAGE_TAG="latest"
fi
- EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}"
+ EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}" # VALID_REGION exported earlier if quota script succeeded
echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
echo "selected_ai_region=$EFFECTIVE_AI_REGION" >> $GITHUB_OUTPUT
+ echo "Resource Group: ${{ env.RESOURCE_GROUP_NAME }} (Created in northcentralus)"
+ echo "Solution Prefix: ${{ env.SOLUTION_PREFIX }}"
+ echo "Image Tag: ${IMAGE_TAG}"
+
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
@@ -142,26 +168,35 @@ jobs:
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline"
- - name: Assign Contributor role to Service Principal
+ - name: Assign Contributor role to Service Principal (Idempotent)
if: always()
run: |
- echo "Assigning Contributor role to SPN for RG: ${{ env.RESOURCE_GROUP_NAME }}"
- az role assignment create \
- --assignee ${{ secrets.AZURE_CLIENT_ID }} \
- --role "Contributor" \
- --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+ scope=/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+ echo "Ensuring Contributor role on scope: $scope"
+ existing=$(az role assignment list --assignee ${{ secrets.AZURE_CLIENT_ID }} --scope "$scope" --query '[0].id' -o tsv || true)
+ if [ -n "$existing" ]; then
+ echo "Role assignment already exists: $existing"
+ else
+ az role assignment create --assignee ${{ secrets.AZURE_CLIENT_ID }} --role "Contributor" --scope "$scope" || echo "Non-fatal: role assignment create failed (possibly permission or propagation delay)."
+ fi
- name: Get Deployment Output and extract Values
id: get_output
run: |
set -e
- echo "Fetching deployment output..."
+ echo "Fetching deployment outputs..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
- echo "Extracting deployment output..."
- WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
+ echo "Raw outputs JSON length: $(echo "$BICEP_OUTPUT" | wc -c)"
+ # Correct output key is WEB_APP_URL (verified in infra/main.bicep)
+ WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r '.WEB_APP_URL.value // empty')
+ if [ -z "$WEBAPP_URL" ]; then
+ echo "::error::WEB_APP_URL output missing or empty. Full outputs below:" >&2
+ echo "$BICEP_OUTPUT" >&2
+ exit 1
+ fi
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment output: $BICEP_OUTPUT"
+ echo "Resolved WEB_APP_URL: $WEBAPP_URL"
- name: Logout from Azure
if: always()
From ca177febe270e26a9ac6a359f0e2d69a703f90c2 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 12:00:05 +0530
Subject: [PATCH 12/40] revert deploy yml file
---
.github/workflows/deploy.yml | 67 ++++++++++--------------------------
1 file changed, 19 insertions(+), 48 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index b16954f2..d7211388 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -24,7 +24,7 @@ jobs:
SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
- uses: actions/checkout@v4
+ uses: actions/checkout@v3
- name: Setup Azure CLI
run: |
@@ -38,33 +38,19 @@ jobs:
- name: Run Quota Check
id: quota-check
run: |
- set -e
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_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
export GPT_MIN_CAPACITY="${{ env.GPT_MIN_CAPACITY }}"
export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
chmod +x scripts/checkquota.sh
- echo "Running quota script..."
- # Capture stdout & stderr
- if ! bash -c './scripts/checkquota.sh' | tee quota.out; then
- echo "Quota script exited non-zero." >&2
- fi
- echo "--- Quota Script Output (truncated) ---"
- head -100 quota.out || true
- # Parse VALID_REGION if present
- REGION_LINE=$(grep -E '^VALID_REGION=' quota.out || true)
- if [ -n "$REGION_LINE" ]; then
- echo "$REGION_LINE" >> $GITHUB_ENV
- echo "Captured $REGION_LINE"
- fi
- if grep -qi 'No region with sufficient quota found' quota.out; then
- echo "QUOTA_FAILED=true" >> $GITHUB_ENV
- echo "Quota failure detected: no region with sufficient quota." >&2
- fi
- if ! grep -q '^VALID_REGION=' quota.out; then
- echo "WARNING: VALID_REGION not found; will fallback later." >&2
+ if ! scripts/checkquota.sh; then
+ # If quota check fails due to insufficient quota, set the flag
+ if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
+ fi
+ exit 1 # Fail the pipeline if any other failure occurs
fi
- name: Send Notification on Quota Failure
@@ -89,13 +75,7 @@ jobs:
- name: Install Bicep CLI
run: az bicep install
- - name: Install jq
- run: |
- if ! command -v jq >/dev/null 2>&1; then
- sudo apt-get update -y
- sudo apt-get install -y jq
- fi
- jq --version
+ # reverted: jq explicit installation step removed
- name: Generate Resource Group Name
id: generate_rg_name
@@ -168,35 +148,26 @@ jobs:
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline"
- - name: Assign Contributor role to Service Principal (Idempotent)
+ - name: Assign Contributor role to Service Principal
if: always()
run: |
- scope=/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
- echo "Ensuring Contributor role on scope: $scope"
- existing=$(az role assignment list --assignee ${{ secrets.AZURE_CLIENT_ID }} --scope "$scope" --query '[0].id' -o tsv || true)
- if [ -n "$existing" ]; then
- echo "Role assignment already exists: $existing"
- else
- az role assignment create --assignee ${{ secrets.AZURE_CLIENT_ID }} --role "Contributor" --scope "$scope" || echo "Non-fatal: role assignment create failed (possibly permission or propagation delay)."
- fi
+ echo "Assigning Contributor role to SPN for RG: ${{ env.RESOURCE_GROUP_NAME }}"
+ az role assignment create \
+ --assignee ${{ secrets.AZURE_CLIENT_ID }} \
+ --role "Contributor" \
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
- name: Get Deployment Output and extract Values
id: get_output
run: |
set -e
- echo "Fetching deployment outputs..."
+ echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
- echo "Raw outputs JSON length: $(echo "$BICEP_OUTPUT" | wc -c)"
- # Correct output key is WEB_APP_URL (verified in infra/main.bicep)
- WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r '.WEB_APP_URL.value // empty')
- if [ -z "$WEBAPP_URL" ]; then
- echo "::error::WEB_APP_URL output missing or empty. Full outputs below:" >&2
- echo "$BICEP_OUTPUT" >&2
- exit 1
- fi
+ echo "Extracting deployment output..."
+ WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Resolved WEB_APP_URL: $WEBAPP_URL"
+ echo "Deployment output: $BICEP_OUTPUT"
- name: Logout from Azure
if: always()
From 4c72c2540fe45eb751278b974bf0acf703cfb2a9 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 13:35:16 +0530
Subject: [PATCH 13/40] added list key val step
---
.github/workflows/deploy.yml | 40 +++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index d7211388..582f9e0d 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -165,9 +165,15 @@ jobs:
echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
echo "Extracting deployment output..."
- WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
+ WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r '.WEB_APP_URL.value')
+ if [ -z "$WEBAPP_URL" ] || [ "$WEBAPP_URL" = "null" ]; then
+ echo "WEB_APP_URL not found in deployment outputs" >&2
+ echo "Full outputs: $BICEP_OUTPUT" >&2
+ exit 1
+ fi
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment output: $BICEP_OUTPUT"
+ echo "Deployment output (truncated for log clarity):"
+ echo "$BICEP_OUTPUT" | head -c 2000
- name: Logout from Azure
if: always()
@@ -213,11 +219,35 @@ jobs:
if [ -n "$openai_resource_name" ]; then
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
fi
- keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
- if [ -n "$keyvaults" ]; then
- 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_ENV; fi
echo "Snapshot complete."
+ - name: List KeyVaults and Store in Array
+ if: always()
+ id: list_keyvaults
+ run: |
+ set -e
+ echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
+ keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
+ if [ -z "$keyvaults" ]; then
+ echo "No KeyVaults found in resource group ${RESOURCE_GROUP_NAME}."
+ echo "KEYVAULTS=[]" >> $GITHUB_ENV
+ else
+ echo "KeyVaults found: $keyvaults"
+ 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_ENV
+ fi
+ echo "Stored KeyVault array in KEYVAULTS environment variable."
+
- name: Delete Resource Group (primary deletion)
if: always()
run: |
From 30223e72682dcac56084517652181a51b3986b19 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 14:37:03 +0530
Subject: [PATCH 14/40] deploy failed fix
---
.github/workflows/deploy.yml | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 582f9e0d..acc4774f 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -165,14 +165,19 @@ jobs:
echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
echo "Extracting deployment output..."
- WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r '.WEB_APP_URL.value')
+ echo "Available output keys:"
+ echo "$BICEP_OUTPUT" | jq -r 'keys | join(", ")'
+ # Case-insensitive lookup for WEB_APP_URL because deployment outputs returned inconsistent casing previously
+ WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r 'to_entries | map(select((.key|ascii_upcase)=="WEB_APP_URL")) | .[0].value.value // empty')
if [ -z "$WEBAPP_URL" ] || [ "$WEBAPP_URL" = "null" ]; then
- echo "WEB_APP_URL not found in deployment outputs" >&2
- echo "Full outputs: $BICEP_OUTPUT" >&2
+ echo "WEB_APP_URL not found in deployment outputs (case-insensitive scan)" >&2
+ echo "Full outputs JSON follows for troubleshooting:" >&2
+ echo "$BICEP_OUTPUT" >&2
exit 1
fi
+ echo "Resolved WEBAPP_URL: $WEBAPP_URL"
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment output (truncated for log clarity):"
+ echo "Deployment outputs (truncated):"
echo "$BICEP_OUTPUT" | head -c 2000
- name: Logout from Azure
From d6ea884b70e4a38da59597bd5544eeefa528e4ab Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 16:08:16 +0530
Subject: [PATCH 15/40] validation template fix
---
.github/workflows/azure-dev-validation.yml | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 3c810b3c..8704f5de 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -21,13 +21,12 @@ jobs:
- name: Pre-flight secret check
id: secret_check
run: |
+ # GitHub Actions expressions are evaluated before the shell loop runs, so we cannot
+ # index into secrets dynamically like secrets[format('{0}', var)]. Instead, check each explicitly.
missing=0
- for var in AZURE_CLIENT_ID AZURE_TENANT_ID AZURE_SUBSCRIPTION_ID; do
- if [ -z "${{ secrets[format('{0}', var)] }}" ]; then
- echo "::error::Required secret $var is missing." >&2
- missing=1
- fi
- done
+ if [ -z "${{ secrets.AZURE_CLIENT_ID }}" ]; then echo "::error::Required secret AZURE_CLIENT_ID is missing." >&2; missing=1; fi
+ if [ -z "${{ secrets.AZURE_TENANT_ID }}" ]; then echo "::error::Required secret AZURE_TENANT_ID is missing." >&2; missing=1; fi
+ if [ -z "${{ secrets.AZURE_SUBSCRIPTION_ID }}" ]; then echo "::error::Required secret AZURE_SUBSCRIPTION_ID is missing." >&2; missing=1; fi
if [ "$missing" -eq 1 ]; then
echo "Missing required secrets. Failing early." >&2
exit 1
From 9f1296eda7712ea2e887fe04407bc62b886bb7d1 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 16:12:38 +0530
Subject: [PATCH 16/40] template fix
---
.github/workflows/azure-dev-validation.yml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 8704f5de..01213484 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -27,12 +27,18 @@ jobs:
if [ -z "${{ secrets.AZURE_CLIENT_ID }}" ]; then echo "::error::Required secret AZURE_CLIENT_ID is missing." >&2; missing=1; fi
if [ -z "${{ secrets.AZURE_TENANT_ID }}" ]; then echo "::error::Required secret AZURE_TENANT_ID is missing." >&2; missing=1; fi
if [ -z "${{ secrets.AZURE_SUBSCRIPTION_ID }}" ]; then echo "::error::Required secret AZURE_SUBSCRIPTION_ID is missing." >&2; missing=1; fi
+ if [ -z "${{ secrets.AZURE_LOCATION }}" ]; then echo "::warning::AZURE_LOCATION not set; defaulting to eastus for validation context."; echo "AZURE_LOCATION=eastus" >> $GITHUB_ENV; else echo "AZURE_LOCATION=${{ secrets.AZURE_LOCATION }}" >> $GITHUB_ENV; fi
if [ "$missing" -eq 1 ]; then
echo "Missing required secrets. Failing early." >&2
exit 1
fi
echo "All required auth secrets present (client secret not required for OIDC)."
+ - name: Ensure Bicep CLI installed
+ run: |
+ az bicep install || true
+ echo "Bicep version:"; az bicep version || echo "Bicep not available" >&2
+
- name: Azure Login (OIDC)
uses: azure/login@v1
with:
@@ -43,9 +49,10 @@ jobs:
- name: Debug Azure context
run: |
az account show || echo "Could not show account (ensure privileges)" >&2
- echo "Listing bicep version (if installed):"; az bicep version || true
+ echo "Listing bicep version:"; az bicep version || true
echo "Listing repo root:"; ls -1 . || true
echo "Infra directory content:"; ls -1 infra || true
+ echo "Resolved AZURE_LOCATION: ${AZURE_LOCATION:-unset}"
- name: Validate Azure Template
id: validation
From bfa33aac78b30b07e077ab0c2cf21992078c5a66 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 16:18:05 +0530
Subject: [PATCH 17/40] login fix
---
.github/workflows/azure-dev-validation.yml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 01213484..20f7651c 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -46,6 +46,23 @@ jobs:
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ - name: Fallback Azure Login (Client Secret)
+ if: failure() && secrets.AZURE_CLIENT_SECRET != ''
+ run: |
+ echo "OIDC login failed; attempting client secret login fallback." >&2
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} || {
+ echo "Client secret fallback login also failed." >&2; exit 1; }
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || true
+
+ - name: Post-login diagnostics
+ if: always()
+ run: |
+ echo "Login diagnostics:"
+ az account show || echo "Account show failed" >&2
+ echo "Listing subscriptions (top 5):"; az account list --query '[].{name:name,id:id}' -o table | head -n 7 || true
+ echo "Active tenant: ${{ secrets.AZURE_TENANT_ID }}"
+ echo "Client ID suffix: $(echo '${{ secrets.AZURE_CLIENT_ID }}' | tail -c 6)"
+
- name: Debug Azure context
run: |
az account show || echo "Could not show account (ensure privileges)" >&2
From a9201fa3c9a5f269707921b6b9b90ce911e80bdb Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 16:22:30 +0530
Subject: [PATCH 18/40] login fix template
---
.github/workflows/azure-dev-validation.yml | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 20f7651c..681196a0 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -47,8 +47,14 @@ jobs:
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Fallback Azure Login (Client Secret)
- if: failure() && secrets.AZURE_CLIENT_SECRET != ''
+ if: failure()
+ env:
+ HAS_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET != '' }}
run: |
+ if [ "${HAS_CLIENT_SECRET}" != "true" ]; then
+ echo "OIDC login failed and no client secret available for fallback." >&2
+ exit 1
+ fi
echo "OIDC login failed; attempting client secret login fallback." >&2
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} || {
echo "Client secret fallback login also failed." >&2; exit 1; }
From 427d54a1fda86873df8d41c8c3a68bfe58905811 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 17:05:57 +0530
Subject: [PATCH 19/40] template fix login
---
.github/workflows/azure-dev-validation.yml | 40 +++++++++++++---------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 681196a0..d2025138 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -14,6 +14,8 @@ jobs:
runs-on: ubuntu-latest
environment: validation
name: Template validation
+ env:
+ AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -37,28 +39,32 @@ jobs:
- name: Ensure Bicep CLI installed
run: |
az bicep install || true
- echo "Bicep version:"; az bicep version || echo "Bicep not available" >&2
-
- - name: Azure Login (OIDC)
+ - name: Azure Login (Service Principal Client Secret)
+ if: ${{ env.AZURE_CLIENT_SECRET != '' }}
+ run: |
+ echo "Using service principal client secret authentication path."
+ 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 }}
+ --tenant ${{ secrets.AZURE_TENANT_ID }}
+ - name: Azure Login (OIDC) (no client secret present)
+ if: ${{ env.AZURE_CLIENT_SECRET == '' }}
uses: azure/login@v1
with:
- client-id: ${{ secrets.AZURE_CLIENT_ID }}
- tenant-id: ${{ secrets.AZURE_TENANT_ID }}
- subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ continue-on-error: false
- - name: Fallback Azure Login (Client Secret)
- if: failure()
- env:
- HAS_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET != '' }}
+ - name: Auth Mode Announcement
run: |
- if [ "${HAS_CLIENT_SECRET}" != "true" ]; then
- echo "OIDC login failed and no client secret available for fallback." >&2
- exit 1
+ if [ -n "${{ secrets.AZURE_CLIENT_SECRET }}" ]; then
+ echo "Auth mode: client secret (SP). OIDC skipped."
+ else
+ echo "Auth mode: OIDC (no client secret set). Ensure federated credential exists for environment 'validation'."
fi
- echo "OIDC login failed; attempting client secret login fallback." >&2
- az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} || {
- echo "Client secret fallback login also failed." >&2; exit 1; }
- az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || true
- name: Post-login diagnostics
if: always()
From d01abcfd1c1977838295e0c8ebb39f289141334f Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 17:14:22 +0530
Subject: [PATCH 20/40] latest fix
---
.github/workflows/azure-dev-validation.yml | 165 ++++-----------------
1 file changed, 30 insertions(+), 135 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index d2025138..8f95e7c7 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -1,139 +1,34 @@
-name: Azure Template Validation
-on:
- workflow_dispatch:
- push:
- branches:
- - main
- - vee-pipeline-fixes
+name: Azure Template Validation
+on:
+# workflow_dispatch:
+ push:
+ branches:
+ - main
permissions:
contents: read
id-token: write
pull-requests: write
-jobs:
- template_validation_job:
- runs-on: ubuntu-latest
- environment: validation
- name: Template validation
- env:
- AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Pre-flight secret check
- id: secret_check
- run: |
- # GitHub Actions expressions are evaluated before the shell loop runs, so we cannot
- # index into secrets dynamically like secrets[format('{0}', var)]. Instead, check each explicitly.
- missing=0
- if [ -z "${{ secrets.AZURE_CLIENT_ID }}" ]; then echo "::error::Required secret AZURE_CLIENT_ID is missing." >&2; missing=1; fi
- if [ -z "${{ secrets.AZURE_TENANT_ID }}" ]; then echo "::error::Required secret AZURE_TENANT_ID is missing." >&2; missing=1; fi
- if [ -z "${{ secrets.AZURE_SUBSCRIPTION_ID }}" ]; then echo "::error::Required secret AZURE_SUBSCRIPTION_ID is missing." >&2; missing=1; fi
- if [ -z "${{ secrets.AZURE_LOCATION }}" ]; then echo "::warning::AZURE_LOCATION not set; defaulting to eastus for validation context."; echo "AZURE_LOCATION=eastus" >> $GITHUB_ENV; else echo "AZURE_LOCATION=${{ secrets.AZURE_LOCATION }}" >> $GITHUB_ENV; fi
- if [ "$missing" -eq 1 ]; then
- echo "Missing required secrets. Failing early." >&2
- exit 1
- fi
- echo "All required auth secrets present (client secret not required for OIDC)."
-
- - name: Ensure Bicep CLI installed
- run: |
- az bicep install || true
- - name: Azure Login (Service Principal Client Secret)
- if: ${{ env.AZURE_CLIENT_SECRET != '' }}
- run: |
- echo "Using service principal client secret authentication path."
- 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 }}
- --tenant ${{ secrets.AZURE_TENANT_ID }}
- - name: Azure Login (OIDC) (no client secret present)
- if: ${{ env.AZURE_CLIENT_SECRET == '' }}
- uses: azure/login@v1
- with:
- client-id: ${{ secrets.AZURE_CLIENT_ID }}
- tenant-id: ${{ secrets.AZURE_TENANT_ID }}
- subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- continue-on-error: false
-
- - name: Auth Mode Announcement
- run: |
- if [ -n "${{ secrets.AZURE_CLIENT_SECRET }}" ]; then
- echo "Auth mode: client secret (SP). OIDC skipped."
- else
- echo "Auth mode: OIDC (no client secret set). Ensure federated credential exists for environment 'validation'."
- fi
-
- - name: Post-login diagnostics
- if: always()
- run: |
- echo "Login diagnostics:"
- az account show || echo "Account show failed" >&2
- echo "Listing subscriptions (top 5):"; az account list --query '[].{name:name,id:id}' -o table | head -n 7 || true
- echo "Active tenant: ${{ secrets.AZURE_TENANT_ID }}"
- echo "Client ID suffix: $(echo '${{ secrets.AZURE_CLIENT_ID }}' | tail -c 6)"
-
- - name: Debug Azure context
- run: |
- az account show || echo "Could not show account (ensure privileges)" >&2
- echo "Listing bicep version:"; az bicep version || true
- echo "Listing repo root:"; ls -1 . || true
- echo "Infra directory content:"; ls -1 infra || true
- echo "Resolved AZURE_LOCATION: ${AZURE_LOCATION:-unset}"
-
- - name: Validate Azure Template
- id: validation
- uses: microsoft/template-validation-action@main
- env:
- AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
- AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
- AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- continue-on-error: true
-
- - name: Capture validation output
- id: capture
- run: |
- out="${{ steps.validation.outputs.resultFile }}"
- if [ -n "$out" ] && [ -f "$out" ]; then
- cp "$out" validation-result.json
- else
- echo '{"warning":"No resultFile produced by action"}' > validation-result.json
- fi
- echo "result_path=validation-result.json" >> $GITHUB_OUTPUT
-
- - name: Print validation result
- if: always()
- run: |
- echo "--- validation-result.json ---"
- cat validation-result.json || echo "No validation-result.json present" >&2
-
- - name: Upload validation result artifact
- if: always()
- uses: actions/upload-artifact@v4
- with:
- name: validation-result
- path: validation-result.json
- retention-days: 7
-
- - name: Fail if validation errors detected
- run: |
- file='validation-result.json'
- if [ ! -f "$file" ]; then
- echo "No validation result file produced; failing." >&2
- exit 1
- fi
- if grep -Ei '"(status|level)" *: *"error"' "$file" || grep -Ei '\b(error|failed)\b' "$file"; then
- echo "Errors detected in template validation output." >&2
- cat "$file"
- exit 1
- fi
- # Also treat underlying action non-zero exit as failure even if heuristic passes.
- if [ "${{ steps.validation.outcome }}" = "failure" ]; then
- echo "Underlying validation action reported failure (steps.validation.outcome)." >&2
- exit 1
- fi
- echo "No blocking errors detected in validation output."
+jobs:
+ template_validation_job:
+ runs-on: ubuntu-latest
+ environment: dev
+ name: Template validation
+ steps:
+ # Step 1: Checkout the code from your repository
+ - name: Checkout code
+ uses: actions/checkout@v4
+ # Step 2: Validate the Azure template using microsoft/template-validation-action
+ - name: Validate Azure Template
+ uses: microsoft/template-validation-action@v0.3.5
+ id: validation
+ env:
+ AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
+ AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
+ AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # Step 3: Print the result of the validation
+ - name: Print result
+ run: cat ${{ steps.validation.outputs.resultFile }}
\ No newline at end of file
From de9cc7955e834f8c562c0e410a9d18fe33d412a2 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 18 Sep 2025 17:20:00 +0530
Subject: [PATCH 21/40] add branach name for trigger
---
.github/workflows/azure-dev-validation.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 8f95e7c7..7e558f48 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- main
+ - vee-pipeline-fixes
permissions:
contents: read
id-token: write
From 7e235fa6d31ecb3099780ff59ac947d08901be4b Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 23 Sep 2025 10:34:03 +0530
Subject: [PATCH 22/40] Removing Local Branch Name in All Pipelines
---
.github/workflows/azure-dev-validation.yml | 1 -
.github/workflows/build-docker-images.yml | 4 +---
.github/workflows/build-docker.yml | 2 --
.github/workflows/deploy.yml | 6 +++---
.github/workflows/test.yml | 2 --
5 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 7e558f48..8f95e7c7 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -4,7 +4,6 @@ on:
push:
branches:
- main
- - vee-pipeline-fixes
permissions:
contents: read
id-token: write
diff --git a/.github/workflows/build-docker-images.yml b/.github/workflows/build-docker-images.yml
index df6213c6..7519d620 100644
--- a/.github/workflows/build-docker-images.yml
+++ b/.github/workflows/build-docker-images.yml
@@ -7,14 +7,12 @@ on:
- dev
- demo
- hotfix
- - vee-pipeline-fixes
pull_request:
branches:
- main
- dev
- demo
- hotfix
- - vee-pipeline-fixes
types:
- opened
- ready_for_review
@@ -41,5 +39,5 @@ jobs:
password_secret: ${{ matrix.password_secret }}
app_name: ${{ matrix.app_name }}
dockerfile: ${{ matrix.dockerfile }}
- push: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' || github.ref_name == 'vee-pipeline-fixes' }}
+ push: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' }}
secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml
index 943107a7..55da1c59 100644
--- a/.github/workflows/build-docker.yml
+++ b/.github/workflows/build-docker.yml
@@ -59,8 +59,6 @@ jobs:
echo "tagname=demo" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref_name }}" == "hotfix" ]]; then
echo "tagname=hotfix" >> $GITHUB_OUTPUT
- elif [[ "${{ github.ref_name }}" == "vee-pipeline-fixes" ]]; then
- echo "tagname=vee-pipeline-fixes" >> $GITHUB_OUTPUT
else
echo "tagname=default" >> $GITHUB_OUTPUT
fi
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index acc4774f..89bef742 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -6,7 +6,9 @@ on:
types:
- completed
branches:
- - vee-pipeline-fixes
+ - main
+ - dev
+ - demo
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
workflow_dispatch:
@@ -123,8 +125,6 @@ jobs:
IMAGE_TAG="dev"
elif [[ "${{ env.BRANCH_NAME }}" == "demo" ]]; then
IMAGE_TAG="demo"
- elif [[ "${{ env.BRANCH_NAME }}" == "vee-pipeline-fixes" ]]; then
- IMAGE_TAG="vee-pipeline-fixes"
else
IMAGE_TAG="latest"
fi
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4870ae15..1c3216e7 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,7 +6,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
pull_request:
types:
- opened
@@ -17,7 +16,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
jobs:
# frontend_tests:
From 94d25da6c7c2d6ec4c6e371e3fbb5e72e9958bc3 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 23 Sep 2025 10:44:46 +0530
Subject: [PATCH 23/40] dev to production change
---
.github/workflows/azure-dev-validation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 8f95e7c7..2619e449 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -11,7 +11,7 @@ permissions:
jobs:
template_validation_job:
runs-on: ubuntu-latest
- environment: dev
+ environment: production
name: Template validation
steps:
# Step 1: Checkout the code from your repository
From 332ea2b87c9ec53b0c984dbdc14f5e590cf982bb Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Wed, 24 Sep 2025 16:57:29 +0530
Subject: [PATCH 24/40] removing waf param
---
.github/workflows/azure-dev-validation.yml | 3 +-
.github/workflows/deploy.yml | 239 +++++++++++----------
.github/workflows/test.yml | 10 +-
3 files changed, 138 insertions(+), 114 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 2619e449..fc98fd7d 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- main
+ - vee-pipeline-fixes
permissions:
contents: read
id-token: write
@@ -19,7 +20,7 @@ jobs:
uses: actions/checkout@v4
# Step 2: Validate the Azure template using microsoft/template-validation-action
- name: Validate Azure Template
- uses: microsoft/template-validation-action@v0.3.5
+ uses: microsoft/template-validation-action@Latest
id: validation
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 89bef742..50c1b378 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -9,6 +9,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
workflow_dispatch:
@@ -23,7 +24,6 @@ jobs:
outputs:
RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }}
- SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
@@ -32,11 +32,9 @@ jobs:
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 }}
-
- name: Run Quota Check
id: quota-check
run: |
@@ -54,7 +52,6 @@ jobs:
fi
exit 1 # Fail the pipeline if any other failure occurs
fi
-
- name: Send Notification on Quota Failure
if: env.QUOTA_FAILED == 'true'
run: |
@@ -65,11 +62,9 @@ jobs:
}
EOF
)
-
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
-
- name: Fail Pipeline if Quota Check Fails
if: env.QUOTA_FAILED == 'true'
run: exit 1
@@ -77,8 +72,6 @@ jobs:
- name: Install Bicep CLI
run: az bicep install
- # reverted: jq explicit installation step removed
-
- name: Generate Resource Group Name
id: generate_rg_name
run: |
@@ -88,7 +81,6 @@ jobs:
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}"
-
- name: Check and Create Resource Group
id: check_create_rg
run: |
@@ -102,7 +94,6 @@ jobs:
echo "Resource group already exists."
fi
echo "RESOURCE_GROUP_NAME=${{ env.RESOURCE_GROUP_NAME }}" >> $GITHUB_OUTPUT
-
- name: Generate Unique Solution Prefix
id: generate_solution_prefix
run: |
@@ -113,7 +104,6 @@ jobs:
UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
-
- name: Deploy Bicep Template
id: deploy
run: |
@@ -128,25 +118,15 @@ jobs:
else
IMAGE_TAG="latest"
fi
-
- EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}" # VALID_REGION exported earlier if quota script succeeded
- echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
- echo "selected_ai_region=$EFFECTIVE_AI_REGION" >> $GITHUB_OUTPUT
-
- echo "Resource Group: ${{ env.RESOURCE_GROUP_NAME }} (Created in northcentralus)"
- echo "Solution Prefix: ${{ env.SOLUTION_PREFIX }}"
- echo "Image Tag: ${IMAGE_TAG}"
-
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
- useWafAlignedArchitecture=false \
+ aiDeploymentsLocation="eastus" \
capacity=${{ env.GPT_MIN_CAPACITY }} \
- imageVersion="${IMAGE_TAG}" \
+ imageVersion="${IMAGE_TAG}"\
createdBy="Pipeline"
- name: Assign Contributor role to Service Principal
if: always()
@@ -156,8 +136,6 @@ jobs:
--assignee ${{ secrets.AZURE_CLIENT_ID }} \
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
-
-
- name: Get Deployment Output and extract Values
id: get_output
run: |
@@ -165,27 +143,14 @@ jobs:
echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
echo "Extracting deployment output..."
- echo "Available output keys:"
- echo "$BICEP_OUTPUT" | jq -r 'keys | join(", ")'
- # Case-insensitive lookup for WEB_APP_URL because deployment outputs returned inconsistent casing previously
- WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r 'to_entries | map(select((.key|ascii_upcase)=="WEB_APP_URL")) | .[0].value.value // empty')
- if [ -z "$WEBAPP_URL" ] || [ "$WEBAPP_URL" = "null" ]; then
- echo "WEB_APP_URL not found in deployment outputs (case-insensitive scan)" >&2
- echo "Full outputs JSON follows for troubleshooting:" >&2
- echo "$BICEP_OUTPUT" >&2
- exit 1
- fi
- echo "Resolved WEBAPP_URL: $WEBAPP_URL"
+ WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment outputs (truncated):"
- echo "$BICEP_OUTPUT" | head -c 2000
-
+ echo "Deployment output: $BICEP_OUTPUT"
- name: Logout from Azure
if: always()
run: |
az logout
echo "Logged out from Azure."
-
e2e-test:
needs: deploy
uses: ./.github/workflows/test-automation.yml
@@ -199,32 +164,43 @@ jobs:
runs-on: ubuntu-latest
env:
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
- AI_REGION: ${{ needs.deploy.outputs.SELECTED_AI_REGION }}
steps:
- 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 }}
-
- name: Get Log Analytics Workspace and OpenAI from Resource Group
if: always()
id: get_azure_resources
run: |
set -e
- echo "Collecting resource identifiers from RG ${{ env.RESOURCE_GROUP_NAME }} before deletion..."
- log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv || true)
- if [ -n "$log_analytics_workspace_name" ]; then
+ echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az monitor log-analytics workspace list command to get the workspace name
+ log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
+
+ if [ -z "$log_analytics_workspace_name" ]; then
+ echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
+ else
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
+ echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
fi
- openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv || true)
- if [ -n "$openai_resource_name" ]; then
+
+ echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az resource list command to get the OpenAI resource name
+ openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
+
+ if [ -z "$openai_resource_name" ]; then
+ echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
+ exit 1
+ else
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
+ echo "OpenAI resource name: ${openai_resource_name}"
fi
- echo "Snapshot complete."
- name: List KeyVaults and Store in Array
if: always()
@@ -232,12 +208,15 @@ jobs:
run: |
set -e
echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
- keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
+
+ # Get the list of KeyVaults in the specified resource group
+ 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 ${RESOURCE_GROUP_NAME}."
- echo "KEYVAULTS=[]" >> $GITHUB_ENV
+ echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
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
@@ -249,97 +228,141 @@ jobs:
fi
done
keyvault_array="$keyvault_array]"
+ # Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
- echo "Stored KeyVault array in KEYVAULTS environment variable."
-
- - name: Delete Resource Group (primary deletion)
+ - name: Delete Bicep Deployment
if: always()
run: |
- set -e
- echo "Initiating deletion of RG ${{ env.RESOURCE_GROUP_NAME }}..."
- az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "Delete command issued."
-
- - name: Wait for RG deletion propagation
- if: always()
- run: |
- set -e
- echo "Polling for RG deletion..."
- max_retries=15
- sleep_interval=20
- for i in $(seq 1 $max_retries); do
- exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }} || echo true)
- if [ "$exists" = false ]; then
- echo "Resource group deleted (confirmed)."
- break
- fi
- echo "RG still exists (attempt $i). Waiting $sleep_interval s..."
- sleep $sleep_interval
- done
-
- - name: Purge soft-deleted OpenAI (if any)
+ set -e
+ echo "Checking if resource group exists..."
+ rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
+ if [ "$rg_exists" = "true" ]; then
+ echo "Resource group exist. Cleaning..."
+ az group delete \
+ --name ${{ env.RESOURCE_GROUP_NAME }} \
+ --yes \
+ --no-wait
+ echo "Resource group deleted... ${{ env.RESOURCE_GROUP_NAME }}"
+ else
+ echo "Resource group does not exists."
+ fi
+ - name: Purge log analytics workspace
if: always()
+ id: log_analytics_workspace
run: |
set -e
- if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
- echo "Attempting purge of soft-deleted OpenAI: ${{ env.OPENAI_RESOURCE_NAME }} in region ${{ env.AI_REGION }}"
- az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge not available yet or failed (non-fatal)."
+ # Purge Log Analytics Workspace
+ echo "Purging the Log Analytics Workspace..."
+ if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
+ echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
else
- echo "No OpenAI resource recorded to purge."
+ echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
fi
+ echo "Log analytics workspace resource purging completed successfully"
+
- - name: Purge soft-deleted KeyVaults (if any)
+ - name: Wait for resource deletion to complete
if: always()
run: |
- set -e
+ # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
- stripped=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
- IFS=',' read -r -a kvs <<< "$stripped"
- for raw in "${kvs[@]}"; do
- kv=$(echo "$raw" | sed 's/\"//g' | xargs)
- [ -z "$kv" ] && continue
- echo "Checking soft-delete state for KeyVault: $kv"
- deleted=$(az keyvault list-deleted --query "[?name=='$kv']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
- if [ "$(echo "$deleted" | jq length)" -gt 0 ]; then
- echo "Purging KeyVault $kv ..."
- az keyvault purge --name "$kv" --no-wait || echo "Failed to purge $kv (non-fatal)"
+ # Remove the surrounding square brackets, if they exist
+ stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+
+ # Convert the comma-separated string into an array
+ IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
+ # Append new resources to the array
+ resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
+ echo "List of resources to check: ${resources_to_check[@]}"
+ # 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
+ # Get the list of resources in YAML format again on each retry
+ resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
+ # Iterate through the resources to check
+ for resource in "${resources_to_check[@]}"; do
+ 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" -gt "$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]}
+ fi
else
- echo "KeyVault $kv not soft-deleted; skipping."
+ echo "No resources found. Exiting."
+ break
fi
done
-
- - name: Purge Log Analytics Workspace (best-effort)
+
+ - name: Purging the Resources
if: always()
run: |
set -e
- if [ -n "${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" ]; then
- echo "Attempting to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} (best-effort)"
- az monitor log-analytics workspace delete --force --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --resource-group ${{ env.RESOURCE_GROUP_NAME }} --yes --verbose || echo "Workspace purge not applicable or already gone."
+ echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
+ # Purge OpenAI Resource
+ echo "Purging the OpenAI Resource..."
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
+ echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
- echo "No Log Analytics workspace recorded."
+ echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
fi
-
+ # List of keyvaults
+ KEYVAULTS="${{ env.KEYVAULTS }}"
+ # Remove the surrounding square brackets, if they exist
+ stripped_keyvaults=$(echo "$KEYVAULTS" | 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
+ 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..."
+ # Purge the KeyVault
+ if az keyvault purge --name "$keyvault_name" --no-wait; then
+ echo "Successfully purged KeyVault '$keyvault_name'."
+ else
+ echo "Failed to purge KeyVault '$keyvault_name'."
+ fi
+ else
+ echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
+ fi
+ done
+ echo "Resource purging completed successfully"
- name: Send Notification on Failure
if: failure() || needs.deploy.result == 'failure'
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
-
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
}
EOF
)
-
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
-
- - name: Final Resource Group Deletion
- if: always()
- run: |
- echo "Final RG delete step retained for idempotency; primary deletion already initiated."
-
- name: Logout from Azure
if: always()
run: |
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1c3216e7..99a148bd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,6 +6,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
pull_request:
types:
- opened
@@ -16,6 +17,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
jobs:
# frontend_tests:
@@ -87,15 +89,13 @@ jobs:
if [ -z "$(find src/tests/backend -type f -name '*_test.py')" ]; then
echo "No backend test files found, skipping backend tests."
echo "skip_backend_tests=true" >> $GITHUB_ENV
- echo "skip_backend_tests=true" >> $GITHUB_OUTPUT
else
echo "Backend test files found, running tests."
echo "skip_backend_tests=false" >> $GITHUB_ENV
- echo "skip_backend_tests=false" >> $GITHUB_OUTPUT
fi
- name: Run Backend Tests with Coverage
- if: steps.check_backend_tests.outputs.skip_backend_tests == 'false'
+ if: env.skip_backend_tests == 'false'
run: |
cd src
pytest --cov=. --cov-report=term-missing --cov-report=xml
@@ -103,6 +103,6 @@ jobs:
- name: Skip Backend Tests
- if: steps.check_backend_tests.outputs.skip_backend_tests == 'true'
+ if: env.skip_backend_tests == 'true'
run: |
- echo "Skipping backend tests because no test files were found."
+ echo "Skipping backend tests because no test files were found."
\ No newline at end of file
From 53001c5a88a843db11c2be7f428840b4147ca9fa Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Wed, 24 Sep 2025 17:16:05 +0530
Subject: [PATCH 25/40] waf removal
---
infra/main.bicep | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/infra/main.bicep b/infra/main.bicep
index f3c9f956..e9fa93b8 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -2,8 +2,8 @@ metadata name = 'Modernize Your Code Solution Accelerator'
metadata description = '''CSA CTO Gold Standard Solution Accelerator for Modernize Your Code.
'''
-@description('Set to true if you want to deploy WAF-aligned infrastructure.')
-param useWafAlignedArchitecture bool
+// @description('Set to true if you want to deploy WAF-aligned infrastructure.')
+// param useWafAlignedArchitecture bool
@minLength(3)
@maxLength(16)
@@ -46,11 +46,11 @@ param aiDeploymentsLocation string
@description('Optional. AI model deployment token capacity. Defaults to 150K tokens per minute.')
param capacity int = 150
-@description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
-param enableMonitoring bool = useWafAlignedArchitecture? true : false
+// @description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
+// param enableMonitoring bool = useWafAlignedArchitecture? true : false
-@description('Optional. Enable scaling for the container apps. Defaults to false.')
-param enableScaling bool = useWafAlignedArchitecture? true : false
+// @description('Optional. Enable scaling for the container apps. Defaults to false.')
+// param enableScaling bool = useWafAlignedArchitecture? true : false
@description('Optional. Enable redundancy for applicable resources. Defaults to false.')
param enableRedundancy bool = false
@@ -58,8 +58,8 @@ param enableRedundancy bool = false
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled.')
param secondaryLocation string?
-@description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
-param enablePrivateNetworking bool = useWafAlignedArchitecture? true : false
+// @description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
+// param enablePrivateNetworking bool = useWafAlignedArchitecture? true : false
@description('Optional. Size of the Jumpbox Virtual Machine when created. Set to custom value if enablePrivateNetworking is true.')
param vmSize string?
From 2c184ef37d92d21a850a40ef53d6a96a11a962d7 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Wed, 24 Sep 2025 17:23:48 +0530
Subject: [PATCH 26/40] usewaf set and declartion
---
infra/main.bicep | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/infra/main.bicep b/infra/main.bicep
index e9fa93b8..b00f9267 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -2,8 +2,8 @@ metadata name = 'Modernize Your Code Solution Accelerator'
metadata description = '''CSA CTO Gold Standard Solution Accelerator for Modernize Your Code.
'''
-// @description('Set to true if you want to deploy WAF-aligned infrastructure.')
-// param useWafAlignedArchitecture bool
+@description('Set to true if you want to deploy WAF-aligned infrastructure.')
+param useWafAlignedArchitecture bool = false
@minLength(3)
@maxLength(16)
@@ -46,11 +46,11 @@ param aiDeploymentsLocation string
@description('Optional. AI model deployment token capacity. Defaults to 150K tokens per minute.')
param capacity int = 150
-// @description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
-// param enableMonitoring bool = useWafAlignedArchitecture? true : false
+@description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
+param enableMonitoring bool = useWafAlignedArchitecture? true : false
-// @description('Optional. Enable scaling for the container apps. Defaults to false.')
-// param enableScaling bool = useWafAlignedArchitecture? true : false
+@description('Optional. Enable scaling for the container apps. Defaults to false.')
+param enableScaling bool = useWafAlignedArchitecture? true : false
@description('Optional. Enable redundancy for applicable resources. Defaults to false.')
param enableRedundancy bool = false
@@ -58,8 +58,8 @@ param enableRedundancy bool = false
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled.')
param secondaryLocation string?
-// @description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
-// param enablePrivateNetworking bool = useWafAlignedArchitecture? true : false
+@description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
+param enablePrivateNetworking bool = useWafAlignedArchitecture? true : false
@description('Optional. Size of the Jumpbox Virtual Machine when created. Set to custom value if enablePrivateNetworking is true.')
param vmSize string?
From 29ff906452046c4e176c0d7fc8789f768db8a1cf Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 25 Sep 2025 10:10:18 +0530
Subject: [PATCH 27/40] pipeline changes add auth
---
.github/workflows/deploy.yml | 246 +++++++++++++++++------------------
.github/workflows/test.yml | 1 -
2 files changed, 116 insertions(+), 131 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 50c1b378..0dc8449b 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -24,6 +24,7 @@ jobs:
outputs:
RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }}
+ SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
@@ -32,9 +33,11 @@ jobs:
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 }}
+
- name: Run Quota Check
id: quota-check
run: |
@@ -52,6 +55,7 @@ jobs:
fi
exit 1 # Fail the pipeline if any other failure occurs
fi
+
- name: Send Notification on Quota Failure
if: env.QUOTA_FAILED == 'true'
run: |
@@ -62,9 +66,11 @@ jobs:
}
EOF
)
+
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
+
- name: Fail Pipeline if Quota Check Fails
if: env.QUOTA_FAILED == 'true'
run: exit 1
@@ -72,6 +78,8 @@ jobs:
- name: Install Bicep CLI
run: az bicep install
+ # reverted: jq explicit installation step removed
+
- name: Generate Resource Group Name
id: generate_rg_name
run: |
@@ -81,6 +89,7 @@ jobs:
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}"
+
- name: Check and Create Resource Group
id: check_create_rg
run: |
@@ -94,6 +103,7 @@ jobs:
echo "Resource group already exists."
fi
echo "RESOURCE_GROUP_NAME=${{ env.RESOURCE_GROUP_NAME }}" >> $GITHUB_OUTPUT
+
- name: Generate Unique Solution Prefix
id: generate_solution_prefix
run: |
@@ -104,6 +114,7 @@ jobs:
UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
+
- name: Deploy Bicep Template
id: deploy
run: |
@@ -118,15 +129,24 @@ jobs:
else
IMAGE_TAG="latest"
fi
+
+ EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}" # VALID_REGION exported earlier if quota script succeeded
+ echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
+ echo "selected_ai_region=$EFFECTIVE_AI_REGION" >> $GITHUB_OUTPUT
+
+ echo "Resource Group: ${{ env.RESOURCE_GROUP_NAME }} (Created in northcentralus)"
+ echo "Solution Prefix: ${{ env.SOLUTION_PREFIX }}"
+ echo "Image Tag: ${IMAGE_TAG}"
+
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="eastus" \
+ aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
capacity=${{ env.GPT_MIN_CAPACITY }} \
- imageVersion="${IMAGE_TAG}"\
+ imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline"
- name: Assign Contributor role to Service Principal
if: always()
@@ -136,6 +156,8 @@ jobs:
--assignee ${{ secrets.AZURE_CLIENT_ID }} \
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+
+
- name: Get Deployment Output and extract Values
id: get_output
run: |
@@ -143,14 +165,27 @@ jobs:
echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
echo "Extracting deployment output..."
- WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
+ echo "Available output keys:"
+ echo "$BICEP_OUTPUT" | jq -r 'keys | join(", ")'
+ # Case-insensitive lookup for WEB_APP_URL because deployment outputs returned inconsistent casing previously
+ WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r 'to_entries | map(select((.key|ascii_upcase)=="WEB_APP_URL")) | .[0].value.value // empty')
+ if [ -z "$WEBAPP_URL" ] || [ "$WEBAPP_URL" = "null" ]; then
+ echo "WEB_APP_URL not found in deployment outputs (case-insensitive scan)" >&2
+ echo "Full outputs JSON follows for troubleshooting:" >&2
+ echo "$BICEP_OUTPUT" >&2
+ exit 1
+ fi
+ echo "Resolved WEBAPP_URL: $WEBAPP_URL"
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment output: $BICEP_OUTPUT"
+ echo "Deployment outputs (truncated):"
+ echo "$BICEP_OUTPUT" | head -c 2000
+
- name: Logout from Azure
if: always()
run: |
az logout
echo "Logged out from Azure."
+
e2e-test:
needs: deploy
uses: ./.github/workflows/test-automation.yml
@@ -164,43 +199,41 @@ jobs:
runs-on: ubuntu-latest
env:
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
+ AI_REGION: ${{ needs.deploy.outputs.SELECTED_AI_REGION }}
steps:
- 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 }}
+
+ - name: Assign Contributor role to Service Principal
+ if: always()
+ run: |
+ echo "Assigning Contributor role to SPN for RG: ${{ env.RESOURCE_GROUP_NAME }}"
+ az role assignment create \
+ --assignee ${{ secrets.AZURE_CLIENT_ID }} \
+ --role "Contributor" \
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+
- name: Get Log Analytics Workspace and OpenAI from Resource Group
if: always()
id: get_azure_resources
run: |
set -e
- echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az monitor log-analytics workspace list command to get the workspace name
- log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
-
- if [ -z "$log_analytics_workspace_name" ]; then
- echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
- else
+ echo "Collecting resource identifiers from RG ${{ env.RESOURCE_GROUP_NAME }} before deletion..."
+ log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv || true)
+ if [ -n "$log_analytics_workspace_name" ]; then
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
- echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
fi
-
- echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
-
- # Run the az resource list command to get the OpenAI resource name
- openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
-
- if [ -z "$openai_resource_name" ]; then
- echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
- exit 1
- else
+ openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv || true)
+ if [ -n "$openai_resource_name" ]; then
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
- echo "OpenAI resource name: ${openai_resource_name}"
fi
+ echo "Snapshot complete."
- name: List KeyVaults and Store in Array
if: always()
@@ -208,15 +241,12 @@ jobs:
run: |
set -e
echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
-
- # Get the list of KeyVaults in the specified resource group
- keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv)
+ keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
if [ -z "$keyvaults" ]; then
echo "No KeyVaults found in resource group ${RESOURCE_GROUP_NAME}."
- echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
+ echo "KEYVAULTS=[]" >> $GITHUB_ENV
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
@@ -228,141 +258,97 @@ jobs:
fi
done
keyvault_array="$keyvault_array]"
- # Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
- - name: Delete Bicep Deployment
+ echo "Stored KeyVault array in KEYVAULTS environment variable."
+
+ - name: Delete Resource Group (primary deletion)
if: always()
run: |
- set -e
- echo "Checking if resource group exists..."
- rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
- if [ "$rg_exists" = "true" ]; then
- echo "Resource group exist. Cleaning..."
- az group delete \
- --name ${{ env.RESOURCE_GROUP_NAME }} \
- --yes \
- --no-wait
- echo "Resource group deleted... ${{ env.RESOURCE_GROUP_NAME }}"
- else
- echo "Resource group does not exists."
- fi
- - name: Purge log analytics workspace
+ set -e
+ echo "Initiating deletion of RG ${{ env.RESOURCE_GROUP_NAME }}..."
+ az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "Delete command issued."
+
+ - name: Wait for RG deletion propagation
+ if: always()
+ run: |
+ set -e
+ echo "Polling for RG deletion..."
+ max_retries=15
+ sleep_interval=20
+ for i in $(seq 1 $max_retries); do
+ exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }} || echo true)
+ if [ "$exists" = false ]; then
+ echo "Resource group deleted (confirmed)."
+ break
+ fi
+ echo "RG still exists (attempt $i). Waiting $sleep_interval s..."
+ sleep $sleep_interval
+ done
+
+ - name: Purge soft-deleted OpenAI (if any)
if: always()
- id: log_analytics_workspace
run: |
set -e
- # Purge Log Analytics Workspace
- echo "Purging the Log Analytics Workspace..."
- if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
- echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
+ if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
+ echo "Attempting purge of soft-deleted OpenAI: ${{ env.OPENAI_RESOURCE_NAME }} in region ${{ env.AI_REGION }}"
+ az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge not available yet or failed (non-fatal)."
else
- echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
+ echo "No OpenAI resource recorded to purge."
fi
- echo "Log analytics workspace resource purging completed successfully"
-
- - name: Wait for resource deletion to complete
+ - name: Purge soft-deleted KeyVaults (if any)
if: always()
run: |
- # List of keyvaults
+ set -e
KEYVAULTS="${{ env.KEYVAULTS }}"
- # Remove the surrounding square brackets, if they exist
- stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
-
- # Convert the comma-separated string into an array
- IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
- # Append new resources to the array
- resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
- echo "List of resources to check: ${resources_to_check[@]}"
- # 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
- # Get the list of resources in YAML format again on each retry
- resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
- # Iterate through the resources to check
- for resource in "${resources_to_check[@]}"; do
- 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" -gt "$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]}
- fi
+ stripped=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+ IFS=',' read -r -a kvs <<< "$stripped"
+ for raw in "${kvs[@]}"; do
+ kv=$(echo "$raw" | sed 's/\"//g' | xargs)
+ [ -z "$kv" ] && continue
+ echo "Checking soft-delete state for KeyVault: $kv"
+ deleted=$(az keyvault list-deleted --query "[?name=='$kv']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
+ if [ "$(echo "$deleted" | jq length)" -gt 0 ]; then
+ echo "Purging KeyVault $kv ..."
+ az keyvault purge --name "$kv" --no-wait || echo "Failed to purge $kv (non-fatal)"
else
- echo "No resources found. Exiting."
- break
+ echo "KeyVault $kv not soft-deleted; skipping."
fi
done
-
- - name: Purging the Resources
+
+ - name: Purge Log Analytics Workspace (best-effort)
if: always()
run: |
set -e
- echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
- # Purge OpenAI Resource
- echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
- echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
+ if [ -n "${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" ]; then
+ echo "Attempting to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} (best-effort)"
+ az monitor log-analytics workspace delete --force --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --resource-group ${{ env.RESOURCE_GROUP_NAME }} --yes --verbose || echo "Workspace purge not applicable or already gone."
else
- echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
+ echo "No Log Analytics workspace recorded."
fi
- # List of keyvaults
- KEYVAULTS="${{ env.KEYVAULTS }}"
- # Remove the surrounding square brackets, if they exist
- stripped_keyvaults=$(echo "$KEYVAULTS" | 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
- 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..."
- # Purge the KeyVault
- if az keyvault purge --name "$keyvault_name" --no-wait; then
- echo "Successfully purged KeyVault '$keyvault_name'."
- else
- echo "Failed to purge KeyVault '$keyvault_name'."
- fi
- else
- echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
- fi
- done
- echo "Resource purging completed successfully"
+
- name: Send Notification on Failure
if: failure() || needs.deploy.result == 'failure'
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
}
EOF
)
+
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
+
+ - name: Final Resource Group Deletion
+ if: always()
+ run: |
+ echo "Final RG delete step retained for idempotency; primary deletion already initiated."
+
- name: Logout from Azure
if: always()
run: |
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 99a148bd..f472104d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -17,7 +17,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
jobs:
# frontend_tests:
From 5aab02fe2aad02f9ab59bae8d60eec49b814581a Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 25 Sep 2025 10:40:03 +0530
Subject: [PATCH 28/40] add auth and reverted changes and removed waf
---
.github/workflows/deploy.yml | 247 +++++++++++++++++++++++------------
1 file changed, 160 insertions(+), 87 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 0dc8449b..67c7bb5b 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -9,7 +9,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
workflow_dispatch:
@@ -24,7 +23,6 @@ jobs:
outputs:
RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }}
- SELECTED_AI_REGION: ${{ steps.deploy.outputs.selected_ai_region || env.VALID_REGION }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
@@ -78,8 +76,6 @@ jobs:
- name: Install Bicep CLI
run: az bicep install
- # reverted: jq explicit installation step removed
-
- name: Generate Resource Group Name
id: generate_rg_name
run: |
@@ -130,24 +126,21 @@ jobs:
IMAGE_TAG="latest"
fi
- EFFECTIVE_AI_REGION="${VALID_REGION:-eastus}" # VALID_REGION exported earlier if quota script succeeded
- echo "Using AI Deployments Region: $EFFECTIVE_AI_REGION"
- echo "selected_ai_region=$EFFECTIVE_AI_REGION" >> $GITHUB_OUTPUT
-
- echo "Resource Group: ${{ env.RESOURCE_GROUP_NAME }} (Created in northcentralus)"
- echo "Solution Prefix: ${{ env.SOLUTION_PREFIX }}"
- echo "Image Tag: ${IMAGE_TAG}"
-
+ # Generate current timestamp in desired format: YYYY-MM-DDTHH:MM:SS.SSSSSSSZ
+ current_date=$(date -u +"%Y-%m-%dT%H:%M:%S.%7NZ")
+
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
+ aiDeploymentsLocation="eastus" \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
- createdBy="Pipeline"
+ createdBy="Pipeline" \
+ tags="{'SecurityControl':'Ignore','Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}"
+
- name: Assign Contributor role to Service Principal
if: always()
run: |
@@ -165,20 +158,9 @@ jobs:
echo "Fetching deployment output..."
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
echo "Extracting deployment output..."
- echo "Available output keys:"
- echo "$BICEP_OUTPUT" | jq -r 'keys | join(", ")'
- # Case-insensitive lookup for WEB_APP_URL because deployment outputs returned inconsistent casing previously
- WEBAPP_URL=$(echo "$BICEP_OUTPUT" | jq -r 'to_entries | map(select((.key|ascii_upcase)=="WEB_APP_URL")) | .[0].value.value // empty')
- if [ -z "$WEBAPP_URL" ] || [ "$WEBAPP_URL" = "null" ]; then
- echo "WEB_APP_URL not found in deployment outputs (case-insensitive scan)" >&2
- echo "Full outputs JSON follows for troubleshooting:" >&2
- echo "$BICEP_OUTPUT" >&2
- exit 1
- fi
- echo "Resolved WEBAPP_URL: $WEBAPP_URL"
+ WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
- echo "Deployment outputs (truncated):"
- echo "$BICEP_OUTPUT" | head -c 2000
+ echo "Deployment output: $BICEP_OUTPUT"
- name: Logout from Azure
if: always()
@@ -199,7 +181,6 @@ jobs:
runs-on: ubuntu-latest
env:
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
- AI_REGION: ${{ needs.deploy.outputs.SELECTED_AI_REGION }}
steps:
- name: Setup Azure CLI
run: |
@@ -209,7 +190,7 @@ jobs:
- name: Login to Azure
run: |
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
-
+
- name: Assign Contributor role to Service Principal
if: always()
run: |
@@ -219,34 +200,56 @@ jobs:
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
+
- name: Get Log Analytics Workspace and OpenAI from Resource Group
if: always()
id: get_azure_resources
run: |
+
set -e
- echo "Collecting resource identifiers from RG ${{ env.RESOURCE_GROUP_NAME }} before deletion..."
- log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv || true)
- if [ -n "$log_analytics_workspace_name" ]; then
+ echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az monitor log-analytics workspace list command to get the workspace name
+ log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
+
+ if [ -z "$log_analytics_workspace_name" ]; then
+ echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
+ else
echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
+ echo "Log Analytics workspace name: ${log_analytics_workspace_name}"
fi
- openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv || true)
- if [ -n "$openai_resource_name" ]; then
+
+ echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
+
+ # Run the az resource list command to get the OpenAI resource name
+ openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
+
+ if [ -z "$openai_resource_name" ]; then
+ echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
+ exit 1
+ else
echo "OPENAI_RESOURCE_NAME=${openai_resource_name}" >> $GITHUB_ENV
+ echo "OpenAI resource name: ${openai_resource_name}"
fi
- echo "Snapshot complete."
- name: List KeyVaults and Store in Array
if: always()
id: list_keyvaults
run: |
+
set -e
echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
- keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv || true)
+
+ # Get the list of KeyVaults in the specified resource group
+ 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 ${RESOURCE_GROUP_NAME}."
- echo "KEYVAULTS=[]" >> $GITHUB_ENV
+ echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
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
@@ -258,76 +261,151 @@ jobs:
fi
done
keyvault_array="$keyvault_array]"
+
+ # Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
- echo "Stored KeyVault array in KEYVAULTS environment variable."
- - name: Delete Resource Group (primary deletion)
+ - name: Delete Bicep Deployment
if: always()
run: |
- set -e
- echo "Initiating deletion of RG ${{ env.RESOURCE_GROUP_NAME }}..."
- az group delete --name ${{ env.RESOURCE_GROUP_NAME }} --yes --no-wait || echo "Delete command issued."
+ set -e
+ echo "Checking if resource group exists..."
+ rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
+ if [ "$rg_exists" = "true" ]; then
+ echo "Resource group exist. Cleaning..."
+ az group delete \
+ --name ${{ env.RESOURCE_GROUP_NAME }} \
+ --yes \
+ --no-wait
+ echo "Resource group deleted... ${{ env.RESOURCE_GROUP_NAME }}"
+ else
+ echo "Resource group does not exists."
+ fi
- - name: Wait for RG deletion propagation
+ - name: Purge log analytics workspace
if: always()
+ id: log_analytics_workspace
run: |
- set -e
- echo "Polling for RG deletion..."
- max_retries=15
- sleep_interval=20
- for i in $(seq 1 $max_retries); do
- exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }} || echo true)
- if [ "$exists" = false ]; then
- echo "Resource group deleted (confirmed)."
- break
- fi
- echo "RG still exists (attempt $i). Waiting $sleep_interval s..."
- sleep $sleep_interval
- done
- - name: Purge soft-deleted OpenAI (if any)
- if: always()
- run: |
set -e
- if [ -n "${{ env.OPENAI_RESOURCE_NAME }}" ]; then
- echo "Attempting purge of soft-deleted OpenAI: ${{ env.OPENAI_RESOURCE_NAME }} in region ${{ env.AI_REGION }}"
- az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/${{ env.AI_REGION || 'eastus' }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose || echo "OpenAI purge not available yet or failed (non-fatal)."
+ # Purge Log Analytics Workspace
+ echo "Purging the Log Analytics Workspace..."
+ if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
+ echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
else
- echo "No OpenAI resource recorded to purge."
+ echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
fi
- - name: Purge soft-deleted KeyVaults (if any)
+ echo "Log analytics workspace resource purging completed successfully"
+
+
+ - name: Wait for resource deletion to complete
if: always()
run: |
- set -e
+
+ # List of keyvaults
KEYVAULTS="${{ env.KEYVAULTS }}"
- stripped=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
- IFS=',' read -r -a kvs <<< "$stripped"
- for raw in "${kvs[@]}"; do
- kv=$(echo "$raw" | sed 's/\"//g' | xargs)
- [ -z "$kv" ] && continue
- echo "Checking soft-delete state for KeyVault: $kv"
- deleted=$(az keyvault list-deleted --query "[?name=='$kv']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo '[]')
- if [ "$(echo "$deleted" | jq length)" -gt 0 ]; then
- echo "Purging KeyVault $kv ..."
- az keyvault purge --name "$kv" --no-wait || echo "Failed to purge $kv (non-fatal)"
+
+ # Remove the surrounding square brackets, if they exist
+ stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+
+ # Convert the comma-separated string into an array
+ IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
+
+ # Append new resources to the array
+ resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
+
+ echo "List of resources to check: ${resources_to_check[@]}"
+
+ # 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
+
+ # Get the list of resources in YAML format again on each retry
+ resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
+
+ # Iterate through the resources to check
+ for resource in "${resources_to_check[@]}"; do
+ 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" -gt "$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]}
+ fi
else
- echo "KeyVault $kv not soft-deleted; skipping."
+ echo "No resources found. Exiting."
+ break
fi
done
-
- - name: Purge Log Analytics Workspace (best-effort)
+
+ - name: Purging the Resources
if: always()
run: |
+
set -e
- if [ -n "${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" ]; then
- echo "Attempting to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} (best-effort)"
- az monitor log-analytics workspace delete --force --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --resource-group ${{ env.RESOURCE_GROUP_NAME }} --yes --verbose || echo "Workspace purge not applicable or already gone."
+
+ echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
+
+ # Purge OpenAI Resource
+ echo "Purging the OpenAI Resource..."
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/northcentralus/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}/deletedAccounts/${{ env.OPENAI_RESOURCE_NAME }} --verbose; then
+ echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
else
- echo "No Log Analytics workspace recorded."
+ echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
fi
+ # List of keyvaults
+ KEYVAULTS="${{ env.KEYVAULTS }}"
+
+ # Remove the surrounding square brackets, if they exist
+ stripped_keyvaults=$(echo "$KEYVAULTS" | 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
+ 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..."
+ # Purge the KeyVault
+ if az keyvault purge --name "$keyvault_name" --no-wait; then
+ echo "Successfully purged KeyVault '$keyvault_name'."
+ else
+ echo "Failed to purge KeyVault '$keyvault_name'."
+ fi
+ else
+ echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
+ fi
+ done
+ echo "Resource purging completed successfully"
+
- name: Send Notification on Failure
if: failure() || needs.deploy.result == 'failure'
run: |
@@ -344,11 +422,6 @@ jobs:
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
- - name: Final Resource Group Deletion
- if: always()
- run: |
- echo "Final RG delete step retained for idempotency; primary deletion already initiated."
-
- name: Logout from Azure
if: always()
run: |
From ba917a040b93b4b9ca4d40ff07e56d41af42f54c Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Thu, 25 Sep 2025 13:25:18 +0530
Subject: [PATCH 29/40] template validation version upgrade
---
.github/workflows/azure-dev-validation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index fc98fd7d..199c0cc5 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v4
# Step 2: Validate the Azure template using microsoft/template-validation-action
- name: Validate Azure Template
- uses: microsoft/template-validation-action@Latest
+ uses: microsoft/template-validation-action@v0.3.5
id: validation
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
From f5039bf5e3fe503937a61620f9a5fa4e0671201c Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Fri, 26 Sep 2025 10:54:54 +0530
Subject: [PATCH 30/40] latest version update
---
.github/workflows/azure-dev-validation.yml | 23 ++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 199c0cc5..aba6eb11 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -1,14 +1,15 @@
-name: Azure Template Validation
+name: Azure Template Validation
on:
-# workflow_dispatch:
- push:
- branches:
- - main
- - vee-pipeline-fixes
+ push:
+ branches:
+ - main
+ - vee-pipeline-fixes
+
permissions:
contents: read
id-token: write
pull-requests: write
+
jobs:
template_validation_job:
runs-on: ubuntu-latest
@@ -18,10 +19,14 @@ jobs:
# Step 1: Checkout the code from your repository
- name: Checkout code
uses: actions/checkout@v4
+
# Step 2: Validate the Azure template using microsoft/template-validation-action
- name: Validate Azure Template
- uses: microsoft/template-validation-action@v0.3.5
+ uses: microsoft/template-validation-action@Latest
id: validation
+ with:
+ # disable auto test generation that breaks validation
+ validateTests: none
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
@@ -30,6 +35,8 @@ jobs:
AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
# Step 3: Print the result of the validation
- name: Print result
- run: cat ${{ steps.validation.outputs.resultFile }}
\ No newline at end of file
+ run: cat ${{ steps.validation.outputs.resultFile }}
+
\ No newline at end of file
From 1f44e159108f2a6b2778d5fbd9c3d9f0ae38ae55 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Fri, 26 Sep 2025 12:22:56 +0530
Subject: [PATCH 31/40] fixing all related changes and removed Waf
---
.github/workflows/azure-dev-validation.yml | 25 ++++++++------------
infra/main.bicep | 12 ----------
infra/main.json | 27 ----------------------
3 files changed, 9 insertions(+), 55 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index aba6eb11..7e558f48 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -1,32 +1,27 @@
-name: Azure Template Validation
+name: Azure Template Validation
on:
- push:
- branches:
- - main
- - vee-pipeline-fixes
-
+# workflow_dispatch:
+ push:
+ branches:
+ - main
+ - vee-pipeline-fixes
permissions:
contents: read
id-token: write
pull-requests: write
-
jobs:
template_validation_job:
runs-on: ubuntu-latest
- environment: production
+ environment: dev
name: Template validation
steps:
# Step 1: Checkout the code from your repository
- name: Checkout code
uses: actions/checkout@v4
-
# Step 2: Validate the Azure template using microsoft/template-validation-action
- name: Validate Azure Template
- uses: microsoft/template-validation-action@Latest
+ uses: microsoft/template-validation-action@v0.3.5
id: validation
- with:
- # disable auto test generation that breaks validation
- validateTests: none
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
@@ -35,8 +30,6 @@ jobs:
AZURE_ENV_NAME: ${{ secrets.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ secrets.AZURE_LOCATION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
# Step 3: Print the result of the validation
- name: Print result
- run: cat ${{ steps.validation.outputs.resultFile }}
-
\ No newline at end of file
+ run: cat ${{ steps.validation.outputs.resultFile }}
\ No newline at end of file
diff --git a/infra/main.bicep b/infra/main.bicep
index b00f9267..9c280330 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -2,9 +2,6 @@ metadata name = 'Modernize Your Code Solution Accelerator'
metadata description = '''CSA CTO Gold Standard Solution Accelerator for Modernize Your Code.
'''
-@description('Set to true if you want to deploy WAF-aligned infrastructure.')
-param useWafAlignedArchitecture bool = false
-
@minLength(3)
@maxLength(16)
@description('Required. A unique application/solution name for all resources in this deployment. This should be 3-16 characters long.')
@@ -46,21 +43,12 @@ param aiDeploymentsLocation string
@description('Optional. AI model deployment token capacity. Defaults to 150K tokens per minute.')
param capacity int = 150
-@description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
-param enableMonitoring bool = useWafAlignedArchitecture? true : false
-
-@description('Optional. Enable scaling for the container apps. Defaults to false.')
-param enableScaling bool = useWafAlignedArchitecture? true : false
-
@description('Optional. Enable redundancy for applicable resources. Defaults to false.')
param enableRedundancy bool = false
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled.')
param secondaryLocation string?
-@description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
-param enablePrivateNetworking bool = useWafAlignedArchitecture? true : false
-
@description('Optional. Size of the Jumpbox Virtual Machine when created. Set to custom value if enablePrivateNetworking is true.')
param vmSize string?
diff --git a/infra/main.json b/infra/main.json
index 72245536..4b1c7d16 100644
--- a/infra/main.json
+++ b/infra/main.json
@@ -12,12 +12,6 @@
"description": "CSA CTO Gold Standard Solution Accelerator for Modernize Your Code. \r\n"
},
"parameters": {
- "useWafAlignedArchitecture": {
- "type": "bool",
- "metadata": {
- "description": "Set to true if you want to deploy WAF-aligned infrastructure."
- }
- },
"solutionName": {
"type": "string",
"minLength": 3,
@@ -77,20 +71,6 @@
"description": "Optional. AI model deployment token capacity. Defaults to 150K tokens per minute."
}
},
- "enableMonitoring": {
- "type": "bool",
- "defaultValue": "[if(parameters('useWafAlignedArchitecture'), true(), false())]",
- "metadata": {
- "description": "Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false."
- }
- },
- "enableScaling": {
- "type": "bool",
- "defaultValue": "[if(parameters('useWafAlignedArchitecture'), true(), false())]",
- "metadata": {
- "description": "Optional. Enable scaling for the container apps. Defaults to false."
- }
- },
"enableRedundancy": {
"type": "bool",
"defaultValue": false,
@@ -105,13 +85,6 @@
"description": "Optional. The secondary location for the Cosmos DB account if redundancy is enabled."
}
},
- "enablePrivateNetworking": {
- "type": "bool",
- "defaultValue": "[if(parameters('useWafAlignedArchitecture'), true(), false())]",
- "metadata": {
- "description": "Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false."
- }
- },
"vmSize": {
"type": "string",
"nullable": true,
From b6b90b749c430520bded9860814c17580c8d8460 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 09:53:51 +0530
Subject: [PATCH 32/40] latest code from dev removed WAF
---
infra/main.bicep | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/infra/main.bicep b/infra/main.bicep
index 9c280330..4e73a7bf 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -2,6 +2,7 @@ metadata name = 'Modernize Your Code Solution Accelerator'
metadata description = '''CSA CTO Gold Standard Solution Accelerator for Modernize Your Code.
'''
+
@minLength(3)
@maxLength(16)
@description('Required. A unique application/solution name for all resources in this deployment. This should be 3-16 characters long.')
@@ -43,12 +44,21 @@ param aiDeploymentsLocation string
@description('Optional. AI model deployment token capacity. Defaults to 150K tokens per minute.')
param capacity int = 150
+@description('Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
+param enableMonitoring bool = false
+
+@description('Optional. Enable scaling for the container apps. Defaults to false.')
+param enableScaling bool = false
+
@description('Optional. Enable redundancy for applicable resources. Defaults to false.')
param enableRedundancy bool = false
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled.')
param secondaryLocation string?
+@description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
+param enablePrivateNetworking bool = false
+
@description('Optional. Size of the Jumpbox Virtual Machine when created. Set to custom value if enablePrivateNetworking is true.')
param vmSize string?
@@ -78,7 +88,7 @@ param llmModel string = 'gpt-4o'
@minLength(1)
@description('Set the Image tag:')
-param imageVersion string = 'latest'
+param imageVersion string = 'latest_2025-09-22_455'
@minLength(1)
@description('Version of the GPT model to deploy:')
@@ -122,8 +132,9 @@ var modelDeployment = {
var abbrs = loadJsonContent('./abbreviations.json')
-@description('Optional created by user name')
-param createdBy string = empty(deployer().userPrincipalName) ? '' : split(deployer().userPrincipalName, '@')[0]
+@description('Tag, Created by user name')
+param createdBy string = contains(deployer(), 'userPrincipalName')? split(deployer().userPrincipalName, '@')[0]: deployer().objectId
+
// ========== Resource Group Tag ========== //
resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = {
@@ -132,6 +143,7 @@ resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = {
tags: {
...allTags
TemplateName: 'Code Modernization'
+ Type: enablePrivateNetworking ? 'WAF' : 'Non-WAF'
CreatedBy: createdBy
}
}
From 47c8fd74c3a9ec013052fe18bc468e8c348202d6 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 10:17:43 +0530
Subject: [PATCH 33/40] adding branch name
---
.github/workflows/deploy.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 67c7bb5b..55090b48 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -9,6 +9,7 @@ on:
- main
- dev
- demo
+ - vee-pipeline-fixes
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
workflow_dispatch:
From 8693cb2c8e181c2c0dc25606dc68d454ec71b23c Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 10:58:39 +0530
Subject: [PATCH 34/40] add auth for log analytics
---
.github/workflows/deploy.yml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 55090b48..740c7be7 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -200,7 +200,12 @@ jobs:
--assignee ${{ secrets.AZURE_CLIENT_ID }} \
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
-
+
+ echo "Assigning Log Analytics Contributor role for Log Analytics workspace access..."
+ az role assignment create \
+ --assignee ${{ secrets.AZURE_CLIENT_ID }} \
+ --role "Log Analytics Contributor" \
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo "Log Analytics Contributor role assignment failed (may already exist)"
- name: Get Log Analytics Workspace and OpenAI from Resource Group
if: always()
From 2e3ea265e40f6a93a1b095cd4c4c33229b2b4c82 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 11:19:48 +0530
Subject: [PATCH 35/40] auth modify in auth step
---
.github/workflows/deploy.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 740c7be7..45e494d8 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -201,11 +201,14 @@ jobs:
--role "Contributor" \
--scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
- echo "Assigning Log Analytics Contributor role for Log Analytics workspace access..."
+ echo "Assigning Log Analytics Contributor role for Log Analytics workspace access at RG level..."
az role assignment create \
--assignee ${{ secrets.AZURE_CLIENT_ID }} \
--role "Log Analytics Contributor" \
- --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }} || echo "Log Analytics Contributor role assignment failed (may already exist)"
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }} || echo "Log Analytics Contributor role assignment failed (may already exist)"
+
+ echo "Waiting for role assignment propagation..."
+ sleep 30
- name: Get Log Analytics Workspace and OpenAI from Resource Group
if: always()
From 547b5ebf5210ff18d1aba9d1337dc2bcbf907b67 Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 16:53:53 +0530
Subject: [PATCH 36/40] dynamic region update
---
.github/workflows/deploy.yml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 45e494d8..5f52885c 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -130,13 +130,20 @@ jobs:
# Generate current timestamp in desired format: YYYY-MM-DDTHH:MM:SS.SSSSSSSZ
current_date=$(date -u +"%Y-%m-%dT%H:%M:%S.%7NZ")
+ EFFECTIVE_AI_REGION="${{ env.VALID_REGION }}"
+ if [ -z "$EFFECTIVE_AI_REGION" ]; then
+ EFFECTIVE_AI_REGION="eastus"
+ echo "⚠️ WARNING: VALID_REGION not set, falling back to eastus"
+ fi
+ echo "✅ Using AI Deployments Region: $EFFECTIVE_AI_REGION"
+
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="eastus" \
+ aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline" \
From 66b51a256d7ccce1045a21bb3ab535225710906b Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 18:56:27 +0530
Subject: [PATCH 37/40] dev to production fix
---
.github/workflows/azure-dev-validation.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 7e558f48..dda61a04 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -12,7 +12,7 @@ permissions:
jobs:
template_validation_job:
runs-on: ubuntu-latest
- environment: dev
+ environment: production
name: Template validation
steps:
# Step 1: Checkout the code from your repository
From e11048503ecab16e722bec38612ebff283c68afe Mon Sep 17 00:00:00 2001
From: Venkateswarlu Marthula
Date: Tue, 30 Sep 2025 19:18:02 +0530
Subject: [PATCH 38/40] removing local brnach name in all the places
---
.github/workflows/azure-dev-validation.yml | 1 -
.github/workflows/deploy.yml | 1 -
.github/workflows/test.yml | 1 -
3 files changed, 3 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index dda61a04..2619e449 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -4,7 +4,6 @@ on:
push:
branches:
- main
- - vee-pipeline-fixes
permissions:
contents: read
id-token: write
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 5f52885c..b63944eb 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -9,7 +9,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
schedule:
- cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
workflow_dispatch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f472104d..f1103949 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,7 +6,6 @@ on:
- main
- dev
- demo
- - vee-pipeline-fixes
pull_request:
types:
- opened
From de4800768c9303fc69b2d1ca5a5a7175e112f169 Mon Sep 17 00:00:00 2001
From: Roopan P M
Date: Tue, 30 Sep 2025 22:09:25 +0530
Subject: [PATCH 39/40] main json updated
---
infra/main.json | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/infra/main.json b/infra/main.json
index 8299020e..9e1a8ac8 100644
--- a/infra/main.json
+++ b/infra/main.json
@@ -6,10 +6,10 @@
"_generator": {
"name": "bicep",
"version": "0.37.4.10188",
- "templateHash": "4708808767614470236"
+ "templateHash": "10857935115773987076"
},
"name": "Modernize Your Code Solution Accelerator",
- "description": "CSA CTO Gold Standard Solution Accelerator for Modernize Your Code. \n"
+ "description": "CSA CTO Gold Standard Solution Accelerator for Modernize Your Code. \r\n"
},
"parameters": {
"solutionName": {
@@ -71,6 +71,20 @@
"description": "Optional. AI model deployment token capacity. Defaults to 150K tokens per minute."
}
},
+ "enableMonitoring": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Optional. Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false."
+ }
+ },
+ "enableScaling": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Optional. Enable scaling for the container apps. Defaults to false."
+ }
+ },
"enableRedundancy": {
"type": "bool",
"defaultValue": false,
@@ -85,6 +99,13 @@
"description": "Optional. The secondary location for the Cosmos DB account if redundancy is enabled."
}
},
+ "enablePrivateNetworking": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false."
+ }
+ },
"vmSize": {
"type": "string",
"nullable": true,
@@ -165,9 +186,9 @@
},
"createdBy": {
"type": "string",
- "defaultValue": "[if(empty(deployer().userPrincipalName), '', split(deployer().userPrincipalName, '@')[0])]",
+ "defaultValue": "[if(contains(deployer(), 'userPrincipalName'), split(deployer().userPrincipalName, '@')[0], deployer().objectId)]",
"metadata": {
- "description": "Optional created by user name"
+ "description": "Tag, Created by user name"
}
}
},
@@ -430,7 +451,7 @@
"apiVersion": "2021-04-01",
"name": "default",
"properties": {
- "tags": "[shallowMerge(createArray(variables('allTags'), createObject('TemplateName', 'Code Modernization', 'CreatedBy', parameters('createdBy'))))]"
+ "tags": "[shallowMerge(createArray(variables('allTags'), createObject('TemplateName', 'Code Modernization', 'Type', if(parameters('enablePrivateNetworking'), 'WAF', 'Non-WAF'), 'CreatedBy', parameters('createdBy'))))]"
}
},
"avmTelemetry": {
From 9bb82c98c4bae539445f309cdadf374ff5a054a2 Mon Sep 17 00:00:00 2001
From: Roopan P M
Date: Tue, 30 Sep 2025 22:20:12 +0530
Subject: [PATCH 40/40] updated the code for valida region
---
.github/workflows/azure-dev-validation.yml | 2 +-
.github/workflows/deploy.yml | 14 ++++++--------
2 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/azure-dev-validation.yml b/.github/workflows/azure-dev-validation.yml
index 2619e449..ce740a94 100644
--- a/.github/workflows/azure-dev-validation.yml
+++ b/.github/workflows/azure-dev-validation.yml
@@ -19,7 +19,7 @@ jobs:
uses: actions/checkout@v4
# Step 2: Validate the Azure template using microsoft/template-validation-action
- name: Validate Azure Template
- uses: microsoft/template-validation-action@v0.3.5
+ uses: microsoft/template-validation-action@Latest
id: validation
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index b63944eb..fdde396d 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -72,6 +72,11 @@ jobs:
- name: Fail Pipeline if Quota Check Fails
if: env.QUOTA_FAILED == 'true'
run: exit 1
+
+ - name: Set Deployment Region
+ run: |
+ echo "Selected Region: $VALID_REGION"
+ echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_ENV
- name: Install Bicep CLI
run: az bicep install
@@ -129,20 +134,13 @@ jobs:
# Generate current timestamp in desired format: YYYY-MM-DDTHH:MM:SS.SSSSSSSZ
current_date=$(date -u +"%Y-%m-%dT%H:%M:%S.%7NZ")
- EFFECTIVE_AI_REGION="${{ env.VALID_REGION }}"
- if [ -z "$EFFECTIVE_AI_REGION" ]; then
- EFFECTIVE_AI_REGION="eastus"
- echo "⚠️ WARNING: VALID_REGION not set, falling back to eastus"
- fi
- echo "✅ Using AI Deployments Region: $EFFECTIVE_AI_REGION"
-
az deployment group create \
--name ${{ env.SOLUTION_PREFIX }}-deployment \
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
--template-file infra/main.bicep \
--parameters \
solutionName="${{ env.SOLUTION_PREFIX }}" \
- aiDeploymentsLocation="$EFFECTIVE_AI_REGION" \
+ aiDeploymentsLocation='${{ env.AZURE_LOCATION }}' \
capacity=${{ env.GPT_MIN_CAPACITY }} \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline" \