From 2a6b283567ce29b1f126a1e6ede62f31617c5092 Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 19 Feb 2026 11:56:06 +0530 Subject: [PATCH 1/4] Migrate GitHub Actions authentication from client secrets to OIDC --- .github/workflows/build-docker-image.yml | 18 +++++++++------- .github/workflows/deploy-linux.yml | 1 + .github/workflows/deploy-orchestrator.yml | 3 --- .github/workflows/deploy-windows.yml | 1 + .github/workflows/deploy.yml | 22 ++++++++++++-------- .github/workflows/job-cleanup-deployment.yml | 13 ++++++------ .github/workflows/job-deploy-linux.yml | 15 +++++++------ .github/workflows/job-deploy-windows.yml | 15 +++++++------ .github/workflows/job-deploy.yml | 16 ++++++-------- .github/workflows/job-docker-build.yml | 17 ++++++++------- .github/workflows/job-send-notification.yml | 3 --- .github/workflows/test-automation-v2.yml | 12 +++++------ .github/workflows/test-automation.yml | 12 +++++------ infra/scripts/checkquota.sh | 13 +++--------- 14 files changed, 80 insertions(+), 81 deletions(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index eef429e6..d2d95847 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -48,14 +48,14 @@ on: permissions: contents: read actions: read + id-token: write jobs: build-and-push: runs-on: ubuntu-latest + environment: production env: ACR_LOGIN_SERVER: ${{ secrets.ACR_LOGIN_SERVER }} - ACR_USERNAME: ${{ secrets.ACR_USERNAME }} - ACR_PASSWORD: ${{ secrets.ACR_PASSWORD }} steps: - name: Checkout repository @@ -68,13 +68,17 @@ jobs: id: date run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - - name: Log in to Azure Container Registry + - name: Login to Azure if: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' || github.ref_name == 'dependabotchanges' }} - uses: azure/docker-login@v2 + uses: azure/login@v2 with: - login-server: ${{ env.ACR_LOGIN_SERVER }} - username: ${{ env.ACR_USERNAME }} - password: ${{ env.ACR_PASSWORD }} + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Log in to Azure Container Registry + if: ${{ github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'demo' || github.ref_name == 'hotfix' || github.ref_name == 'dependabotchanges' }} + run: az acr login --name ${{ env.ACR_LOGIN_SERVER }} - name: Get registry id: registry diff --git a/.github/workflows/deploy-linux.yml b/.github/workflows/deploy-linux.yml index d65a3c16..9b0e5dbb 100644 --- a/.github/workflows/deploy-linux.yml +++ b/.github/workflows/deploy-linux.yml @@ -95,6 +95,7 @@ on: permissions: contents: read actions: read + id-token: write jobs: validate-inputs: runs-on: ubuntu-latest diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml index f8a4d7e6..ae83fbd3 100644 --- a/.github/workflows/deploy-orchestrator.yml +++ b/.github/workflows/deploy-orchestrator.yml @@ -64,9 +64,6 @@ on: env: AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }} -permissions: - contents: read - actions: read jobs: docker-build: uses: ./.github/workflows/job-docker-build.yml diff --git a/.github/workflows/deploy-windows.yml b/.github/workflows/deploy-windows.yml index 491cb1a7..6cd18189 100644 --- a/.github/workflows/deploy-windows.yml +++ b/.github/workflows/deploy-windows.yml @@ -78,6 +78,7 @@ on: permissions: contents: read actions: read + id-token: write jobs: validate-inputs: runs-on: ubuntu-latest diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0a6db726..e40a5bc5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -17,9 +17,11 @@ on: permissions: contents: read actions: read + id-token: write jobs: deploy: runs-on: ubuntu-latest + environment: production outputs: invoice_schema_id: ${{ steps.register.outputs.invoice_schema_id }} propertydamageclaimform_schema_id: ${{ steps.register.outputs.propertylossdamageclaimform_schema_id }} @@ -37,16 +39,15 @@ 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 }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Run Quota Check id: quota-check env: - AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} - AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} - AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} GPT_MIN_CAPACITY: "100" AZURE_REGIONS: ${{ vars.AZURE_REGIONS }} @@ -290,6 +291,7 @@ jobs: if: always() needs: [deploy, e2e-test] runs-on: ubuntu-latest + environment: production env: RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }} AI_SERVICES_NAME: ${{ needs.deploy.outputs.AI_SERVICES_NAME }} @@ -298,9 +300,11 @@ jobs: ENVIRONMENT_NAME: ${{ needs.deploy.outputs.ENVIRONMENT_NAME }} steps: - name: Login to Azure - run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Delete Bicep Deployment if: always() diff --git a/.github/workflows/job-cleanup-deployment.yml b/.github/workflows/job-cleanup-deployment.yml index 0467b9e0..736712d9 100644 --- a/.github/workflows/job-cleanup-deployment.yml +++ b/.github/workflows/job-cleanup-deployment.yml @@ -40,12 +40,10 @@ on: description: 'Docker Image Tag' required: true type: string -permissions: - contents: read - actions: read jobs: cleanup-deployment: runs-on: ${{ inputs.runner_os }} + environment: production continue-on-error: true env: RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }} @@ -201,10 +199,11 @@ jobs: echo "✅ All input parameters validated successfully!" - name: Login to Azure - shell: bash - run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Delete Resource Group (Optimized Cleanup) id: delete_rg diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml index 1c7ac1fc..27abf709 100644 --- a/.github/workflows/job-deploy-linux.yml +++ b/.github/workflows/job-deploy-linux.yml @@ -38,12 +38,10 @@ on: CONTAINER_WEB_APPURL: description: "Container Web App URL" value: ${{ jobs.deploy-linux.outputs.CONTAINER_WEB_APPURL }} -permissions: - contents: read - actions: read jobs: deploy-linux: runs-on: ubuntu-latest + environment: production env: AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }} outputs: @@ -204,9 +202,14 @@ jobs: id: login-azure shell: bash run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} - azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --client-secret ${{ secrets.AZURE_CLIENT_SECRET }} --tenant-id ${{ secrets.AZURE_TENANT_ID }} + azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --federated-credential-provider "github" --tenant-id ${{ secrets.AZURE_TENANT_ID }} + + - name: Login to Azure CLI + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Deploy using azd up and extract values (Linux) id: get_output_linux diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml index 7b0ce43f..132a0340 100644 --- a/.github/workflows/job-deploy-windows.yml +++ b/.github/workflows/job-deploy-windows.yml @@ -38,12 +38,10 @@ on: CONTAINER_WEB_APPURL: description: "Container Web App URL" value: ${{ jobs.deploy-windows.outputs.CONTAINER_WEB_APPURL }} -permissions: - contents: read - actions: read jobs: deploy-windows: runs-on: windows-latest + environment: production env: AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }} outputs: @@ -204,9 +202,14 @@ jobs: id: login-azure shell: bash run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} - azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --client-secret ${{ secrets.AZURE_CLIENT_SECRET }} --tenant-id ${{ secrets.AZURE_TENANT_ID }} + azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --federated-credential-provider "github" --tenant-id ${{ secrets.AZURE_TENANT_ID }} + + - name: Login to Azure CLI + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Deploy using azd up and extract values (Windows) diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml index 40ed81e9..aebe0624 100644 --- a/.github/workflows/job-deploy.yml +++ b/.github/workflows/job-deploy.yml @@ -97,14 +97,12 @@ env: CLEANUP_RESOURCES: ${{ inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources }} RUN_E2E_TESTS: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.run_e2e_tests || 'GoldenPath-Testing') || 'GoldenPath-Testing' }} BUILD_DOCKER_IMAGE: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.build_docker_image || false) || false }} -permissions: - contents: read - actions: read jobs: azure-setup: name: Azure Setup if: inputs.trigger_type != 'workflow_dispatch' || inputs.existing_webapp_url == '' || inputs.existing_webapp_url == null runs-on: ubuntu-latest + environment: production outputs: RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }} ENV_NAME: ${{ steps.generate_env_name.outputs.ENV_NAME }} @@ -317,17 +315,15 @@ jobs: uses: actions/checkout@v4 - name: Login to Azure - shell: bash - run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Run Quota Check id: quota-check env: - AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} - AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} - AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} GPT_MIN_CAPACITY: ${{ env.GPT_MIN_CAPACITY }} AZURE_REGIONS: ${{ vars.AZURE_REGIONS }} diff --git a/.github/workflows/job-docker-build.yml b/.github/workflows/job-docker-build.yml index 185ac7e8..e257f8c3 100644 --- a/.github/workflows/job-docker-build.yml +++ b/.github/workflows/job-docker-build.yml @@ -19,13 +19,11 @@ on: env: BRANCH_NAME: ${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }} -permissions: - contents: read - actions: read jobs: docker-build: if: inputs.trigger_type == 'workflow_dispatch' && inputs.build_docker_image == true runs-on: ubuntu-latest + environment: production outputs: IMAGE_TAG: ${{ steps.generate_docker_tag.outputs.IMAGE_TAG }} steps: @@ -49,12 +47,15 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Log in to Azure Container Registry - uses: azure/docker-login@v2 + - name: Login to Azure + uses: azure/login@v2 with: - login-server: ${{ secrets.ACR_TEST_LOGIN_SERVER }} - username: ${{ secrets.ACR_TEST_USERNAME }} - password: ${{ secrets.ACR_TEST_PASSWORD }} + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Log in to Azure Container Registry + run: az acr login --name ${{ secrets.ACR_TEST_LOGIN_SERVER }} - name: Build and Push ContentProcessor Docker image uses: docker/build-push-action@v6 diff --git a/.github/workflows/job-send-notification.yml b/.github/workflows/job-send-notification.yml index 2f43ca53..c03d4b22 100644 --- a/.github/workflows/job-send-notification.yml +++ b/.github/workflows/job-send-notification.yml @@ -67,9 +67,6 @@ 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' }} -permissions: - contents: read - actions: read jobs: send-notification: runs-on: ubuntu-latest diff --git a/.github/workflows/test-automation-v2.yml b/.github/workflows/test-automation-v2.yml index 4ec41a0b..1f5431d9 100644 --- a/.github/workflows/test-automation-v2.yml +++ b/.github/workflows/test-automation-v2.yml @@ -24,12 +24,10 @@ env: url: ${{ inputs.CP_WEB_URL }} accelerator_name: "Content Processing" test_suite: ${{ inputs.TEST_SUITE }} -permissions: - contents: read - actions: read jobs: test: runs-on: ubuntu-latest + environment: production outputs: TEST_SUCCESS: ${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }} TEST_REPORT_URL: ${{ steps.upload_report.outputs.artifact-url }} @@ -43,9 +41,11 @@ jobs: python-version: '3.13' - name: Login to Azure - run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Install dependencies run: | diff --git a/.github/workflows/test-automation.yml b/.github/workflows/test-automation.yml index 1112a225..989f1378 100644 --- a/.github/workflows/test-automation.yml +++ b/.github/workflows/test-automation.yml @@ -14,14 +14,12 @@ env: url: ${{ inputs.CP_WEB_URL }} CP_RG: ${{ inputs.CP_RG }} accelerator_name: "Content Processing" -permissions: - contents: read - actions: read jobs: test: runs-on: ubuntu-latest + environment: production steps: - name: Checkout repository uses: actions/checkout@v5 @@ -32,9 +30,11 @@ jobs: python-version: '3.12' - name: Login to Azure - run: | - az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }} - az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Install dependencies run: | diff --git a/infra/scripts/checkquota.sh b/infra/scripts/checkquota.sh index 69a20ec0..ff749968 100644 --- a/infra/scripts/checkquota.sh +++ b/infra/scripts/checkquota.sh @@ -5,16 +5,9 @@ IFS=', ' read -ra REGIONS <<< "$AZURE_REGIONS" SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID}" GPT_MIN_CAPACITY="${GPT_MIN_CAPACITY}" -AZURE_CLIENT_ID="${AZURE_CLIENT_ID}" -AZURE_TENANT_ID="${AZURE_TENANT_ID}" -AZURE_CLIENT_SECRET="${AZURE_CLIENT_SECRET}" - -# Authenticate using Managed Identity -echo "Authentication using Managed Identity..." -if ! az login --service-principal -u "$AZURE_CLIENT_ID" -p "$AZURE_CLIENT_SECRET" --tenant "$AZURE_TENANT_ID"; then - echo "❌ Error: Failed to login using Managed Identity." - exit 1 -fi + +# Authentication is handled by the caller workflow via OIDC (azure/login@v2) +# No need to login here - the session is already authenticated echo "🔄 Validating required environment variables..." if [[ -z "$SUBSCRIPTION_ID" || -z "$GPT_MIN_CAPACITY" || -z "$REGIONS" ]]; then From d764d52f5c363670b088894eafbd293355624f79 Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 19 Feb 2026 13:55:50 +0530 Subject: [PATCH 2/4] Refactor cleanup-deployment conditions and update notification email content for clarity --- .github/workflows/deploy-orchestrator.yml | 2 +- .github/workflows/job-send-notification.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml index ae83fbd3..c3be5e9e 100644 --- a/.github/workflows/deploy-orchestrator.yml +++ b/.github/workflows/deploy-orchestrator.yml @@ -121,7 +121,7 @@ jobs: secrets: inherit cleanup-deployment: - if: "!cancelled() && needs.deploy.result == 'success' && needs.deploy.outputs.RESOURCE_GROUP_NAME != '' && inputs.existing_webapp_url == '' && (inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources)" + 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: diff --git a/.github/workflows/job-send-notification.yml b/.github/workflows/job-send-notification.yml index c03d4b22..14d50f15 100644 --- a/.github/workflows/job-send-notification.yml +++ b/.github/workflows/job-send-notification.yml @@ -401,15 +401,15 @@ jobs: EMAIL_BODY=$(cat <Dear Team,

