Deploy-Test-Cleanup (v2) #362
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy-Test-Cleanup (v2) | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'src/ContentProcessor/src/**' | |
| - 'src/**/Dockerfile' | |
| - 'src/**/requirements.txt' | |
| - 'src/**/pyproject.toml' | |
| - 'src/ContentProcessorAPI/app/**' | |
| - 'src/ContentProcessorAPI/helpers/**' | |
| - 'src/ContentProcessorWeb/src/**' | |
| - 'src/ContentProcessorWeb/public/**' | |
| - 'src/ContentProcessorWeb/package.json' | |
| - 'src/ContentProcessorWeb/package-lock.json' | |
| - 'src/ContentProcessorWeb/yarn.lock' | |
| - 'src/ContentProcessorWeb/tsconfig.json' | |
| - 'src/ContentProcessorWeb/config-overrides.js' | |
| - 'src/ContentProcessorWeb/nginx-custom.conf' | |
| - 'src/ContentProcessorWeb/env.sh' | |
| - '.github/workflows/deploy-v2.yml' | |
| workflow_dispatch: | |
| inputs: | |
| runner_os: | |
| description: 'Deployment Environment' | |
| required: false | |
| type: choice | |
| options: | |
| - 'codespace' | |
| - 'Local' | |
| default: 'codespace' | |
| azure_location: | |
| description: 'Azure Region (Non-AI Services)' | |
| 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 | |
| build_docker_image: | |
| description: 'Build & Use Custom Images (Optional)' | |
| required: false | |
| default: false | |
| type: boolean | |
| waf_enabled: | |
| description: 'Deploy WAF' | |
| required: false | |
| default: false | |
| type: boolean | |
| EXP: | |
| description: 'Deploy EXP' | |
| required: false | |
| default: false | |
| type: boolean | |
| enableScalability: | |
| description: 'Enable Scalability (WAF only)' | |
| required: false | |
| default: false | |
| type: boolean | |
| cleanup_resources: | |
| description: 'Auto Delete RG' | |
| 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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: | |
| description: 'Existing Log Analytics Workspace Resource ID (Optional)' | |
| required: false | |
| default: '' | |
| type: string | |
| AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: | |
| description: 'Existing AI Project Resource ID (Optional)' | |
| required: false | |
| default: '' | |
| type: string | |
| existing_webapp_url: | |
| description: 'Run Tests Against Existing RG (Provide Web App URL)' | |
| 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 }} | |
| runner_os: ${{ steps.validate.outputs.runner_os }} | |
| azure_location: ${{ steps.validate.outputs.azure_location }} | |
| resource_group_name: ${{ steps.validate.outputs.resource_group_name }} | |
| waf_enabled: ${{ steps.validate.outputs.waf_enabled }} | |
| enable_scalability: ${{ steps.validate.outputs.enable_scalability }} | |
| 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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ steps.validate.outputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} | |
| 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_ENABLE_SCALABILITY: ${{ github.event.inputs.enableScalability }} | |
| 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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ github.event.inputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID }} | |
| 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 }} | |
| INPUT_RUNNER_OS: ${{ github.event.inputs.runner_os }} | |
| run: | | |
| echo "🔍 Validating workflow input parameters..." | |
| VALIDATION_FAILED=false | |
| # Resolve runner_os from Deployment Environment selection | |
| DEPLOY_ENV="${INPUT_RUNNER_OS:-codespace}" | |
| if [[ "$DEPLOY_ENV" == "codespace" ]]; then | |
| RUNNER_OS="ubuntu-latest" | |
| echo "✅ Deployment Environment: 'codespace' → runner: ubuntu-latest" | |
| elif [[ "$DEPLOY_ENV" == "Local" ]]; then | |
| RUNNER_OS="windows-latest" | |
| echo "✅ Deployment Environment: 'Local' → runner: windows-latest" | |
| else | |
| echo "❌ ERROR: Deployment Environment must be 'codespace' or 'Local', got: '$DEPLOY_ENV'" | |
| VALIDATION_FAILED=true | |
| RUNNER_OS="ubuntu-latest" | |
| fi | |
| # 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 enableScalability (boolean, WAF-only opt-in) | |
| ENABLE_SCALABILITY="${INPUT_ENABLE_SCALABILITY:-false}" | |
| if [[ "$ENABLE_SCALABILITY" != "true" && "$ENABLE_SCALABILITY" != "false" ]]; then | |
| echo "❌ ERROR: enableScalability must be 'true' or 'false', got: '$ENABLE_SCALABILITY'" | |
| VALIDATION_FAILED=true | |
| else | |
| echo "✅ enableScalability: '$ENABLE_SCALABILITY' is valid" | |
| if [[ "$ENABLE_SCALABILITY" == "true" && "$WAF_ENABLED" != "true" ]]; then | |
| echo "ℹ️ Note: enableScalability=true only applies when waf_enabled=true; it will be ignored for non-WAF deployments." | |
| fi | |
| 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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID (optional, Azure Resource ID format) | |
| if [[ -n "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" ]]; then | |
| if [[ ! "$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" =~ ^/subscriptions/[a-fA-F0-9-]+/[Rr]esource[Gg]roups/[^/]+/providers/[Mm]icrosoft\.[Oo]perational[Ii]nsights/[Ww]orkspaces/[^/]+$ ]]; then | |
| echo "❌ ERROR: AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID 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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID'" | |
| VALIDATION_FAILED=true | |
| else | |
| echo "✅ AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: Valid Resource ID format" | |
| fi | |
| else | |
| echo "✅ AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: 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 "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 | |
| echo "enable_scalability=$ENABLE_SCALABILITY" >> $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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID=$INPUT_AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID" >> $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: ${{ 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' }} | |
| enableScalability: ${{ needs.validate-inputs.outputs.enable_scalability == '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_EXISTING_LOG_ANALYTICS_WORKSPACE_RID: ${{ needs.validate-inputs.outputs.AZURE_ENV_EXISTING_LOG_ANALYTICS_WORKSPACE_RID || '' }} | |
| 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 |