11name : Deploy-Test-Cleanup Pipeline
22
33on :
4- workflow_run :
5- workflows : ["Build Docker and Optional Push"]
6- types :
7- - completed
8- branches :
9- - vee-pipeline-fixes
10- schedule :
11- - cron : ' 0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
12- workflow_dispatch :
4+ workflow_run :
5+ workflows : ["Build Docker and Optional Push"]
6+ types :
7+ - completed
8+ branches :
9+ - vee-pipeline-fixes
10+ schedule :
11+ - cron : ' 0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
12+ workflow_dispatch :
1313
1414env :
1515 GPT_MIN_CAPACITY : 150
@@ -34,32 +34,22 @@ jobs:
3434 run : |
3535 az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
3636
37- - name : Install Azure OpenAI Extension
37+ - name : Run Quota Check
38+ id : quota-check
3839 run : |
39- az extension add --upgrade -n openai
40-
41- - name : Select Region with Sufficient OpenAI Quota
42- id : select_region
43- run : |
44- regions=("eastus2" "francecentral" "westus3" "southcentralus")
45- required_quota=150
46- selected_region=""
47- for region in "${regions[@]}"; do
48- available_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].limit" -o tsv)
49- used_quota=$(az openai quota show --location "$region" --query "quotas[?name=='OpenAI.GlobalStandard.gpt-4o'].used" -o tsv)
50- if [[ $((available_quota - used_quota)) -ge $required_quota ]]; then
51- selected_region="$region"
52- break
40+ export AZURE_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}
41+ export AZURE_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}
42+ export AZURE_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
43+ export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
44+ export GPT_MIN_CAPACITY="${{ env.GPT_MIN_CAPACITY }}"
45+ export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
46+ chmod +x scripts/checkquota.sh
47+ if ! scripts/checkquota.sh; then
48+ # If quota check fails due to insufficient quota, set the flag
49+ if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
50+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
5351 fi
54- done
55- if [[ -z "$selected_region" ]]; then
56- echo "No region with sufficient quota found."
57- echo "QUOTA_FAILED=true" >> $GITHUB_ENV
58- exit 1
59- else
60- echo "Selected region: $selected_region"
61- echo "SELECTED_REGION=$selected_region" >> $GITHUB_ENV
62- echo "selected_region=$selected_region" >> $GITHUB_OUTPUT
52+ exit 1 # Fail the pipeline if any other failure occurs
6353 fi
6454
6555 - name : Send Notification on Quota Failure
10292 rg_exists=$(az group exists --name ${{ env.RESOURCE_GROUP_NAME }})
10393 if [ "$rg_exists" = "false" ]; then
10494 echo "Resource group does not exist. Creating..."
105- az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location ${{ env.SELECTED_REGION }} || { echo "Error creating resource group"; exit 1; }
95+ az group create --name ${{ env.RESOURCE_GROUP_NAME }} --location northcentralus || { echo "Error creating resource group"; exit 1; }
10696 else
10797 echo "Resource group already exists."
10898 fi
@@ -140,12 +130,11 @@ jobs:
140130 --template-file infra/main.bicep \
141131 --parameters \
142132 solutionName="${{ env.SOLUTION_PREFIX }}" \
143- aiDeploymentsLocation="${{ env.SELECTED_REGION }} " \
133+ aiDeploymentsLocation="eastus " \
144134 useWafAlignedArchitecture=false \
145135 capacity=${{ env.GPT_MIN_CAPACITY }} \
146136 imageVersion="${IMAGE_TAG}" \
147137 createdBy="Pipeline"
148-
149138 - name : Assign Contributor role to Service Principal
150139 if : always()
151140 run : |
@@ -155,6 +144,7 @@ jobs:
155144 --role "Contributor" \
156145 --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ env.RESOURCE_GROUP_NAME }}
157146
147+
158148 - name : Get Deployment Output and extract Values
159149 id : get_output
160150 run : |
@@ -202,15 +192,22 @@ jobs:
202192
203193 set -e
204194 echo "Fetching Log Analytics workspace from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
195+
196+ # Run the az monitor log-analytics workspace list command to get the workspace name
205197 log_analytics_workspace_name=$(az monitor log-analytics workspace list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[0].name" -o tsv)
198+
206199 if [ -z "$log_analytics_workspace_name" ]; then
207200 echo "No Log Analytics workspace found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
208201 else
209202 echo "LOG_ANALYTICS_WORKSPACE_NAME=${log_analytics_workspace_name}" >> $GITHUB_ENV
210203 echo "Log Analytics workspace name : ${log_analytics_workspace_name}"
211204 fi
205+
212206 echo "Fetching OpenAI resource from resource group ${{ env.RESOURCE_GROUP_NAME }}..."
207+
208+ # Run the az resource list command to get the OpenAI resource name
213209 openai_resource_name=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --resource-type "Microsoft.CognitiveServices/accounts" --query "[0].name" -o tsv)
210+
214211 if [ -z "$openai_resource_name" ]; then
215212 echo "No OpenAI resource found in resource group ${{ env.RESOURCE_GROUP_NAME }}."
216213 exit 1
@@ -226,12 +223,17 @@ jobs:
226223
227224 set -e
228225 echo "Listing all KeyVaults in the resource group ${RESOURCE_GROUP_NAME}..."
226+
227+ # Get the list of KeyVaults in the specified resource group
229228 keyvaults=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "[?type=='Microsoft.KeyVault/vaults'].name" -o tsv)
229+
230230 if [ -z "$keyvaults" ]; then
231231 echo "No KeyVaults found in resource group ${RESOURCE_GROUP_NAME}."
232232 echo "KEYVAULTS=[]" >> $GITHUB_ENV # If no KeyVaults found, set an empty array
233233 else
234234 echo "KeyVaults found: $keyvaults"
235+
236+ # Format the list into an array with proper formatting (no trailing comma)
235237 keyvault_array="["
236238 first=true
237239 for kv in $keyvaults; do
@@ -243,6 +245,8 @@ jobs:
243245 fi
244246 done
245247 keyvault_array="$keyvault_array]"
248+
249+ # Output the formatted array and save it to the environment variable
246250 echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
247251 fi
248252
@@ -269,28 +273,50 @@ jobs:
269273 run : |
270274
271275 set -e
276+ # Purge Log Analytics Workspace
272277 echo "Purging the Log Analytics Workspace..."
273278 if ! az monitor log-analytics workspace delete --force --resource-group ${{ env.RESOURCE_GROUP_NAME }} --workspace-name ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }} --yes --verbose; then
274279 echo "Failed to purge Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
275280 else
276281 echo "Purged the Log Analytics workspace: ${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}"
277282 fi
283+
278284 echo "Log analytics workspace resource purging completed successfully"
285+
279286
280287 - name : Wait for resource deletion to complete
281288 if : always()
282289 run : |
290+
291+ # List of keyvaults
283292 KEYVAULTS="${{ env.KEYVAULTS }}"
293+
294+ # Remove the surrounding square brackets, if they exist
284295 stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
296+
297+ # Convert the comma-separated string into an array
285298 IFS=',' read -r -a resources_to_check <<< "$stripped_keyvaults"
299+
300+ # Append new resources to the array
286301 resources_to_check+=("${{ env.LOG_ANALYTICS_WORKSPACE_NAME }}" "${{ env.OPENAI_RESOURCE_NAME }}")
302+
287303 echo "List of resources to check: ${resources_to_check[@]}"
304+
305+ # Maximum number of retries
288306 max_retries=3
307+
308+ # Retry intervals in seconds (30, 60, 120)
289309 retry_intervals=(30 60 120)
310+
311+ # Retry mechanism to check resources
290312 retries=0
291313 while true; do
292314 resource_found=false
315+
316+ # Get the list of resources in YAML format again on each retry
293317 resource_list=$(az resource list --resource-group ${{ env.RESOURCE_GROUP_NAME }} --output yaml)
318+
319+ # Iterate through the resources to check
294320 for resource in "${resources_to_check[@]}"; do
295321 echo "Checking resource: $resource"
296322 if echo "$resource_list" | grep -q "name: $resource"; then
@@ -300,12 +326,15 @@ jobs:
300326 echo "Resource '$resource' does not exist in the resource group."
301327 fi
302328 done
329+
330+ # If any resource exists, retry
303331 if [ "$resource_found" = true ]; then
304332 retries=$((retries + 1))
305333 if [ "$retries" -gt "$max_retries" ]; then
306334 echo "Maximum retry attempts reached. Exiting."
307335 break
308336 else
337+ # Wait for the appropriate interval for the current retry
309338 echo "Waiting for ${retry_intervals[$retries-1]} seconds before retrying..."
310339 sleep ${retry_intervals[$retries-1]}
311340 fi
@@ -314,30 +343,44 @@ jobs:
314343 break
315344 fi
316345 done
317-
346+
318347 - name : Purging the Resources
319348 if : always()
320349 run : |
321350
322351 set -e
352+
323353 echo "Azure OpenAI: ${{ env.OPENAI_RESOURCE_NAME }}"
354+
355+ # Purge OpenAI Resource
324356 echo "Purging the OpenAI Resource..."
325- 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
357+ 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
326358 echo "Failed to purge openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
327359 else
328360 echo "Purged the openai resource: ${{ env.OPENAI_RESOURCE_NAME }}"
329361 fi
362+
363+ # List of keyvaults
330364 KEYVAULTS="${{ env.KEYVAULTS }}"
365+
366+ # Remove the surrounding square brackets, if they exist
331367 stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
368+
369+ # Convert the comma-separated string into an array
332370 IFS=',' read -r -a keyvault_array <<< "$stripped_keyvaults"
371+
333372 echo "Using KeyVaults Array..."
334373 for keyvault_name in "${keyvault_array[@]}"; do
335374 echo "Processing KeyVault: $keyvault_name"
375+ # Check if the KeyVault is soft-deleted
336376 deleted_vaults=$(az keyvault list-deleted --query "[?name=='$keyvault_name']" -o json --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }})
377+
378+ # If the KeyVault is found in the soft-deleted state, purge it
337379 if [ "$(echo "$deleted_vaults" | jq length)" -gt 0 ]; then
338380 echo "KeyVault '$keyvault_name' is soft-deleted. Proceeding to purge..."
381+ # Purge the KeyVault
339382 if az keyvault purge --name "$keyvault_name" --no-wait; then
340- echo "Successfully purged KeyVault '$keyvault_name'."
383+ echo "Successfully purged KeyVault '$keyvault_name'."
341384 else
342385 echo "Failed to purge KeyVault '$keyvault_name'."
343386 fi
@@ -351,12 +394,14 @@ jobs:
351394 if : failure() || needs.deploy.result == 'failure'
352395 run : |
353396 RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
397+
354398 EMAIL_BODY=$(cat <<EOF
355399 {
356400 "body": "<p>Dear Team,</p><p>We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Build URL:</strong> <a href=\"${RUN_URL}\">${RUN_URL}</a><br></p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>"
357401 }
358402 EOF
359403 )
404+
360405 curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
361406 -H "Content-Type: application/json" \
362407 -d "$EMAIL_BODY" || echo "Failed to send notification"
@@ -365,4 +410,4 @@ jobs:
365410 if : always()
366411 run : |
367412 az logout
368- echo "Logged out from Azure."
413+ echo "Logged out from Azure."
0 commit comments