The ${ACCELERATOR_NAME} pipeline executed against the existing 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 (Existing URL)" + "body": "

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" } EOF ) curl -X POST "${LOGICAPP_URL}" \ -H "Content-Type: application/json" \ - -d "$EMAIL_BODY" || echo "Failed to send existing URL success notification" + -d "$EMAIL_BODY" || echo "Failed to send success notification" - name: Send Existing URL Test Failure Notification if: inputs.deploy_result == 'skipped' && inputs.existing_webapp_url != '' && inputs.e2e_test_result == 'failure' @@ -430,12 +430,12 @@ jobs: EMAIL_BODY=$(cat <Dear Team,

The ${ACCELERATOR_NAME} pipeline executed against the existing 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 (Existing URL)" + "body": "

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" } EOF ) curl -X POST "${LOGICAPP_URL}" \ -H "Content-Type: application/json" \ - -d "$EMAIL_BODY" || echo "Failed to send existing URL test failure notification" + -d "$EMAIL_BODY" || echo "Failed to send test failure notification" From 75dbe69810c1a8c57f299e8f12b1c5d1d9b842f9 Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 19 Feb 2026 15:33:28 +0530 Subject: [PATCH 3/4] Added Input paramter to select Codespace/Local deployment --- .../{deploy-linux.yml => deploy-v2.yml} | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) rename .github/workflows/{deploy-linux.yml => deploy-v2.yml} (94%) diff --git a/.github/workflows/deploy-linux.yml b/.github/workflows/deploy-v2.yml similarity index 94% rename from .github/workflows/deploy-linux.yml rename to .github/workflows/deploy-v2.yml index 9b0e5dbb..d00020e6 100644 --- a/.github/workflows/deploy-linux.yml +++ b/.github/workflows/deploy-v2.yml @@ -1,4 +1,4 @@ -name: Deploy-Test-Cleanup (v2) Linux +name: Deploy-Test-Cleanup (v2) on: push: branches: @@ -22,6 +22,14 @@ on: - '.github/workflows/deploy-linux.yml' workflow_dispatch: inputs: + runner_os: + description: 'Deployment Environment' + required: false + type: choice + options: + - 'codespace' + - 'Local' + default: 'codespace' azure_location: description: 'Azure Location For Deployment' required: false @@ -111,11 +119,13 @@ jobs: azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }} azure_existing_ai_project_resource_id: ${{ steps.validate.outputs.azure_existing_ai_project_resource_id }} existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }} + runner_os: ${{ steps.validate.outputs.runner_os }} steps: - name: Validate Workflow Input Parameters id: validate shell: bash env: + INPUT_RUNNER_OS: ${{ github.event.inputs.runner_os }} INPUT_AZURE_LOCATION: ${{ github.event.inputs.azure_location }} INPUT_RESOURCE_GROUP_NAME: ${{ github.event.inputs.resource_group_name }} INPUT_WAF_ENABLED: ${{ github.event.inputs.waf_enabled }} @@ -130,6 +140,15 @@ jobs: echo "🔍 Validating workflow input parameters..." VALIDATION_FAILED=false + # Derive actual runner from runner_os input + RUNNER_OS_INPUT="${INPUT_RUNNER_OS:-codespace}" + if [[ "$RUNNER_OS_INPUT" == "codespace" ]]; then + RUNNER_OS="ubuntu-latest" + else + RUNNER_OS="windows-latest" + fi + echo "✅ runner_os derived as: '$RUNNER_OS'" + # Validate azure_location (Azure region format) LOCATION="${INPUT_AZURE_LOCATION:-australiaeast}" @@ -252,6 +271,7 @@ jobs: # Output validated values echo "passed=true" >> $GITHUB_OUTPUT + echo "runner_os=$RUNNER_OS" >> $GITHUB_OUTPUT echo "azure_location=$LOCATION" >> $GITHUB_OUTPUT echo "resource_group_name=$INPUT_RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT echo "waf_enabled=$WAF_ENABLED" >> $GITHUB_OUTPUT @@ -268,7 +288,7 @@ jobs: if: needs.validate-inputs.outputs.validation_passed == 'true' uses: ./.github/workflows/deploy-orchestrator.yml with: - runner_os: ubuntu-latest + runner_os: ${{ needs.validate-inputs.outputs.runner_os || 'ubuntu-latest' }} azure_location: ${{ needs.validate-inputs.outputs.azure_location || 'australiaeast' }} resource_group_name: ${{ needs.validate-inputs.outputs.resource_group_name || '' }} waf_enabled: ${{ needs.validate-inputs.outputs.waf_enabled == 'true' }} From bcc6a27189025e99b0e1b1ca059f6ad3f98a9dce Mon Sep 17 00:00:00 2001 From: Vamshi-Microsoft Date: Thu, 19 Feb 2026 15:34:10 +0530 Subject: [PATCH 4/4] Remove unused Windows deployment workflow --- .github/workflows/deploy-windows.yml | 266 --------------------------- 1 file changed, 266 deletions(-) delete mode 100644 .github/workflows/deploy-windows.yml diff --git a/.github/workflows/deploy-windows.yml b/.github/workflows/deploy-windows.yml deleted file mode 100644 index 6cd18189..00000000 --- a/.github/workflows/deploy-windows.yml +++ /dev/null @@ -1,266 +0,0 @@ -name: Deploy-Test-Cleanup (v2) Windows -on: - # push: - # branches: - # - main - workflow_dispatch: - inputs: - azure_location: - description: 'Azure Location For Deployment' - required: false - default: 'australiaeast' - type: choice - options: - - 'australiaeast' - - 'centralus' - - 'eastasia' - - 'eastus2' - - 'japaneast' - - 'northeurope' - - 'southeastasia' - - 'uksouth' - resource_group_name: - description: 'Resource Group Name (Optional)' - required: false - default: '' - type: string - - waf_enabled: - description: 'Enable WAF' - required: false - default: false - type: boolean - EXP: - description: 'Enable EXP' - required: false - default: false - type: boolean - build_docker_image: - description: 'Build And Push Docker Image (Optional)' - required: false - default: false - type: boolean - - cleanup_resources: - description: 'Cleanup Deployed Resources' - required: false - default: false - type: boolean - - run_e2e_tests: - description: 'Run End-to-End Tests' - required: false - default: 'GoldenPath-Testing' - type: choice - options: - - 'GoldenPath-Testing' - - 'Smoke-Testing' - - 'None' - - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: - description: 'Log Analytics Workspace ID (Optional)' - required: false - default: '' - type: string - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: - description: 'AI Project Resource ID (Optional)' - required: false - default: '' - type: string - existing_webapp_url: - description: 'Existing Container WebApp URL (Skips Deployment)' - required: false - default: '' - type: string - - # schedule: - # - cron: '0 9,21 * * *' # Runs at 9:00 AM and 9:00 PM GMT -permissions: - contents: read - actions: read - id-token: write -jobs: - validate-inputs: - runs-on: ubuntu-latest - outputs: - validation_passed: ${{ steps.validate.outputs.passed }} - azure_location: ${{ steps.validate.outputs.azure_location }} - resource_group_name: ${{ steps.validate.outputs.resource_group_name }} - waf_enabled: ${{ steps.validate.outputs.waf_enabled }} - exp: ${{ steps.validate.outputs.exp }} - build_docker_image: ${{ steps.validate.outputs.build_docker_image }} - cleanup_resources: ${{ steps.validate.outputs.cleanup_resources }} - run_e2e_tests: ${{ steps.validate.outputs.run_e2e_tests }} - azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }} - azure_existing_ai_project_resource_id: ${{ steps.validate.outputs.azure_existing_ai_project_resource_id }} - existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }} - steps: - - name: Validate Workflow Input Parameters - id: validate - shell: bash - env: - INPUT_AZURE_LOCATION: ${{ github.event.inputs.azure_location }} - INPUT_RESOURCE_GROUP_NAME: ${{ github.event.inputs.resource_group_name }} - INPUT_WAF_ENABLED: ${{ github.event.inputs.waf_enabled }} - INPUT_EXP: ${{ github.event.inputs.EXP }} - INPUT_BUILD_DOCKER_IMAGE: ${{ github.event.inputs.build_docker_image }} - INPUT_CLEANUP_RESOURCES: ${{ github.event.inputs.cleanup_resources }} - INPUT_RUN_E2E_TESTS: ${{ github.event.inputs.run_e2e_tests }} - INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }} - INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }} - INPUT_EXISTING_WEBAPP_URL: ${{ github.event.inputs.existing_webapp_url }} - run: | - echo "🔍 Validating workflow input parameters..." - VALIDATION_FAILED=false - - # Validate azure_location (Azure region format) - LOCATION="${INPUT_AZURE_LOCATION:-australiaeast}" - - if [[ ! "$LOCATION" =~ ^[a-z0-9]+$ ]]; then - echo "❌ ERROR: azure_location '$LOCATION' is invalid. Must contain only lowercase letters and numbers" - VALIDATION_FAILED=true - else - echo "✅ azure_location: '$LOCATION' is valid" - fi - - # Validate resource_group_name (Azure naming convention, optional) - 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 (length: ${#INPUT_RESOURCE_GROUP_NAME})" - VALIDATION_FAILED=true - else - echo "✅ resource_group_name: '$INPUT_RESOURCE_GROUP_NAME' is valid" - fi - else - echo "✅ resource_group_name: Not provided (will be auto-generated)" - fi - - # Validate waf_enabled (boolean) - WAF_ENABLED="${INPUT_WAF_ENABLED:-false}" - if [[ "$WAF_ENABLED" != "true" && "$WAF_ENABLED" != "false" ]]; then - echo "❌ ERROR: waf_enabled must be 'true' or 'false', got: '$WAF_ENABLED'" - VALIDATION_FAILED=true - else - echo "✅ waf_enabled: '$WAF_ENABLED' is valid" - fi - - # Validate EXP (boolean) - EXP_ENABLED="${INPUT_EXP:-false}" - if [[ "$EXP_ENABLED" != "true" && "$EXP_ENABLED" != "false" ]]; then - echo "❌ ERROR: EXP must be 'true' or 'false', got: '$EXP_ENABLED'" - VALIDATION_FAILED=true - else - echo "✅ EXP: '$EXP_ENABLED' is valid" - fi - - # Validate build_docker_image (boolean) - BUILD_DOCKER="${INPUT_BUILD_DOCKER_IMAGE:-false}" - if [[ "$BUILD_DOCKER" != "true" && "$BUILD_DOCKER" != "false" ]]; then - echo "❌ ERROR: build_docker_image must be 'true' or 'false', got: '$BUILD_DOCKER'" - VALIDATION_FAILED=true - else - echo "✅ build_docker_image: '$BUILD_DOCKER' is valid" - fi - - # Validate cleanup_resources (boolean) - CLEANUP_RESOURCES="${INPUT_CLEANUP_RESOURCES:-false}" - if [[ "$CLEANUP_RESOURCES" != "true" && "$CLEANUP_RESOURCES" != "false" ]]; then - echo "❌ ERROR: cleanup_resources must be 'true' or 'false', got: '$CLEANUP_RESOURCES'" - VALIDATION_FAILED=true - else - echo "✅ cleanup_resources: '$CLEANUP_RESOURCES' is valid" - fi - - # Validate run_e2e_tests (specific allowed values) - TEST_OPTION="${INPUT_RUN_E2E_TESTS:-GoldenPath-Testing}" - if [[ "$TEST_OPTION" != "GoldenPath-Testing" && "$TEST_OPTION" != "Smoke-Testing" && "$TEST_OPTION" != "None" ]]; then - echo "❌ ERROR: run_e2e_tests must be one of: GoldenPath-Testing, Smoke-Testing, None, got: '$TEST_OPTION'" - VALIDATION_FAILED=true - else - echo "✅ run_e2e_tests: '$TEST_OPTION' is valid" - fi - - # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then - if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then - echo "❌ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}" - echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'" - VALIDATION_FAILED=true - else - echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format" - fi - else - echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Not provided (optional)" - fi - - # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, Azure Resource ID format) - if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then - if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/([Mm]icrosoft\.[Mm]achine[Ll]earning[Ss]ervices/([Ww]orkspaces|[Pp]rojects)/[^/]+|[Mm]icrosoft\.[Cc]ognitive[Ss]ervices/[Aa]ccounts/[^/]+/[Pp]rojects/[^/]+)$ ]]; then - echo "❌ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:" - echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}" - echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'" - VALIDATION_FAILED=true - else - echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format" - fi - else - echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Not provided (optional)" - fi - - # Validate existing_webapp_url (optional, must start with https) - 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 - else - echo "✅ existing_webapp_url: Not provided (will perform deployment)" - 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!" - - # Output validated values - echo "passed=true" >> $GITHUB_OUTPUT - echo "azure_location=$LOCATION" >> $GITHUB_OUTPUT - echo "resource_group_name=$INPUT_RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT - echo "waf_enabled=$WAF_ENABLED" >> $GITHUB_OUTPUT - echo "exp=$EXP_ENABLED" >> $GITHUB_OUTPUT - echo "build_docker_image=$BUILD_DOCKER" >> $GITHUB_OUTPUT - echo "cleanup_resources=$CLEANUP_RESOURCES" >> $GITHUB_OUTPUT - echo "run_e2e_tests=$TEST_OPTION" >> $GITHUB_OUTPUT - echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" >> $GITHUB_OUTPUT - echo "azure_existing_ai_project_resource_id=$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" >> $GITHUB_OUTPUT - echo "existing_webapp_url=$INPUT_EXISTING_WEBAPP_URL" >> $GITHUB_OUTPUT - - Run: - needs: validate-inputs - if: needs.validate-inputs.outputs.validation_passed == 'true' - uses: ./.github/workflows/deploy-orchestrator.yml - with: - runner_os: windows-latest - azure_location: ${{ needs.validate-inputs.outputs.azure_location || 'australiaeast' }} - resource_group_name: ${{ needs.validate-inputs.outputs.resource_group_name || '' }} - waf_enabled: ${{ needs.validate-inputs.outputs.waf_enabled == 'true' }} - EXP: ${{ needs.validate-inputs.outputs.exp == 'true' }} - build_docker_image: ${{ needs.validate-inputs.outputs.build_docker_image == 'true' }} - cleanup_resources: ${{ needs.validate-inputs.outputs.cleanup_resources == 'true' }} - run_e2e_tests: ${{ needs.validate-inputs.outputs.run_e2e_tests || 'GoldenPath-Testing' }} - AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }} - AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ needs.validate-inputs.outputs.azure_existing_ai_project_resource_id || '' }} - existing_webapp_url: ${{ needs.validate-inputs.outputs.existing_webapp_url || '' }} - trigger_type: ${{ github.event_name }} - secrets: inherit