From 2d2acaeaedeb063c6caf711a086735028e72a668 Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Wed, 4 Dec 2024 21:08:31 +0530
Subject: [PATCH 1/6] unit test cases and one click deploy pipeline
---
.github/workflows/deploy.yml | 253 +++++++++++++++++++++++++++++++++++
.github/workflows/tests.yml | 111 +++++++++++++++
2 files changed, 364 insertions(+)
create mode 100644 .github/workflows/deploy.yml
create mode 100644 .github/workflows/tests.yml
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 00000000..3a16967a
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,253 @@
+name: CI-Validate Deployment
+
+on:
+ push:
+ branches:
+ - main
+ schedule:
+ - cron: '0 6,18 * * *' # Runs at 6:00 AM and 6:00 PM GMT
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v3
+
+ - 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 }}
+ # Check if service principal exists
+ az ad sp show --id ${{ secrets.AZURE_CLIENT_ID }}
+
+ - name: Install Bicep CLI
+ run: az bicep install
+
+ - name: Generate Unique Solution Prefix and Environment Name
+ id: generate_solution_prefix
+ run: |
+ set -e
+ COMMON_PART="pslc"
+ TIMESTAMP=$(date +%s)
+ UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 3)
+ UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
+ ENVIRONMENT_NAME="env-${UNIQUE_SOLUTION_PREFIX}" # Dynamically generated environment name
+ echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
+ echo "ENVIRONMENT_NAME=${ENVIRONMENT_NAME}" >> $GITHUB_ENV
+ echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}, ENVIRONMENT_NAME: ${ENVIRONMENT_NAME}"
+
+ - name: Deploy Template at Subscription Level
+ id: deploy
+ run: |
+ set -e
+ echo "Deploying template at the subscription level...."
+ az deployment sub create \
+ --location WestUS \
+ --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
+ --template-file infra/main.bicep \
+ --parameters \
+ authClientId=${{ secrets.AZURE_CLIENT_ID }} \
+ authClientSecret=${{ secrets.AZURE_CLIENT_SECRET }} \
+ environmentName=rg-env-pslc88 \
+ location=NorthCentralUS \
+ principalId=${{ secrets.AZURE_PRINCIPAL_ID }} # Added Principal ID
+
+ - name: Update Web App Docker Configuration
+ run: |
+ set -e
+ echo "Updating the Web App to use the ACR Docker image..."
+
+ # Use the dynamically generated web app name from the previous step
+ webapp_name=app-backend-6esreazijnwm4
+ container_registry="byocgacontainerreg.azurecr.io"
+ image_name="webapp:dev"
+
+ # Set up Web App with the correct ACR image
+ az webapp config container set \
+ --name $webapp_name \
+ --resource-group rg-env-pslc88 \
+ --docker-custom-image-name "$container_registry/$image_name" \
+ --docker-registry-server-url "https://$container_registry" \
+ --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
+ --query "containerSettings" \
+ --output json
+
+ - name: List KeyVaults and Store in Array
+ id: list_keyvaults
+ run: |
+ set -e
+ echo "Listing all KeyVaults in the subscription..."
+
+ # Get the list of KeyVaults in the subscription
+ keyvaults=$(az resource list --resource-type "Microsoft.KeyVault/vaults" --query "[].name" -o tsv)
+
+ if [ -z "$keyvaults" ]; then
+ echo "No KeyVaults found in the subscription."
+ 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
+
+ - name: Delete Bicep Deployment
+ if: success()
+ run: |
+ set -e
+ echo "Deleting the resources from the subscription..."
+ az deployment sub delete \
+ --name ${{ env.SOLUTION_PREFIX }} \
+ --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
+ --no-wait
+
+ - name: Wait for resource deletion to complete
+ run: |
+ # List of KeyVaults and additional resources
+ 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.SOLUTION_PREFIX }}-openai" "${{ env.SOLUTION_PREFIX }}-cogser")
+
+ echo "List of resources to check: ${resources_to_check[@]}"
+
+ # Get the list of resources in YAML format
+ resource_list=$(az resource list --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} --output yaml)
+
+ # 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
+
+ # 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 subscription."
+ resource_found=true
+ else
+ echo "Resource '$resource' does not exist in the subscription."
+ fi
+ done
+
+ # If any resource exists, retry
+ if [ "$resource_found" = true ]; then
+ retries=$((retries + 1))
+ if [ "$retries" -ge "$max_retries" ]; then
+ echo "Maximum retry attempts reached. Exiting."
+ break
+ else
+ # Wait for the appropriate interval for the current retry
+ echo "Waiting for ${retry_intervals[$retries-1]} seconds before retrying..."
+ sleep ${retry_intervals[$retries-1]}
+ fi
+ else
+ echo "No resources found. Exiting."
+ break
+ fi
+ done
+
+ - name: Purging the Resources
+ if: success()
+ run: |
+ set -e
+ # Define variables
+ OPENAI_COMMON_PART="-openai"
+ openai_name="${{ env.SOLUTION_PREFIX }}${OPENAI_COMMON_PART}"
+ echo "Azure OpenAI: $openai_name"
+
+ MULTISERVICE_COMMON_PART="-cogser"
+ multiservice_account_name="${{ env.SOLUTION_PREFIX }}${MULTISERVICE_COMMON_PART}"
+ echo "Azure MultiService Account: $multiservice_account_name"
+
+ # Purge OpenAI Resource
+ echo "Purging the OpenAI Resource..."
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$openai_name --verbose; then
+ echo "Failed to purge openai resource: $openai_name"
+ else
+ echo "Purged the openai resource: $openai_name"
+ fi
+
+ # Purge MultiService Account Resource
+ echo "Purging the MultiService Account Resource..."
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$multiservice_account_name --verbose; then
+ echo "Failed to purge multiService account resource: $multiservice_account_name"
+ else
+ echo "Purged the multiService account resource: $multiservice_account_name"
+ fi
+
+ # Ensure KEYVAULTS is properly formatted as a comma-separated string
+ 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..."
+ az keyvault purge --name "$keyvault_name" --no-wait
+ else
+ echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
+ fi
+ done
+
+ echo "Resource purging completed successfully"
+
+ - name: Send Notification on Failure
+ if: failure()
+ run: |
+
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+
+ # Construct the email body
+ EMAIL_BODY=$(cat <Dear Team,
We would like to inform you that the Client Advisor Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
${OUTPUT}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
+ }
+ EOF
+ )
+
+ # Send the notification
+ curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send notification"
\ No newline at end of file
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 00000000..760261f8
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,111 @@
+name: Tests
+
+on:
+ push:
+ branches:
+ - main # Trigger on push to the main branch
+ pull_request:
+ branches:
+ - main # Trigger on pull requests to the main branch
+ types:
+ - opened
+ - ready_for_review
+ - reopened
+ - synchronize
+
+jobs:
+ backend_tests:
+ name: Backend Tests
+ runs-on: ubuntu-latest # Use the latest Ubuntu runner
+
+ steps:
+ - uses: actions/checkout@v4 # Checkout the repository
+
+ # Set up Python environment for Backend
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.11" # Set Python version
+
+ - name: Install Backend Dependencies
+ run: |
+ python -m pip install -r requirements.txt
+ python -m pip install coverage pytest-cov
+ python -m pip install azure-keyvault-secrets
+
+ - name: Run Backend Tests with Coverage
+ run: |
+ if python -m pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=coverage-junit.xml; then
+ echo "Tests completed, checking coverage."
+ # Only fail if coverage does not meet criteria
+ if [ -f coverage.xml ]; then
+ COVERAGE=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); coverage = root.find('coverage').get('lines').split('%')[0]; print(float(coverage))")
+ if (( $(echo "$COVERAGE < 80" | bc -l) )); then
+ echo "Coverage is below 80%, failing the job."
+ exit 1
+ fi
+ fi
+ else
+ echo "No tests found, skipping coverage check."
+ fi
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: backend-coverage
+ path: |
+ coverage.xml # Correct path to backend coverage
+ coverage-junit.xml # Correct path to backend JUnit report
+ htmlcov/ # Correct path to backend HTML coverage report
+
+ frontend_tests:
+ name: Frontend Tests
+ runs-on: ubuntu-latest # Use the latest Ubuntu runner
+
+ steps:
+ - uses: actions/checkout@v4 # Checkout the repository
+
+ # Set up Node.js environment for Frontend
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '20' # Set the Node.js version
+
+ - name: Cache npm dependencies
+ uses: actions/cache@v3
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+
+ - name: Navigate to frontend directory
+ run: cd frontend
+
+ - name: Install Frontend Dependencies
+ run: |
+ cd frontend # Change to the frontend directory
+ npm install # Install dependencies from frontend/package.json
+
+ - name: Run Frontend Tests with Coverage
+ run: |
+ cd frontend # Change to the frontend directory
+ if npm run test -- --coverage; then
+ echo "Tests completed, checking coverage."
+ # Check coverage report and ensure it meets threshold
+ if [ -f frontend/coverage/lcov-report/index.html ]; then
+ COVERAGE=$(cat frontend/coverage/lcov-report/index.html | grep -oP 'total: \K[0-9]+(\.[0-9]+)?')
+ if (( $(echo "$COVERAGE < 80" | bc -l) )); then
+ echo "Coverage is below 80%, failing the job."
+ exit 1
+ fi
+ fi
+ else
+ echo "No tests found, skipping coverage check."
+ fi
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: frontend-coverage
+ path: |
+ frontend/coverage/ # Correct path to frontend coverage
+ frontend/coverage/lcov-report/ # Correct path to frontend lcov report
\ No newline at end of file
From 41054c97d1b9540206931f89012ba4f44787c123 Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Wed, 4 Dec 2024 22:43:07 +0530
Subject: [PATCH 2/6] changes in deployment file
---
.github/workflows/deploy.yml | 47 ++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 3a16967a..fd7057e7 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,11 +1,17 @@
name: CI-Validate Deployment
on:
- push:
- branches:
- - main
- schedule:
- - cron: '0 6,18 * * *' # Runs at 6:00 AM and 6:00 PM GMT
+ push:
+ branches:
+ - main # Trigger on push to the main branch
+ pull_request:
+ branches:
+ - main # Trigger on pull requests to the main branch
+ types:
+ - opened
+ - ready_for_review
+ - reopened
+ - synchronize
jobs:
deploy:
@@ -42,41 +48,47 @@ jobs:
echo "ENVIRONMENT_NAME=${ENVIRONMENT_NAME}" >> $GITHUB_ENV
echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}, ENVIRONMENT_NAME: ${ENVIRONMENT_NAME}"
- - name: Deploy Template at Subscription Level
+ - name: Deploy Bicep Template at Subscription Level
id: deploy
run: |
set -e
- echo "Deploying template at the subscription level...."
- az deployment sub create \
+ echo "Deploying bicep template at the subscription level...."
+ deployment_output=$(az deployment sub create \
--location WestUS \
--subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
--template-file infra/main.bicep \
--parameters \
authClientId=${{ secrets.AZURE_CLIENT_ID }} \
authClientSecret=${{ secrets.AZURE_CLIENT_SECRET }} \
- environmentName=rg-env-pslc88 \
+ environmentName=${{ env.ENVIRONMENT_NAME }} \
location=NorthCentralUS \
- principalId=${{ secrets.AZURE_PRINCIPAL_ID }} # Added Principal ID
+ principalId=${{ secrets.AZURE_PRINCIPAL_ID }} \
+ --query "properties.outputs.webappName.value" --output json)
+
+ # Extract the webapp name from JSON response using jq
+ webapp_name=$(echo $deployment_output | jq -r .)
+ echo "webapp_name=$webapp_name" >> $GITHUB_ENV
+ echo "Deployment completed with webapp_name: $webapp_name"
- name: Update Web App Docker Configuration
run: |
set -e
echo "Updating the Web App to use the ACR Docker image..."
-
- # Use the dynamically generated web app name from the previous step
- webapp_name=app-backend-6esreazijnwm4
+
+ # Use the dynamically retrieved web app name from the deployment step
+ webapp_name=${{ env.webapp_name }}
container_registry="byocgacontainerreg.azurecr.io"
image_name="webapp:dev"
# Set up Web App with the correct ACR image
az webapp config container set \
--name $webapp_name \
- --resource-group rg-env-pslc88 \
+ --resource-group rg-${{ env.ENVIRONMENT_NAME }} \
--docker-custom-image-name "$container_registry/$image_name" \
--docker-registry-server-url "https://$container_registry" \
--subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
--query "containerSettings" \
- --output json
+ --output json
- name: List KeyVaults and Store in Array
id: list_keyvaults
@@ -109,7 +121,7 @@ jobs:
# Output the formatted array and save it to the environment variable
echo "KEYVAULTS=$keyvault_array" >> $GITHUB_ENV
fi
-
+
- name: Delete Bicep Deployment
if: success()
run: |
@@ -236,7 +248,6 @@ jobs:
- name: Send Notification on Failure
if: failure()
run: |
-
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
# Construct the email body
@@ -250,4 +261,4 @@ jobs:
# Send the notification
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
- -d "$EMAIL_BODY" || echo "Failed to send notification"
\ No newline at end of file
+ -d "$EMAIL_BODY" || echo "Failed to send notification"
From 1a51871767c01bd33656b049c94a8fb38320bdbc Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Wed, 4 Dec 2024 23:36:22 +0530
Subject: [PATCH 3/6] added output in main.bicep
---
.github/workflows/deploy.yml | 2 +-
infra/main.bicep | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index fd7057e7..98eb5979 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -128,7 +128,7 @@ jobs:
set -e
echo "Deleting the resources from the subscription..."
az deployment sub delete \
- --name ${{ env.SOLUTION_PREFIX }} \
+ --name rg-${{ env.ENVIRONMENT_NAME }} \
--subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
--no-wait
diff --git a/infra/main.bicep b/infra/main.bicep
index ee0c9826..334135ac 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -306,3 +306,4 @@ output AZURE_COSMOSDB_DATABASE string = cosmos.outputs.databaseName
output AZURE_COSMOSDB_CONVERSATIONS_CONTAINER string = cosmos.outputs.containerName
output AUTH_ISSUER_URI string = authIssuerUri
+output webappName string = appServiceName
From a5e164cd1bb10a423a1e760d4e2b97ed0ea709f5 Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Thu, 5 Dec 2024 00:04:28 +0530
Subject: [PATCH 4/6] scheduled the pipeline at 6 AM and 6 PM GMT
---
.github/workflows/deploy.yml | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 98eb5979..9355a970 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -3,15 +3,9 @@ name: CI-Validate Deployment
on:
push:
branches:
- - main # Trigger on push to the main branch
- pull_request:
- branches:
- - main # Trigger on pull requests to the main branch
- types:
- - opened
- - ready_for_review
- - reopened
- - synchronize
+ - main
+ schedule:
+ - cron: '0 6,18 * * *' # Runs at 6:00 AM and 6:00 PM GMT
jobs:
deploy:
From b59e9a914150c749f43edc47cb753bfc5bc297d1 Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Mon, 9 Dec 2024 21:17:30 +0530
Subject: [PATCH 5/6] validated through deployment.json
---
.github/workflows/deploy.yml | 254 +++++++++++++----------------------
infra/main.bicep | 1 -
2 files changed, 93 insertions(+), 162 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 9355a970..5a43fd8b 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -10,7 +10,6 @@ on:
jobs:
deploy:
runs-on: ubuntu-latest
-
steps:
- name: Checkout Code
uses: actions/checkout@v3
@@ -23,139 +22,84 @@ 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 }}
- # Check if service principal exists
- az ad sp show --id ${{ secrets.AZURE_CLIENT_ID }}
- name: Install Bicep CLI
run: az bicep install
- - name: Generate Unique Solution Prefix and Environment Name
+ - name: Generate Resource Group Name
+ id: generate_rg_name
+ run: |
+ echo "Generating a unique resource group name..."
+ TIMESTAMP=$(date +%Y%m%d%H%M%S)
+ COMMON_PART="pslautomationRes"
+ UNIQUE_RG_NAME="${COMMON_PART}${TIMESTAMP}"
+ echo "RESOURCE_GROUP_NAME=${UNIQUE_RG_NAME}" >> $GITHUB_ENV
+ echo "Generated Resource_GROUP_PREFIX: ${UNIQUE_RG_NAME}"
+
+ - name: Check and Create Resource Group
+ id: check_create_rg
+ run: |
+ set -e
+ echo "Checking if resource group exists..."
+ 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; }
+ else
+ echo "Resource group already exists."
+ fi
+
+ - name: Generate Unique Solution Prefix
id: generate_solution_prefix
run: |
set -e
- COMMON_PART="pslc"
+ COMMON_PART="pslr"
TIMESTAMP=$(date +%s)
UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 3)
UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
- ENVIRONMENT_NAME="env-${UNIQUE_SOLUTION_PREFIX}" # Dynamically generated environment name
echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
- echo "ENVIRONMENT_NAME=${ENVIRONMENT_NAME}" >> $GITHUB_ENV
- echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}, ENVIRONMENT_NAME: ${ENVIRONMENT_NAME}"
+ echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
- - name: Deploy Bicep Template at Subscription Level
+ - name: Deploy Bicep Template
id: deploy
run: |
set -e
- echo "Deploying bicep template at the subscription level...."
- deployment_output=$(az deployment sub create \
- --location WestUS \
- --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
- --template-file infra/main.bicep \
+ az deployment group create \
+ --resource-group ${{ env.RESOURCE_GROUP_NAME }} \
+ --template-file infrastructure/deployment.json \
--parameters \
- authClientId=${{ secrets.AZURE_CLIENT_ID }} \
- authClientSecret=${{ secrets.AZURE_CLIENT_SECRET }} \
- environmentName=${{ env.ENVIRONMENT_NAME }} \
- location=NorthCentralUS \
- principalId=${{ secrets.AZURE_PRINCIPAL_ID }} \
- --query "properties.outputs.webappName.value" --output json)
-
- # Extract the webapp name from JSON response using jq
- webapp_name=$(echo $deployment_output | jq -r .)
- echo "webapp_name=$webapp_name" >> $GITHUB_ENV
- echo "Deployment completed with webapp_name: $webapp_name"
-
- - name: Update Web App Docker Configuration
+ HostingPlanName="${{ env.SOLUTION_PREFIX }}-plan" \
+ ApplicationInsightsName="appins-${{ env.SOLUTION_PREFIX }}" \
+ WebsiteName="webapp-${{ env.SOLUTION_PREFIX }}" \
+ CosmosDBName="db-cosmos-${{ env.SOLUTION_PREFIX }}" \
+ CosmosDBRegion="NorthCentralUS" \
+ AzureSearchService="search-${{ env.SOLUTION_PREFIX }}" \
+ AzureOpenAIResource="aoai-${{ env.SOLUTION_PREFIX }}" \
+ WorkspaceName="worksp-${{ env.SOLUTION_PREFIX }}"
+
+ - name: Wait for Resource Deletion to Complete
run: |
- set -e
- echo "Updating the Web App to use the ACR Docker image..."
-
- # Use the dynamically retrieved web app name from the deployment step
- webapp_name=${{ env.webapp_name }}
- container_registry="byocgacontainerreg.azurecr.io"
- image_name="webapp:dev"
-
- # Set up Web App with the correct ACR image
- az webapp config container set \
- --name $webapp_name \
- --resource-group rg-${{ env.ENVIRONMENT_NAME }} \
- --docker-custom-image-name "$container_registry/$image_name" \
- --docker-registry-server-url "https://$container_registry" \
- --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
- --query "containerSettings" \
- --output json
-
- - name: List KeyVaults and Store in Array
- id: list_keyvaults
- run: |
- set -e
- echo "Listing all KeyVaults in the subscription..."
-
- # Get the list of KeyVaults in the subscription
- keyvaults=$(az resource list --resource-type "Microsoft.KeyVault/vaults" --query "[].name" -o tsv)
-
- if [ -z "$keyvaults" ]; then
- echo "No KeyVaults found in the subscription."
- 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
-
- - name: Delete Bicep Deployment
- if: success()
- run: |
- set -e
- echo "Deleting the resources from the subscription..."
- az deployment sub delete \
- --name rg-${{ env.ENVIRONMENT_NAME }} \
- --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} \
- --no-wait
-
- - name: Wait for resource deletion to complete
- run: |
- # List of KeyVaults and additional resources
- 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.SOLUTION_PREFIX }}-openai" "${{ env.SOLUTION_PREFIX }}-cogser")
-
- echo "List of resources to check: ${resources_to_check[@]}"
+ # List of resources to check based on SOLUTION_PREFIX
+ resources_to_check=(
+ "aoai-${{ env.SOLUTION_PREFIX }}"
+ "appins-${{ env.SOLUTION_PREFIX }}"
+ "db-cosmos-${{ env.SOLUTION_PREFIX }}"
+ "${{ env.SOLUTION_PREFIX }}-plan"
+ "search-${{ env.SOLUTION_PREFIX }}"
+ "webapp-${{ env.SOLUTION_PREFIX }}"
+ "worksp-${{ env.SOLUTION_PREFIX }}"
+ )
# Get the list of resources in YAML format
resource_list=$(az resource list --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} --output yaml)
-
- # Maximum number of retries
+
+ # Maximum number of retries and retry intervals
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
-
# Iterate through the resources to check
for resource in "${resources_to_check[@]}"; do
echo "Checking resource: $resource"
@@ -174,7 +118,6 @@ jobs:
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
@@ -187,72 +130,61 @@ jobs:
- name: Purging the Resources
if: success()
run: |
- set -e
- # Define variables
- OPENAI_COMMON_PART="-openai"
- openai_name="${{ env.SOLUTION_PREFIX }}${OPENAI_COMMON_PART}"
- echo "Azure OpenAI: $openai_name"
-
- MULTISERVICE_COMMON_PART="-cogser"
- multiservice_account_name="${{ env.SOLUTION_PREFIX }}${MULTISERVICE_COMMON_PART}"
- echo "Azure MultiService Account: $multiservice_account_name"
-
- # Purge OpenAI Resource
- echo "Purging the OpenAI Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$openai_name --verbose; then
- echo "Failed to purge openai resource: $openai_name"
- else
- echo "Purged the openai resource: $openai_name"
- fi
-
- # Purge MultiService Account Resource
- echo "Purging the MultiService Account Resource..."
- if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$multiservice_account_name --verbose; then
- echo "Failed to purge multiService account resource: $multiservice_account_name"
- else
- echo "Purged the multiService account resource: $multiservice_account_name"
- fi
-
- # Ensure KEYVAULTS is properly formatted as a comma-separated string
- KEYVAULTS="${{ env.KEYVAULTS }}"
-
- # Remove the surrounding square brackets, if they exist
- stripped_keyvaults=$(echo "$KEYVAULTS" | sed 's/\[\|\]//g')
+ set -e
+ # Purging resources based on solution prefix
+ echo "Purging resources..."
+
+ # List of resources to purge
+ resources_to_purge=(
+ "aoai-${{ env.SOLUTION_PREFIX }}"
+ "appins-${{ env.SOLUTION_PREFIX }}"
+ "db-cosmos-${{ env.SOLUTION_PREFIX }}"
+ "${{ env.SOLUTION_PREFIX }}-plan"
+ "search-${{ env.SOLUTION_PREFIX }}"
+ "webapp-${{ env.SOLUTION_PREFIX }}"
+ "worksp-${{ env.SOLUTION_PREFIX }}"
+ )
- # 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..."
- az keyvault purge --name "$keyvault_name" --no-wait
+ for resource in "${resources_to_purge[@]}"; do
+ echo "Purging resource: $resource"
+ if ! az resource delete --ids /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/providers/Microsoft.CognitiveServices/locations/uksouth/deletedAccounts/$resource --verbose; then
+ echo "Failed to purge resource: $resource"
else
- echo "KeyVault '$keyvault_name' is not soft-deleted. No action taken."
+ echo "Purged the resource: $resource"
fi
done
echo "Resource purging completed successfully"
-
+
+ - name: Delete Bicep Deployment
+ if: success()
+ 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 exists. 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 exist."
+ fi
+
- name: Send Notification on Failure
if: failure()
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
-
- # Construct the email body
+
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the Client Advisor Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
${OUTPUT}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
+ "body": "Dear Team,
We would like to inform you that the Research Assistant Automation process has encountered an issue and has failed to complete successfully.
Build URL: ${RUN_URL}
${OUTPUT}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
"
}
EOF
)
-
- # Send the notification
+
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"
diff --git a/infra/main.bicep b/infra/main.bicep
index 334135ac..ee0c9826 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -306,4 +306,3 @@ output AZURE_COSMOSDB_DATABASE string = cosmos.outputs.databaseName
output AZURE_COSMOSDB_CONVERSATIONS_CONTAINER string = cosmos.outputs.containerName
output AUTH_ISSUER_URI string = authIssuerUri
-output webappName string = appServiceName
From ee9be99d0fe827b6fbdfc0ac29c072f4dab9db43 Mon Sep 17 00:00:00 2001
From: "Priyanka Singhal (Persistent Systems Inc)"
Date: Tue, 10 Dec 2024 17:48:34 +0530
Subject: [PATCH 6/6] Validated deleting the main resource group
---
.github/workflows/deploy.yml | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 5a43fd8b..29d3e5f3 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -76,6 +76,23 @@ jobs:
AzureSearchService="search-${{ env.SOLUTION_PREFIX }}" \
AzureOpenAIResource="aoai-${{ env.SOLUTION_PREFIX }}" \
WorkspaceName="worksp-${{ env.SOLUTION_PREFIX }}"
+
+ - name: Delete Bicep Deployment
+ if: success()
+ 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 exists. 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 exist."
+ fi
- name: Wait for Resource Deletion to Complete
run: |
@@ -156,23 +173,6 @@ jobs:
echo "Resource purging completed successfully"
- - name: Delete Bicep Deployment
- if: success()
- 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 exists. 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 exist."
- fi
-
- name: Send Notification on Failure
if: failure()
run: |
@@ -187,4 +187,4 @@ jobs:
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
-H "Content-Type: application/json" \
- -d "$EMAIL_BODY" || echo "Failed to send notification"
+ -d "$EMAIL_BODY" || echo "Failed to send notification"
\ No newline at end of file