From 0943c7eb8deaa64f8dd6d78aaf82610fbadeab61 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Sun, 22 Mar 2026 11:09:42 +0530
Subject: [PATCH 1/5] refactor notification email templates
---
.github/workflows/deploy-orchestrator.yml | 35 ++-
.github/workflows/job-send-notification.yml | 331 ++++++--------------
2 files changed, 119 insertions(+), 247 deletions(-)
diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml
index c3be5e9e..3f55241c 100644
--- a/.github/workflows/deploy-orchestrator.yml
+++ b/.github/workflows/deploy-orchestrator.yml
@@ -101,9 +101,25 @@ jobs:
TEST_SUITE: ${{ inputs.trigger_type == 'workflow_dispatch' && inputs.run_e2e_tests || 'GoldenPath-Testing' }}
secrets: inherit
+ cleanup-deployment:
+ if: "!cancelled() && needs.deploy.outputs.RESOURCE_GROUP_NAME != '' && inputs.existing_webapp_url == '' && (inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources)"
+ needs: [docker-build, deploy, e2e-test]
+ uses: ./.github/workflows/job-cleanup-deployment.yml
+ with:
+ runner_os: ${{ inputs.runner_os }}
+ trigger_type: ${{ inputs.trigger_type }}
+ cleanup_resources: ${{ inputs.cleanup_resources }}
+ existing_webapp_url: ${{ inputs.existing_webapp_url }}
+ RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
+ AZURE_LOCATION: ${{ needs.deploy.outputs.AZURE_LOCATION }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ needs.deploy.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ ENV_NAME: ${{ needs.deploy.outputs.ENV_NAME }}
+ IMAGE_TAG: ${{ needs.deploy.outputs.IMAGE_TAG }}
+ secrets: inherit
+
send-notification:
if: "!cancelled()"
- needs: [docker-build, deploy, e2e-test]
+ needs: [docker-build, deploy, e2e-test, cleanup-deployment]
uses: ./.github/workflows/job-send-notification.yml
with:
trigger_type: ${{ inputs.trigger_type }}
@@ -113,25 +129,10 @@ jobs:
existing_webapp_url: ${{ inputs.existing_webapp_url }}
deploy_result: ${{ needs.deploy.result }}
e2e_test_result: ${{ needs.e2e-test.result }}
+ cleanup_result: ${{ needs.cleanup-deployment.result }}
CONTAINER_WEB_APPURL: ${{ needs.deploy.outputs.CONTAINER_WEB_APPURL }}
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
QUOTA_FAILED: ${{ needs.deploy.outputs.QUOTA_FAILED }}
TEST_SUCCESS: ${{ needs.e2e-test.outputs.TEST_SUCCESS }}
TEST_REPORT_URL: ${{ needs.e2e-test.outputs.TEST_REPORT_URL }}
secrets: inherit
-
- cleanup-deployment:
- if: "!cancelled() && needs.deploy.outputs.RESOURCE_GROUP_NAME != '' && inputs.existing_webapp_url == '' && (inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources)"
- needs: [docker-build, deploy, e2e-test]
- uses: ./.github/workflows/job-cleanup-deployment.yml
- with:
- runner_os: ${{ inputs.runner_os }}
- trigger_type: ${{ inputs.trigger_type }}
- cleanup_resources: ${{ inputs.cleanup_resources }}
- existing_webapp_url: ${{ inputs.existing_webapp_url }}
- RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
- AZURE_LOCATION: ${{ needs.deploy.outputs.AZURE_LOCATION }}
- AZURE_ENV_OPENAI_LOCATION: ${{ needs.deploy.outputs.AZURE_ENV_OPENAI_LOCATION }}
- ENV_NAME: ${{ needs.deploy.outputs.ENV_NAME }}
- IMAGE_TAG: ${{ needs.deploy.outputs.IMAGE_TAG }}
- secrets: inherit
diff --git a/.github/workflows/job-send-notification.yml b/.github/workflows/job-send-notification.yml
index 14d50f15..87154f99 100644
--- a/.github/workflows/job-send-notification.yml
+++ b/.github/workflows/job-send-notification.yml
@@ -33,7 +33,8 @@ on:
type: string
e2e_test_result:
description: 'E2E test job result (success, failure, skipped)'
- required: true
+ required: false
+ default: ''
type: string
CONTAINER_WEB_APPURL:
description: 'Container Web App URL'
@@ -60,6 +61,11 @@ on:
required: false
default: ''
type: string
+ cleanup_result:
+ description: 'Cleanup job result (success, failure, skipped)'
+ required: false
+ default: 'skipped'
+ type: string
env:
GPT_MIN_CAPACITY: 100
@@ -67,6 +73,7 @@ env:
WAF_ENABLED: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.waf_enabled || false) || false }}
EXP: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.EXP || false) || false }}
RUN_E2E_TESTS: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.run_e2e_tests || 'GoldenPath-Testing') || 'GoldenPath-Testing' }}
+
jobs:
send-notification:
runs-on: ubuntu-latest
@@ -74,162 +81,6 @@ jobs:
env:
accelerator_name: "Content Processing"
steps:
- - name: Validate Workflow Input Parameters
- shell: bash
- env:
- INPUT_TRIGGER_TYPE: ${{ inputs.trigger_type }}
- INPUT_WAF_ENABLED: ${{ inputs.waf_enabled }}
- INPUT_EXP: ${{ inputs.EXP }}
- INPUT_RUN_E2E_TESTS: ${{ inputs.run_e2e_tests }}
- INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
- INPUT_DEPLOY_RESULT: ${{ inputs.deploy_result }}
- INPUT_E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
- INPUT_CONTAINER_WEB_APPURL: ${{ inputs.CONTAINER_WEB_APPURL }}
- INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
- INPUT_QUOTA_FAILED: ${{ inputs.QUOTA_FAILED }}
- INPUT_TEST_SUCCESS: ${{ inputs.TEST_SUCCESS }}
- INPUT_TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
- run: |
- echo "🔍 Validating workflow input parameters..."
- VALIDATION_FAILED=false
-
- # Validate trigger_type (required - alphanumeric with underscores)
- if [[ -z "$INPUT_TRIGGER_TYPE" ]]; then
- echo "❌ ERROR: trigger_type is required but was not provided"
- VALIDATION_FAILED=true
- elif [[ ! "$INPUT_TRIGGER_TYPE" =~ ^[a-zA-Z0-9_]+$ ]]; then
- echo "❌ ERROR: trigger_type '$INPUT_TRIGGER_TYPE' is invalid. Must contain only alphanumeric characters and underscores"
- VALIDATION_FAILED=true
- else
- echo "✅ trigger_type: '$INPUT_TRIGGER_TYPE' is valid"
- fi
-
- # Validate waf_enabled (boolean)
- if [[ "$INPUT_WAF_ENABLED" != "true" && "$INPUT_WAF_ENABLED" != "false" ]]; then
- echo "❌ ERROR: waf_enabled must be 'true' or 'false', got: '$INPUT_WAF_ENABLED'"
- VALIDATION_FAILED=true
- else
- echo "✅ waf_enabled: '$INPUT_WAF_ENABLED' is valid"
- fi
-
- # Validate EXP (boolean)
- if [[ "$INPUT_EXP" != "true" && "$INPUT_EXP" != "false" ]]; then
- echo "❌ ERROR: EXP must be 'true' or 'false', got: '$INPUT_EXP'"
- VALIDATION_FAILED=true
- else
- echo "✅ EXP: '$INPUT_EXP' is valid"
- fi
-
- # Validate run_e2e_tests (specific allowed values)
- if [[ -n "$INPUT_RUN_E2E_TESTS" ]]; then
- ALLOWED_VALUES=("None" "GoldenPath-Testing" "Smoke-Testing")
- if [[ ! " ${ALLOWED_VALUES[@]} " =~ " ${INPUT_RUN_E2E_TESTS} " ]]; then
- echo "❌ ERROR: run_e2e_tests '$INPUT_RUN_E2E_TESTS' is invalid. Allowed values: ${ALLOWED_VALUES[*]}"
- VALIDATION_FAILED=true
- else
- echo "✅ run_e2e_tests: '$INPUT_RUN_E2E_TESTS' is valid"
- fi
- fi
-
- # Validate existing_webapp_url (must start with https if provided)
- if [[ -n "$INPUT_EXISTING_WEBAPP_URL" ]]; then
- if [[ ! "$INPUT_EXISTING_WEBAPP_URL" =~ ^https:// ]]; then
- echo "❌ ERROR: existing_webapp_url must start with 'https://', got: '$INPUT_EXISTING_WEBAPP_URL'"
- VALIDATION_FAILED=true
- else
- echo "✅ existing_webapp_url: '$INPUT_EXISTING_WEBAPP_URL' is valid"
- fi
- fi
-
- # Validate deploy_result (required, must be specific values)
- if [[ -z "$INPUT_DEPLOY_RESULT" ]]; then
- echo "❌ ERROR: deploy_result is required but not provided"
- VALIDATION_FAILED=true
- else
- ALLOWED_DEPLOY_RESULTS=("success" "failure" "skipped")
- if [[ ! " ${ALLOWED_DEPLOY_RESULTS[@]} " =~ " ${INPUT_DEPLOY_RESULT} " ]]; then
- echo "❌ ERROR: deploy_result '$INPUT_DEPLOY_RESULT' is invalid. Allowed values: ${ALLOWED_DEPLOY_RESULTS[*]}"
- VALIDATION_FAILED=true
- else
- echo "✅ deploy_result: '$INPUT_DEPLOY_RESULT' is valid"
- fi
- fi
-
- # Validate e2e_test_result (required, must be specific values)
- if [[ -z "$INPUT_E2E_TEST_RESULT" ]]; then
- echo "❌ ERROR: e2e_test_result is required but not provided"
- VALIDATION_FAILED=true
- else
- ALLOWED_TEST_RESULTS=("success" "failure" "skipped")
- if [[ ! " ${ALLOWED_TEST_RESULTS[@]} " =~ " ${INPUT_E2E_TEST_RESULT} " ]]; then
- echo "❌ ERROR: e2e_test_result '$INPUT_E2E_TEST_RESULT' is invalid. Allowed values: ${ALLOWED_TEST_RESULTS[*]}"
- VALIDATION_FAILED=true
- else
- echo "✅ e2e_test_result: '$INPUT_E2E_TEST_RESULT' is valid"
- fi
- fi
-
- # Validate CONTAINER_WEB_APPURL (must start with https if provided)
- if [[ -n "$INPUT_CONTAINER_WEB_APPURL" ]]; then
- if [[ ! "$INPUT_CONTAINER_WEB_APPURL" =~ ^https:// ]]; then
- echo "❌ ERROR: CONTAINER_WEB_APPURL must start with 'https://', got: '$INPUT_CONTAINER_WEB_APPURL'"
- VALIDATION_FAILED=true
- else
- echo "✅ CONTAINER_WEB_APPURL: '$INPUT_CONTAINER_WEB_APPURL' is valid"
- fi
- fi
-
- # Validate RESOURCE_GROUP_NAME (Azure resource group naming convention if provided)
- if [[ -n "$INPUT_RESOURCE_GROUP_NAME" ]]; then
- if [[ ! "$INPUT_RESOURCE_GROUP_NAME" =~ ^[a-zA-Z0-9._\(\)-]+$ ]] || [[ "$INPUT_RESOURCE_GROUP_NAME" =~ \.$ ]]; then
- echo "❌ ERROR: RESOURCE_GROUP_NAME '$INPUT_RESOURCE_GROUP_NAME' is invalid. Must contain only alphanumerics, periods, underscores, hyphens, and parentheses. Cannot end with period."
- VALIDATION_FAILED=true
- elif [[ ${#INPUT_RESOURCE_GROUP_NAME} -gt 90 ]]; then
- echo "❌ ERROR: RESOURCE_GROUP_NAME '$INPUT_RESOURCE_GROUP_NAME' exceeds 90 characters"
- VALIDATION_FAILED=true
- else
- echo "✅ RESOURCE_GROUP_NAME: '$INPUT_RESOURCE_GROUP_NAME' is valid"
- fi
- fi
-
- # Validate QUOTA_FAILED (must be 'true', 'false', or empty string)
- if [[ "$INPUT_QUOTA_FAILED" != "true" && "$INPUT_QUOTA_FAILED" != "false" && "$INPUT_QUOTA_FAILED" != "" ]]; then
- echo "❌ ERROR: QUOTA_FAILED must be 'true', 'false', or empty string, got: '$INPUT_QUOTA_FAILED'"
- VALIDATION_FAILED=true
- else
- echo "✅ QUOTA_FAILED: '$INPUT_QUOTA_FAILED' is valid"
- fi
-
- # Validate TEST_SUCCESS (must be 'true' or 'false' or empty)
- if [[ -n "$INPUT_TEST_SUCCESS" ]]; then
- if [[ "$INPUT_TEST_SUCCESS" != "true" && "$INPUT_TEST_SUCCESS" != "false" ]]; then
- echo "❌ ERROR: TEST_SUCCESS must be 'true', 'false', or empty, got: '$INPUT_TEST_SUCCESS'"
- VALIDATION_FAILED=true
- else
- echo "✅ TEST_SUCCESS: '$INPUT_TEST_SUCCESS' is valid"
- fi
- fi
-
- # Validate TEST_REPORT_URL (must start with https if provided)
- if [[ -n "$INPUT_TEST_REPORT_URL" ]]; then
- if [[ ! "$INPUT_TEST_REPORT_URL" =~ ^https:// ]]; then
- echo "❌ ERROR: TEST_REPORT_URL must start with 'https://', got: '$INPUT_TEST_REPORT_URL'"
- VALIDATION_FAILED=true
- else
- echo "✅ TEST_REPORT_URL: '$INPUT_TEST_REPORT_URL' is valid"
- fi
- fi
-
- # Fail workflow if any validation failed
- if [[ "$VALIDATION_FAILED" == "true" ]]; then
- echo ""
- echo "❌ Parameter validation failed. Please correct the errors above and try again."
- exit 1
- fi
-
- echo ""
- echo "✅ All input parameters validated successfully!"
-
- name: Determine Test Suite Display Name
id: test_suite
shell: bash
@@ -248,24 +99,45 @@ jobs:
echo "TEST_SUITE_NAME=$TEST_SUITE_NAME" >> $GITHUB_OUTPUT
echo "Test Suite: $TEST_SUITE_NAME"
+ - name: Determine Cleanup Status
+ id: cleanup
+ shell: bash
+ env:
+ CLEANUP_RESULT: ${{ inputs.cleanup_result }}
+ run: |
+ case "$CLEANUP_RESULT" in
+ success) echo "CLEANUP_STATUS=✅ SUCCESS" >> $GITHUB_OUTPUT ;;
+ failure) echo "CLEANUP_STATUS=❌ FAILED (Needs Manual Cleanup)" >> $GITHUB_OUTPUT ;;
+ *) echo "CLEANUP_STATUS=⏭️ SKIPPED (Needs Manual Cleanup)" >> $GITHUB_OUTPUT ;;
+ esac
+
+ - name: Determine Configuration Label
+ id: config
+ shell: bash
+ env:
+ WAF_ENABLED: ${{ env.WAF_ENABLED }}
+ EXP: ${{ env.EXP }}
+ run: |
+ WAF_LABEL=$( [ "$WAF_ENABLED" = "true" ] && echo "WAF" || echo "Non-WAF" )
+ EXP_LABEL=$( [ "$EXP" = "true" ] && echo "EXP" || echo "Non-EXP" )
+ echo "CONFIG_LABEL=${WAF_LABEL} + ${EXP_LABEL}" >> $GITHUB_OUTPUT
+
- name: Send Quota Failure Notification
if: inputs.deploy_result == 'failure' && inputs.QUOTA_FAILED == 'true'
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- QUOTA_FAILED: ${{ inputs.QUOTA_FAILED }}
- ACCELERATOR_NAME: ${{ env.accelerator_name }}
- GPT_MIN_CAPACITY: ${{ env.GPT_MIN_CAPACITY }}
- AZURE_REGIONS: ${{ vars.AZURE_REGIONS }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
+ ACCELERATOR_NAME: ${{ env.accelerator_name }}
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
+ CONFIG_LABEL: ${{ steps.config.outputs.CONFIG_LABEL }}
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 ${ACCELERATOR_NAME} deployment has failed due to insufficient quota in the requested regions.
Issue Details:
• Quota check failed for GPT model
• Required GPT Capacity: ${GPT_MIN_CAPACITY}
• Checked Regions: ${AZURE_REGIONS}
Run URL: ${RUN_URL}
Please resolve the quota issue and retry the deployment.
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Failed (Insufficient Quota)"
+ "body": "Dear Team,
We would like to inform you that the ${ACCELERATOR_NAME} deployment has failed due to insufficient quota.
Status Summary:
| Stage | Status |
|---|
| Deployment | ❌ FAILED (Insufficient Quota) |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please resolve the quota issue and retry the deployment.
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Insufficient Quota"
}
EOF
)
@@ -278,23 +150,19 @@ jobs:
if: inputs.deploy_result == 'failure' && inputs.QUOTA_FAILED != 'true'
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- QUOTA_FAILED: ${{ inputs.QUOTA_FAILED }}
- RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
+ INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
ACCELERATOR_NAME: ${{ env.accelerator_name }}
- WAF_ENABLED: ${{ env.WAF_ENABLED }}
- EXP: ${{ env.EXP }}
- GITHUB_REPOSITORY: ${{ github.repository }}
- GITHUB_RUN_ID: ${{ github.run_id }}
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CONFIG_LABEL: ${{ steps.config.outputs.CONFIG_LABEL }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
run: |
- RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
- RESOURCE_GROUP="${RESOURCE_GROUP_NAME}"
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ RESOURCE_GROUP="$INPUT_RESOURCE_GROUP_NAME"
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment process has encountered an issue and has failed to complete successfully.
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• WAF Enabled: ${WAF_ENABLED}
• EXP Enabled: ${EXP}
Run URL: ${RUN_URL}
Please investigate the deployment failure at your earliest convenience.
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Failed"
+ "body": "Dear Team,
We would like to inform you that the ${ACCELERATOR_NAME} deployment has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ❌ FAILED (Deployment Issue) |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please investigate the deployment failure at your earliest convenience.
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Deployment-Failed"
}
EOF
)
@@ -307,38 +175,39 @@ jobs:
if: inputs.deploy_result == 'success' && (inputs.e2e_test_result == 'skipped' || inputs.TEST_SUCCESS == 'true')
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
- TEST_SUCCESS: ${{ inputs.TEST_SUCCESS }}
- CONTAINER_WEB_APPURL: ${{ inputs.CONTAINER_WEB_APPURL }}
- EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
- RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
- TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
- TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
+ INPUT_WEB_APPURL: ${{ inputs.CONTAINER_WEB_APPURL }}
+ INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
+ INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
+ INPUT_TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
+ INPUT_E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
ACCELERATOR_NAME: ${{ env.accelerator_name }}
- WAF_ENABLED: ${{ env.WAF_ENABLED }}
- EXP: ${{ env.EXP }}
+ LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
- LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CONFIG_LABEL: ${{ steps.config.outputs.CONFIG_LABEL }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
+ RUN_E2E_TESTS: ${{ env.RUN_E2E_TESTS }}
+ TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
+
run: |
RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
- WEBAPP_URL="${CONTAINER_WEB_APPURL:-${EXISTING_WEBAPP_URL}}"
- RESOURCE_GROUP="${RESOURCE_GROUP_NAME}"
+ WEBAPP_URL="${INPUT_WEB_APPURL:-$INPUT_EXISTING_WEBAPP_URL}"
+ RESOURCE_GROUP="$INPUT_RESOURCE_GROUP_NAME"
+ TEST_REPORT_URL="$INPUT_TEST_REPORT_URL"
- if [ "${E2E_TEST_RESULT}" = "skipped" ]; then
+ if [ "$INPUT_E2E_TEST_RESULT" = "skipped" ]; then
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment has completed successfully.
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• E2E Tests: Skipped (as configured)
Configuration:
• WAF Enabled: ${WAF_ENABLED}
• EXP Enabled: ${EXP}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Deployment Success"
+ "body": "Dear Team,
We would like to inform you that the ${ACCELERATOR_NAME} deployment has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
else
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment and testing process has completed successfully.
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• E2E Tests: Passed ✅
• Test Suite: ${TEST_SUITE_NAME}
• Test Report: View Report
Configuration:
• WAF Enabled: ${WAF_ENABLED}
• EXP Enabled: ${EXP}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Test Automation - Success"
+ "body": "Dear Team,
We would like to inform you that the ${ACCELERATOR_NAME} deployment and test automation has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ✅ SUCCESS |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• Test Suite: ${TEST_SUITE_NAME}
• Test Report: View Report
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
@@ -352,27 +221,28 @@ jobs:
if: inputs.deploy_result == 'success' && inputs.e2e_test_result != 'skipped' && inputs.TEST_SUCCESS != 'true'
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
- TEST_SUCCESS: ${{ inputs.TEST_SUCCESS }}
- TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
- CONTAINER_WEB_APPURL: ${{ inputs.CONTAINER_WEB_APPURL }}
- EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
- RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
- TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
- ACCELERATOR_NAME: ${{ env.accelerator_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
+ INPUT_WEB_APPURL: ${{ inputs.CONTAINER_WEB_APPURL }}
+ INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
+ INPUT_RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
+ ACCELERATOR_NAME: ${{ env.accelerator_name }}
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
+ CONFIG_LABEL: ${{ steps.config.outputs.CONFIG_LABEL }}
+ RUN_E2E_TESTS: ${{ env.RUN_E2E_TESTS }}
+ TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
+ INPUT_TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
run: |
- RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
- WEBAPP_URL="${CONTAINER_WEB_APPURL:-${EXISTING_WEBAPP_URL}}"
- RESOURCE_GROUP="${RESOURCE_GROUP_NAME}"
+ RUN_URL="https://github.com/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}"
+ TEST_REPORT_URL="$INPUT_TEST_REPORT_URL"
+ WEBAPP_URL="${INPUT_WEB_APPURL:-$INPUT_EXISTING_WEBAPP_URL}"
+ RESOURCE_GROUP="$INPUT_RESOURCE_GROUP_NAME"
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that ${ACCELERATOR_NAME} accelerator test automation process has encountered issues and failed to complete successfully.
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• Deployment Status: ✅ Success
• E2E Tests: ❌ Failed
• Test Suite: ${TEST_SUITE_NAME}
Test Details:
• Test Report: View Report
Run URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Test Automation - Failed"
+ "body": "Dear Team,
We would like to inform you that ${ACCELERATOR_NAME} test automation has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ❌ FAILED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• Test Suite: ${TEST_SUITE_NAME}
• Test Report: View Report
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
}
EOF
)
@@ -385,57 +255,58 @@ jobs:
if: inputs.deploy_result == 'skipped' && inputs.existing_webapp_url != '' && inputs.e2e_test_result == 'success' && (inputs.TEST_SUCCESS == 'true' || inputs.TEST_SUCCESS == '')
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
- E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
- TEST_SUCCESS: ${{ inputs.TEST_SUCCESS }}
- TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
- TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
- ACCELERATOR_NAME: ${{ env.accelerator_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
+ INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
+ INPUT_TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
+ ACCELERATOR_NAME: ${{ env.accelerator_name }}
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
+ RUN_E2E_TESTS: ${{ env.RUN_E2E_TESTS }}
+ TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
run: |
- RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
- EXISTING_URL="${EXISTING_WEBAPP_URL}"
+ RUN_URL="https://github.com/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}"
+ EXISTING_URL="$INPUT_EXISTING_WEBAPP_URL"
+ TEST_REPORT_URL="$INPUT_TEST_REPORT_URL"
EMAIL_BODY=$(cat <Dear Team,The ${ACCELERATOR_NAME} pipeline executed against the Specified WebApp URL and testing process has completed successfully.
Test Results:
• Status: ✅ Passed
• Test Suite: ${TEST_SUITE_NAME}
${TEST_REPORT_URL:+• Test Report: View Report}
• Target URL: ${EXISTING_URL}
Deployment: Skipped
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Test Automation Passed"
+ "body": "Dear Team,
The ${ACCELERATOR_NAME} pipeline executed against the specified Target URL and test automation has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ⏭️ SKIPPED (Tests executed on Pre-deployed RG) |
| E2E Tests | ✅ SUCCESS |
| Cleanup | ${CLEANUP_STATUS} |
Test Results:
• Test Suite: ${TEST_SUITE_NAME}
${TEST_REPORT_URL:+• Test Report: View Report}
• Target URL: ${EXISTING_URL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
curl -X POST "${LOGICAPP_URL}" \
-H "Content-Type: application/json" \
- -d "$EMAIL_BODY" || echo "Failed to send success notification"
+ -d "$EMAIL_BODY" || echo "Failed to send existing URL success notification"
- name: Send Existing URL Test Failure Notification
if: inputs.deploy_result == 'skipped' && inputs.existing_webapp_url != '' && inputs.e2e_test_result == 'failure'
shell: bash
env:
- DEPLOY_RESULT: ${{ inputs.deploy_result }}
- EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
- E2E_TEST_RESULT: ${{ inputs.e2e_test_result }}
- TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
- TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
- ACCELERATOR_NAME: ${{ env.accelerator_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_RUN_ID: ${{ github.run_id }}
+ INPUT_EXISTING_WEBAPP_URL: ${{ inputs.existing_webapp_url }}
+ INPUT_TEST_REPORT_URL: ${{ inputs.TEST_REPORT_URL }}
+ ACCELERATOR_NAME: ${{ env.accelerator_name }}
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
+ CLEANUP_STATUS: ${{ steps.cleanup.outputs.CLEANUP_STATUS }}
+ RUN_E2E_TESTS: ${{ env.RUN_E2E_TESTS }}
+ TEST_SUITE_NAME: ${{ steps.test_suite.outputs.TEST_SUITE_NAME }}
run: |
- RUN_URL="https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
- EXISTING_URL="${EXISTING_WEBAPP_URL}"
+ RUN_URL="https://github.com/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}"
+ EXISTING_URL="$INPUT_EXISTING_WEBAPP_URL"
+ TEST_REPORT_URL="$INPUT_TEST_REPORT_URL"
EMAIL_BODY=$(cat <Dear Team,The ${ACCELERATOR_NAME} pipeline executed against the Specified WebApp URL and the test automation has encountered issues and failed to complete successfully.
Failure Details:
• Target URL: ${EXISTING_URL}
${TEST_REPORT_URL:+• Test Report: View Report}
• Test Suite: ${TEST_SUITE_NAME}
• Deployment: Skipped
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "${ACCELERATOR_NAME} Pipeline - Test Automation Failed"
+ "body": "Dear Team,
The ${ACCELERATOR_NAME} pipeline executed against the specified Target URL and test automation has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ⏭️ SKIPPED (Tests executed on Pre-deployed RG) |
| E2E Tests | ❌ FAILED |
| Cleanup | ${CLEANUP_STATUS} |
Failure Details:
• Target URL: ${EXISTING_URL}
${TEST_REPORT_URL:+• Test Report: View Report}
• Test Suite: ${TEST_SUITE_NAME}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
}
EOF
)
curl -X POST "${LOGICAPP_URL}" \
-H "Content-Type: application/json" \
- -d "$EMAIL_BODY" || echo "Failed to send test failure notification"
+ -d "$EMAIL_BODY" || echo "Failed to send existing URL test failure notification"
From 88f78574241274486ca6177bb5f60a001e4ed67f Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Tue, 24 Mar 2026 10:49:04 +0530
Subject: [PATCH 2/5] fix: Update email subjects to include status icons
---
.github/workflows/job-send-notification.yml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/job-send-notification.yml b/.github/workflows/job-send-notification.yml
index 87154f99..63f414ce 100644
--- a/.github/workflows/job-send-notification.yml
+++ b/.github/workflows/job-send-notification.yml
@@ -137,7 +137,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment has failed due to insufficient quota.
Status Summary:
| Stage | Status |
|---|
| Deployment | ❌ FAILED (Insufficient Quota) |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please resolve the quota issue and retry the deployment.
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Insufficient Quota"
+ "subject": "❌[CI/CD-Automation] [${ACCELERATOR_NAME}] Insufficient Quota"
}
EOF
)
@@ -162,7 +162,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ❌ FAILED (Deployment Issue) |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please investigate the deployment failure at your earliest convenience.
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Deployment-Failed"
+ "subject": "❌[CI/CD-Automation] [${ACCELERATOR_NAME}] Deployment-Failed"
}
EOF
)
@@ -199,7 +199,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ⏭️ SKIPPED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
+ "subject": "✅[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
@@ -207,7 +207,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${ACCELERATOR_NAME} deployment and test automation has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ✅ SUCCESS |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• Test Suite: ${TEST_SUITE_NAME}
• Test Report: View Report
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
+ "subject": "✅[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
@@ -242,7 +242,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,We would like to inform you that ${ACCELERATOR_NAME} test automation has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ✅ SUCCESS |
| E2E Tests | ❌ FAILED |
| Cleanup | ${CLEANUP_STATUS} |
Deployment Details:
• Resource Group: ${RESOURCE_GROUP}
• Web App URL: ${WEBAPP_URL}
• Test Suite: ${TEST_SUITE_NAME}
• Test Report: View Report
Configuration: ${CONFIG_LABEL}
Run URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
+ "subject": "❌[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
}
EOF
)
@@ -272,7 +272,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,The ${ACCELERATOR_NAME} pipeline executed against the specified Target URL and test automation has completed successfully.
Status Summary:
| Stage | Status |
|---|
| Deployment | ⏭️ SKIPPED (Tests executed on Pre-deployed RG) |
| E2E Tests | ✅ SUCCESS |
| Cleanup | ${CLEANUP_STATUS} |
Test Results:
• Test Suite: ${TEST_SUITE_NAME}
${TEST_REPORT_URL:+• Test Report: View Report}
• Target URL: ${EXISTING_URL}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
+ "subject": "✅[CI/CD-Automation] [${ACCELERATOR_NAME}] Success"
}
EOF
)
@@ -302,7 +302,7 @@ jobs:
EMAIL_BODY=$(cat <Dear Team,The ${ACCELERATOR_NAME} pipeline executed against the specified Target URL and test automation has failed.
Status Summary:
| Stage | Status |
|---|
| Deployment | ⏭️ SKIPPED (Tests executed on Pre-deployed RG) |
| E2E Tests | ❌ FAILED |
| Cleanup | ${CLEANUP_STATUS} |
Failure Details:
• Target URL: ${EXISTING_URL}
${TEST_REPORT_URL:+• Test Report: View Report}
• Test Suite: ${TEST_SUITE_NAME}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
- "subject": "[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
+ "subject": "❌[CI/CD-Automation] [${ACCELERATOR_NAME}] E2E Test-Failed"
}
EOF
)
From ffe43cae788fbab2f133f83950e6cb8d6b3ca67a Mon Sep 17 00:00:00 2001
From: Harsh-Microsoft
Date: Tue, 24 Mar 2026 18:29:01 +0530
Subject: [PATCH 3/5] fix: Update dependencies in Bicep and JSON templates
---
infra/main.bicep | 7 +++++++
infra/main.json | 15 +++++++++------
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/infra/main.bicep b/infra/main.bicep
index 38671957..229c0cef 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -1472,6 +1472,10 @@ module avmContainerApp_update 'br/public:avm/res/app/container-app:0.19.0' = {
: []
}
}
+ dependsOn: [
+ cognitiveServicePrivateEndpoint
+ contentUnderstandingPrivateEndpoint
+ ]
}
module avmContainerApp_API_update 'br/public:avm/res/app/container-app:0.19.0' = {
@@ -1595,6 +1599,9 @@ module avmContainerApp_API_update 'br/public:avm/res/app/container-app:0.19.0' =
]
}
}
+ dependsOn: [
+ cognitiveServicePrivateEndpoint
+ ]
}
// ============ //
diff --git a/infra/main.json b/infra/main.json
index 2b87e970..f4049f54 100644
--- a/infra/main.json
+++ b/infra/main.json
@@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.41.2.15936",
- "templateHash": "13407662447721904016"
+ "templateHash": "12196124000444437279"
},
"name": "Content Processing Solution Accelerator",
"description": "Bicep template to deploy the Content Processing Solution Accelerator with AVM compliance."
@@ -41701,9 +41701,9 @@
},
"dependsOn": [
"avmAiServices",
- "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]",
- "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]",
+ "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]",
+ "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"virtualNetwork"
]
@@ -45072,8 +45072,8 @@
},
"dependsOn": [
"avmAiServices_cu",
- "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]",
+ "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"virtualNetwork"
]
},
@@ -63527,7 +63527,9 @@
"dependsOn": [
"avmAppConfig",
"avmContainerAppEnv",
- "avmContainerRegistryReader"
+ "avmContainerRegistryReader",
+ "cognitiveServicePrivateEndpoint",
+ "contentUnderstandingPrivateEndpoint"
]
},
"avmContainerApp_API_update": {
@@ -65201,7 +65203,8 @@
"dependsOn": [
"avmAppConfig",
"avmContainerAppEnv",
- "avmContainerRegistryReader"
+ "avmContainerRegistryReader",
+ "cognitiveServicePrivateEndpoint"
]
}
},
From 297a4cf1ad2511a4670524368367189c1505c226 Mon Sep 17 00:00:00 2001
From: Prajwal D C
Date: Wed, 25 Mar 2026 00:38:22 +0530
Subject: [PATCH 4/5] fix: Content understanding networking issue
---
infra/main.bicep | 6 +-
infra/main.json | 289 ++++++++++++++++++-----------------------------
2 files changed, 112 insertions(+), 183 deletions(-)
diff --git a/infra/main.bicep b/infra/main.bicep
index 229c0cef..6c98afad 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -814,7 +814,7 @@ module cognitiveServicePrivateEndpoint 'br/public:avm/res/network/private-endpoi
}
}
-module avmAiServices_cu 'br/public:avm/res/cognitive-services/account:0.13.2' = {
+module avmAiServices_cu 'br/public:avm/res/cognitive-services/account:0.14.1' = {
name: take('avm.res.cognitive-services.account.content-understanding.${solutionSuffix}', 64)
params: {
@@ -873,6 +873,10 @@ module contentUnderstandingPrivateEndpoint 'br/public:avm/res/network/private-en
name: 'aicu-dns-zone-cognitiveservices'
privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId
}
+ {
+ name: 'ai-services-dns-zone-aiservices'
+ privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId
+ }
{
name: 'aicu-dns-zone-contentunderstanding'
privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.contentUnderstanding]!.outputs.resourceId
diff --git a/infra/main.json b/infra/main.json
index f4049f54..b4735de6 100644
--- a/infra/main.json
+++ b/infra/main.json
@@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.41.2.15936",
- "templateHash": "12196124000444437279"
+ "templateHash": "892970507353265658"
},
"name": "Content Processing Solution Accelerator",
"description": "Bicep template to deploy the Content Processing Solution Accelerator with AVM compliance."
@@ -41777,8 +41777,8 @@
"metadata": {
"_generator": {
"name": "bicep",
- "version": "0.37.4.10188",
- "templateHash": "9381727816193702843"
+ "version": "0.39.26.7824",
+ "templateHash": "6544538318162038728"
},
"name": "Cognitive Services",
"description": "This module deploys a Cognitive Service."
@@ -43123,14 +43123,15 @@
"Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]",
"User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]"
- }
+ },
+ "isHSMManagedCMK": "[equals(tryGet(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), ''), '/'), 7), 'managedHSMs')]"
},
"resources": {
"cMKKeyVault::cMKKey": {
- "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]",
+ "condition": "[and(and(not(empty(parameters('customerManagedKey'))), not(variables('isHSMManagedCMK'))), and(not(empty(parameters('customerManagedKey'))), not(variables('isHSMManagedCMK'))))]",
"existing": true,
"type": "Microsoft.KeyVault/vaults/keys",
- "apiVersion": "2024-11-01",
+ "apiVersion": "2025-05-01",
"subscriptionId": "[split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/')[2]]",
"resourceGroup": "[split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/')[4]]",
"name": "[format('{0}/{1}', last(split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/')), tryGet(parameters('customerManagedKey'), 'keyName'))]"
@@ -43139,7 +43140,7 @@
"condition": "[parameters('enableTelemetry')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2024-03-01",
- "name": "[format('46d3xbcp.res.cognitiveservices-account.{0}.{1}', replace('0.13.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]",
+ "name": "[format('46d3xbcp.res.cognitiveservices-account.{0}.{1}', replace('0.14.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]",
"properties": {
"mode": "Incremental",
"template": {
@@ -43156,10 +43157,10 @@
}
},
"cMKKeyVault": {
- "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]",
+ "condition": "[and(not(empty(parameters('customerManagedKey'))), not(variables('isHSMManagedCMK')))]",
"existing": true,
"type": "Microsoft.KeyVault/vaults",
- "apiVersion": "2024-11-01",
+ "apiVersion": "2025-05-01",
"subscriptionId": "[split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/')[2]]",
"resourceGroup": "[split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/')[4]]",
"name": "[last(split(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '/'))]"
@@ -43193,7 +43194,7 @@
"allowedFqdnList": "[parameters('allowedFqdnList')]",
"apiProperties": "[parameters('apiProperties')]",
"disableLocalAuth": "[parameters('disableLocalAuth')]",
- "encryption": "[if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.KeyVault', 'keyVaultProperties', createObject('identityClientId', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), ''))), reference('cMKUserAssignedIdentity').clientId, null()), 'keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), tryGet(parameters('customerManagedKey'), 'keyVersion'), last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null())]",
+ "encryption": "[if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.KeyVault', 'keyVaultProperties', createObject('identityClientId', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), ''))), reference('cMKUserAssignedIdentity').clientId, null()), 'keyVaultUri', if(not(variables('isHSMManagedCMK')), reference('cMKKeyVault').vaultUri, format('https://{0}.managedhsm.azure.net/', last(split(parameters('customerManagedKey').keyVaultResourceId, '/')))), 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(tryGet(parameters('customerManagedKey'), 'keyVersion'))), parameters('customerManagedKey').keyVersion, if(not(variables('isHSMManagedCMK')), last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/')), fail('Managed HSM CMK encryption requires specifying the ''keyVersion''.'))))), null())]",
"migrationToken": "[parameters('migrationToken')]",
"restore": "[parameters('restore')]",
"restrictOutboundNetworkAccess": "[parameters('restrictOutboundNetworkAccess')]",
@@ -43322,7 +43323,7 @@
"count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]"
},
"type": "Microsoft.Resources/deployments",
- "apiVersion": "2022-09-01",
+ "apiVersion": "2025-04-01",
"name": "[format('{0}-cognitiveService-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]",
"subscriptionId": "[split(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupResourceId'), resourceGroup().id), '/')[2]]",
"resourceGroup": "[split(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupResourceId'), resourceGroup().id), '/')[4]]",
@@ -43378,8 +43379,8 @@
"metadata": {
"_generator": {
"name": "bicep",
- "version": "0.34.44.8038",
- "templateHash": "12389807800450456797"
+ "version": "0.38.5.1644",
+ "templateHash": "16604612898799598358"
},
"name": "Private Endpoints",
"description": "This module deploys a Private Endpoint."
@@ -43406,115 +43407,8 @@
}
},
"metadata": {
- "__bicep_export!": true
- }
- },
- "ipConfigurationType": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "metadata": {
- "description": "Required. The name of the resource that is unique within a resource group."
- }
- },
- "properties": {
- "type": "object",
- "properties": {
- "groupId": {
- "type": "string",
- "metadata": {
- "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string."
- }
- },
- "memberName": {
- "type": "string",
- "metadata": {
- "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string."
- }
- },
- "privateIPAddress": {
- "type": "string",
- "metadata": {
- "description": "Required. A private IP address obtained from the private endpoint's subnet."
- }
- }
- },
- "metadata": {
- "description": "Required. Properties of private endpoint IP configurations."
- }
- }
- },
- "metadata": {
- "__bicep_export!": true
- }
- },
- "privateLinkServiceConnectionType": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "metadata": {
- "description": "Required. The name of the private link service connection."
- }
- },
- "properties": {
- "type": "object",
- "properties": {
- "groupIds": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "metadata": {
- "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`."
- }
- },
- "privateLinkServiceId": {
- "type": "string",
- "metadata": {
- "description": "Required. The resource id of private link service."
- }
- },
- "requestMessage": {
- "type": "string",
- "nullable": true,
- "metadata": {
- "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars."
- }
- }
- },
- "metadata": {
- "description": "Required. Properties of private link service connection."
- }
- }
- },
- "metadata": {
- "__bicep_export!": true
- }
- },
- "customDnsConfigType": {
- "type": "object",
- "properties": {
- "fqdn": {
- "type": "string",
- "nullable": true,
- "metadata": {
- "description": "Optional. FQDN that resolves to private endpoint IP address."
- }
- },
- "ipAddresses": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "metadata": {
- "description": "Required. A list of private IP addresses of the private endpoint."
- }
- }
- },
- "metadata": {
- "__bicep_export!": true
+ "__bicep_export!": true,
+ "description": "The type of a private dns zone group."
}
},
"lockType": {
@@ -43538,12 +43432,19 @@
"metadata": {
"description": "Optional. Specify the type of lock."
}
+ },
+ "notes": {
+ "type": "string",
+ "nullable": true,
+ "metadata": {
+ "description": "Optional. Specify the notes of the lock."
+ }
}
},
"metadata": {
"description": "An AVM-aligned type for a lock.",
"__bicep_imported_from!": {
- "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1"
+ "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.1"
}
}
},
@@ -43565,6 +43466,7 @@
}
},
"metadata": {
+ "description": "The type of a private DNS zone group configuration.",
"__bicep_imported_from!": {
"sourceTemplate": "private-dns-zone-group/main.bicep"
}
@@ -43641,7 +43543,7 @@
"metadata": {
"description": "An AVM-aligned type for a role assignment.",
"__bicep_imported_from!": {
- "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1"
+ "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.1"
}
}
}
@@ -43678,13 +43580,13 @@
},
"ipConfigurations": {
"type": "array",
- "items": {
- "$ref": "#/definitions/ipConfigurationType"
- },
- "nullable": true,
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/properties/properties/ipConfigurations"
+ },
"description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints."
- }
+ },
+ "nullable": true
},
"privateDnsZoneGroup": {
"$ref": "#/definitions/privateDnsZoneGroupType",
@@ -43719,40 +43621,43 @@
},
"tags": {
"type": "object",
- "nullable": true,
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/tags"
+ },
"description": "Optional. Tags to be applied on all resources/resource groups in this deployment."
- }
+ },
+ "nullable": true
},
"customDnsConfigs": {
"type": "array",
- "items": {
- "$ref": "#/definitions/customDnsConfigType"
- },
- "nullable": true,
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/properties/properties/customDnsConfigs"
+ },
"description": "Optional. Custom DNS configurations."
- }
+ },
+ "nullable": true
},
"manualPrivateLinkServiceConnections": {
"type": "array",
- "items": {
- "$ref": "#/definitions/privateLinkServiceConnectionType"
- },
- "nullable": true,
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/properties/properties/manualPrivateLinkServiceConnections"
+ },
"description": "Conditional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource. Required if `privateLinkServiceConnections` is empty."
- }
+ },
+ "nullable": true
},
"privateLinkServiceConnections": {
"type": "array",
- "items": {
- "$ref": "#/definitions/privateLinkServiceConnectionType"
- },
- "nullable": true,
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/properties/properties/privateLinkServiceConnections"
+ },
"description": "Conditional. A grouping of information about the connection to the remote resource. Required if `manualPrivateLinkServiceConnections` is empty."
- }
+ },
+ "nullable": true
},
"enableTelemetry": {
"type": "bool",
@@ -43787,8 +43692,8 @@
"avmTelemetry": {
"condition": "[parameters('enableTelemetry')]",
"type": "Microsoft.Resources/deployments",
- "apiVersion": "2024-03-01",
- "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.11.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]",
+ "apiVersion": "2025-04-01",
+ "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.11.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]",
"properties": {
"mode": "Incremental",
"template": {
@@ -43806,7 +43711,7 @@
},
"privateEndpoint": {
"type": "Microsoft.Network/privateEndpoints",
- "apiVersion": "2024-05-01",
+ "apiVersion": "2024-10-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"tags": "[parameters('tags')]",
@@ -43838,7 +43743,7 @@
"name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]",
"properties": {
"level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]",
- "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]"
+ "notes": "[coalesce(tryGet(parameters('lock'), 'notes'), if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.'))]"
},
"dependsOn": [
"privateEndpoint"
@@ -43869,7 +43774,7 @@
"privateEndpoint_privateDnsZoneGroup": {
"condition": "[not(empty(parameters('privateDnsZoneGroup')))]",
"type": "Microsoft.Resources/deployments",
- "apiVersion": "2022-09-01",
+ "apiVersion": "2025-04-01",
"name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]",
"properties": {
"expressionEvaluationOptions": {
@@ -43894,8 +43799,8 @@
"metadata": {
"_generator": {
"name": "bicep",
- "version": "0.34.44.8038",
- "templateHash": "13997305779829540948"
+ "version": "0.38.5.1644",
+ "templateHash": "24141742673128945"
},
"name": "Private Endpoint Private DNS Zone Groups",
"description": "This module deploys a Private Endpoint Private DNS Zone Group."
@@ -43919,7 +43824,8 @@
}
},
"metadata": {
- "__bicep_export!": true
+ "__bicep_export!": true,
+ "description": "The type of a private DNS zone group configuration."
}
}
},
@@ -43949,33 +43855,30 @@
}
}
},
- "variables": {
- "copy": [
- {
- "name": "privateDnsZoneConfigsVar",
- "count": "[length(parameters('privateDnsZoneConfigs'))]",
- "input": {
- "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]",
- "properties": {
- "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]"
- }
- }
- }
- ]
- },
"resources": {
"privateEndpoint": {
"existing": true,
"type": "Microsoft.Network/privateEndpoints",
- "apiVersion": "2024-05-01",
+ "apiVersion": "2024-10-01",
"name": "[parameters('privateEndpointName')]"
},
"privateDnsZoneGroup": {
"type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
- "apiVersion": "2024-05-01",
+ "apiVersion": "2024-10-01",
"name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]",
"properties": {
- "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]"
+ "copy": [
+ {
+ "name": "privateDnsZoneConfigs",
+ "count": "[length(parameters('privateDnsZoneConfigs'))]",
+ "input": {
+ "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigs')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigs')].privateDnsZoneResourceId, '/')))]",
+ "properties": {
+ "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigs')].privateDnsZoneResourceId]"
+ }
+ }
+ }
+ ]
}
}
},
@@ -44036,14 +43939,15 @@
"metadata": {
"description": "The location the resource was deployed into."
},
- "value": "[reference('privateEndpoint', '2024-05-01', 'full').location]"
+ "value": "[reference('privateEndpoint', '2024-10-01', 'full').location]"
},
"customDnsConfigs": {
"type": "array",
- "items": {
- "$ref": "#/definitions/customDnsConfigType"
- },
"metadata": {
+ "__bicep_resource_derived_type!": {
+ "source": "Microsoft.Network/privateEndpoints@2024-01-01#properties/properties/properties/customDnsConfigs",
+ "output": true
+ },
"description": "The custom DNS configurations of the private endpoint."
},
"value": "[reference('privateEndpoint').customDnsConfigs]"
@@ -44076,7 +43980,7 @@
"secretsExport": {
"condition": "[not(equals(parameters('secretsExportConfiguration'), null()))]",
"type": "Microsoft.Resources/deployments",
- "apiVersion": "2022-09-01",
+ "apiVersion": "2025-04-01",
"name": "[format('{0}-secrets-kv', uniqueString(deployment().name, parameters('location')))]",
"subscriptionId": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[2]]",
"resourceGroup": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[4]]",
@@ -44100,8 +44004,8 @@
"metadata": {
"_generator": {
"name": "bicep",
- "version": "0.37.4.10188",
- "templateHash": "10828079590669389085"
+ "version": "0.39.26.7824",
+ "templateHash": "356315690886888607"
}
},
"definitions": {
@@ -44130,7 +44034,7 @@
"metadata": {
"description": "An AVM-aligned type for the output of the secret set via the secrets export feature.",
"__bicep_imported_from!": {
- "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1"
+ "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.1"
}
}
},
@@ -44153,7 +44057,7 @@
"metadata": {
"description": "An AVM-aligned type for the secret to set via the secrets export feature.",
"__bicep_imported_from!": {
- "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1"
+ "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.1"
}
}
}
@@ -44179,7 +44083,7 @@
"keyVault": {
"existing": true,
"type": "Microsoft.KeyVault/vaults",
- "apiVersion": "2024-11-01",
+ "apiVersion": "2025-05-01",
"name": "[parameters('keyVaultName')]"
},
"secrets": {
@@ -44188,7 +44092,7 @@
"count": "[length(parameters('secretsToSet'))]"
},
"type": "Microsoft.KeyVault/vaults/secrets",
- "apiVersion": "2024-11-01",
+ "apiVersion": "2025-05-01",
"name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretsToSet')[copyIndex()].name)]",
"properties": {
"value": "[parameters('secretsToSet')[copyIndex()].value]"
@@ -44297,6 +44201,22 @@
"networkInterfaceResourceIds": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceResourceIds.value]"
}
}
+ },
+ "primaryKey": {
+ "type": "securestring",
+ "nullable": true,
+ "metadata": {
+ "description": "The primary access key."
+ },
+ "value": "[if(not(parameters('disableLocalAuth')), listKeys('cognitiveService', '2025-06-01').key1, null())]"
+ },
+ "secondaryKey": {
+ "type": "securestring",
+ "nullable": true,
+ "metadata": {
+ "description": "The secondary access key."
+ },
+ "value": "[if(not(parameters('disableLocalAuth')), listKeys('cognitiveService', '2025-06-01').key2, null())]"
}
}
}
@@ -44349,6 +44269,10 @@
"name": "aicu-dns-zone-cognitiveservices",
"privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)).outputs.resourceId.value]"
},
+ {
+ "name": "ai-services-dns-zone-aiservices",
+ "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)).outputs.resourceId.value]"
+ },
{
"name": "aicu-dns-zone-contentunderstanding",
"privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)).outputs.resourceId.value]"
@@ -45072,6 +44996,7 @@
},
"dependsOn": [
"avmAiServices_cu",
+ "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"virtualNetwork"
From f21877e414a4ec7855f239e4fcef88ad45dca12b Mon Sep 17 00:00:00 2001
From: Thanusree-Microsoft
<168087422+Thanusree-Microsoft@users.noreply.github.com>
Date: Thu, 26 Mar 2026 17:25:48 +0530
Subject: [PATCH 5/5] Update RBAC role name in Deployment Guide
---
docs/DeploymentGuide.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md
index a04f3a3c..1ee9a35e 100644
--- a/docs/DeploymentGuide.md
+++ b/docs/DeploymentGuide.md
@@ -16,7 +16,7 @@ Ensure you have access to an [Azure subscription](https://azure.microsoft.com/fr
|------------------------------|-----------|-------------|
| **Contributor** | Subscription or Resource Group | Create and manage Azure resources |
| **User Access Administrator** | Subscription or Resource Group | Manage user access and role assignments |
-| **Role Based Access Control** | Subscription/Resource Group level | Configure RBAC permissions |
+| **Role Based Access Control Admin** | Subscription/Resource Group level | Configure RBAC permissions |
| **Application Administrator** | Tenant | Create app registrations for authentication |
**🔍 How to Check Your Permissions:**