@@ -116,18 +116,190 @@ jobs:
116116 QUOTA_FAILED : ${{ steps.quota_failure_output.outputs.QUOTA_FAILED }}
117117
118118 steps :
119+ - name : Validate Workflow Input Parameters
120+ shell : bash
121+ env :
122+ INPUT_TRIGGER_TYPE : ${{ inputs.trigger_type }}
123+ INPUT_RUNNER_OS : ${{ inputs.runner_os }}
124+ INPUT_BUILD_DOCKER_IMAGE : ${{ inputs.build_docker_image }}
125+ INPUT_AZURE_LOCATION : ${{ inputs.azure_location }}
126+ INPUT_RESOURCE_GROUP_NAME : ${{ inputs.resource_group_name }}
127+ INPUT_WAF_ENABLED : ${{ inputs.waf_enabled }}
128+ INPUT_EXP : ${{ inputs.exp }}
129+ INPUT_CLEANUP_RESOURCES : ${{ inputs.cleanup_resources }}
130+ INPUT_RUN_E2E_TESTS : ${{ inputs.run_e2e_tests }}
131+ INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID : ${{ inputs.azure_env_log_anlytics_workspace_id }}
132+ INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID : ${{ inputs.azure_existing_ai_project_resource_id }}
133+ INPUT_EXISTING_WEBAPP_URL : ${{ inputs.existing_webapp_url }}
134+ INPUT_DOCKER_IMAGE_TAG : ${{ inputs.docker_image_tag }}
135+ run : |
136+ echo "🔍 Validating workflow input parameters..."
137+ VALIDATION_FAILED=false
138+
139+ # Validate trigger_type (required - alphanumeric with underscores)
140+ if [[ -z "$INPUT_TRIGGER_TYPE" ]]; then
141+ echo "❌ ERROR: trigger_type is required but was not provided"
142+ VALIDATION_FAILED=true
143+ elif [[ ! "$INPUT_TRIGGER_TYPE" =~ ^[a-zA-Z0-9_]+$ ]]; then
144+ echo "❌ ERROR: trigger_type '$INPUT_TRIGGER_TYPE' is invalid. Must contain only alphanumeric characters and underscores"
145+ VALIDATION_FAILED=true
146+ else
147+ echo "✅ trigger_type: '$INPUT_TRIGGER_TYPE' is valid"
148+ fi
149+
150+ # Validate runner_os (required - must be specific values)
151+ ALLOWED_RUNNER_OS=("ubuntu-latest" "windows-latest")
152+ if [[ -z "$INPUT_RUNNER_OS" ]]; then
153+ echo "❌ ERROR: runner_os is required but was not provided"
154+ VALIDATION_FAILED=true
155+ elif [[ ! " ${ALLOWED_RUNNER_OS[@]} " =~ " ${INPUT_RUNNER_OS} " ]]; then
156+ echo "❌ ERROR: runner_os '$INPUT_RUNNER_OS' is invalid. Allowed values: ${ALLOWED_RUNNER_OS[*]}"
157+ VALIDATION_FAILED=true
158+ else
159+ echo "✅ runner_os: '$INPUT_RUNNER_OS' is valid"
160+ fi
161+
162+ # Validate build_docker_image (boolean)
163+ if [[ "$INPUT_BUILD_DOCKER_IMAGE" != "true" && "$INPUT_BUILD_DOCKER_IMAGE" != "false" ]]; then
164+ echo "❌ ERROR: build_docker_image must be 'true' or 'false', got: '$INPUT_BUILD_DOCKER_IMAGE'"
165+ VALIDATION_FAILED=true
166+ else
167+ echo "✅ build_docker_image: '$INPUT_BUILD_DOCKER_IMAGE' is valid"
168+ fi
169+
170+ # Validate azure_location (Azure region format)
171+ if [[ -n "$INPUT_AZURE_LOCATION" ]]; then
172+ if [[ ! "$INPUT_AZURE_LOCATION" =~ ^[a-z0-9]+$ ]]; then
173+ echo "❌ ERROR: azure_location '$INPUT_AZURE_LOCATION' is invalid. Must contain only lowercase letters and numbers (e.g., 'australiaeast', 'westus2')"
174+ VALIDATION_FAILED=true
175+ else
176+ echo "✅ azure_location: '$INPUT_AZURE_LOCATION' is valid"
177+ fi
178+ fi
179+
180+ # Validate resource_group_name (Azure resource group naming convention)
181+ if [[ -n "$INPUT_RESOURCE_GROUP_NAME" ]]; then
182+ if [[ ! "$INPUT_RESOURCE_GROUP_NAME" =~ ^[a-zA-Z0-9._\(\)-]+$ ]] || [[ "$INPUT_RESOURCE_GROUP_NAME" =~ \.$ ]]; then
183+ echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' is invalid. Must contain only alphanumerics, periods, underscores, hyphens, and parentheses. Cannot end with period."
184+ VALIDATION_FAILED=true
185+ elif [[ ${#INPUT_RESOURCE_GROUP_NAME} -gt 90 ]]; then
186+ echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' exceeds 90 characters"
187+ VALIDATION_FAILED=true
188+ else
189+ echo "✅ resource_group_name: '$INPUT_RESOURCE_GROUP_NAME' is valid"
190+ fi
191+ fi
192+
193+ # Validate waf_enabled (boolean)
194+ if [[ "$INPUT_WAF_ENABLED" != "true" && "$INPUT_WAF_ENABLED" != "false" ]]; then
195+ echo "❌ ERROR: waf_enabled must be 'true' or 'false', got: '$INPUT_WAF_ENABLED'"
196+ VALIDATION_FAILED=true
197+ else
198+ echo "✅ waf_enabled: '$INPUT_WAF_ENABLED' is valid"
199+ fi
200+
201+ # Validate EXP (boolean)
202+ if [[ "$INPUT_EXP" != "true" && "$INPUT_EXP" != "false" ]]; then
203+ echo "❌ ERROR: EXP must be 'true' or 'false', got: '$INPUT_EXP'"
204+ VALIDATION_FAILED=true
205+ else
206+ echo "✅ EXP: '$INPUT_EXP' is valid"
207+ fi
208+
209+ # Validate cleanup_resources (boolean)
210+ if [[ "$INPUT_CLEANUP_RESOURCES" != "true" && "$INPUT_CLEANUP_RESOURCES" != "false" ]]; then
211+ echo "❌ ERROR: cleanup_resources must be 'true' or 'false', got: '$INPUT_CLEANUP_RESOURCES'"
212+ VALIDATION_FAILED=true
213+ else
214+ echo "✅ cleanup_resources: '$INPUT_CLEANUP_RESOURCES' is valid"
215+ fi
216+
217+ # Validate run_e2e_tests (specific allowed values)
218+ if [[ -n "$INPUT_RUN_E2E_TESTS" ]]; then
219+ ALLOWED_VALUES=("None" "GoldenPath-Testing" "Smoke-Testing")
220+ if [[ ! " ${ALLOWED_VALUES[@]} " =~ " ${INPUT_RUN_E2E_TESTS} " ]]; then
221+ echo "❌ ERROR: run_e2e_tests '$INPUT_RUN_E2E_TESTS' is invalid. Allowed values: ${ALLOWED_VALUES[*]}"
222+ VALIDATION_FAILED=true
223+ else
224+ echo "✅ run_e2e_tests: '$INPUT_RUN_E2E_TESTS' is valid"
225+ fi
226+ fi
227+
228+ # Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (Azure Resource ID format)
229+ if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then
230+ if [[ ! "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/resourceGroups/[^/]+/providers/microsoft\.operationalinsights/workspaces/[^/]+$ ]]; then
231+ echo "❌ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:"
232+ echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}"
233+ echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'"
234+ VALIDATION_FAILED=true
235+ else
236+ echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format"
237+ fi
238+ fi
239+
240+ # Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (Azure Resource ID format)
241+ if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then
242+ if [[ ! "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" =~ ^/subscriptions/[a-fA-F0-9-]+/resourceGroups/[^/]+/providers/(Microsoft\.MachineLearningServices/(workspaces|projects)/[^/]+|Microsoft\.CognitiveServices/accounts/[^/]+/projects/[^/]+)$ ]]; then
243+ echo "❌ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:"
244+ echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}"
245+ echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'"
246+ VALIDATION_FAILED=true
247+ else
248+ echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format"
249+ fi
250+ fi
251+
252+ # Validate existing_webapp_url (must start with https)
253+ if [[ -n "$INPUT_EXISTING_WEBAPP_URL" ]]; then
254+ if [[ ! "$INPUT_EXISTING_WEBAPP_URL" =~ ^https:// ]]; then
255+ echo "❌ ERROR: existing_webapp_url must start with 'https://', got: '$INPUT_EXISTING_WEBAPP_URL'"
256+ VALIDATION_FAILED=true
257+ else
258+ echo "✅ existing_webapp_url: '$INPUT_EXISTING_WEBAPP_URL' is valid"
259+ fi
260+ fi
261+
262+ # Validate docker_image_tag (Docker tag pattern)
263+ if [[ -n "$INPUT_DOCKER_IMAGE_TAG" ]]; then
264+ # Docker tags: lowercase and uppercase letters, digits, underscores, periods, and hyphens
265+ # Cannot start with period or hyphen, max 128 characters
266+ if [[ ! "$INPUT_DOCKER_IMAGE_TAG" =~ ^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$ ]]; then
267+ echo "❌ ERROR: docker_image_tag '$INPUT_DOCKER_IMAGE_TAG' is invalid. Must:"
268+ echo " - Start with alphanumeric or underscore"
269+ echo " - Contain only alphanumerics, underscores, periods, hyphens"
270+ echo " - Be max 128 characters"
271+ VALIDATION_FAILED=true
272+ else
273+ echo "✅ docker_image_tag: '$INPUT_DOCKER_IMAGE_TAG' is valid"
274+ fi
275+ fi
276+
277+ # Fail workflow if any validation failed
278+ if [[ "$VALIDATION_FAILED" == "true" ]]; then
279+ echo ""
280+ echo "❌ Parameter validation failed. Please correct the errors above and try again."
281+ exit 1
282+ fi
283+
284+ echo ""
285+ echo "✅ All input parameters validated successfully!"
286+
119287 - name : Validate and Auto-Configure EXP
120288 shell : bash
289+ env :
290+ INPUT_EXP : ${{ inputs.exp }}
291+ INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID : ${{ inputs.azure_env_log_anlytics_workspace_id }}
292+ INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID : ${{ inputs.azure_existing_ai_project_resource_id }}
121293 run : |
122294 echo "🔍 Validating EXP configuration..."
123295
124- if [[ "${{ inputs.exp }} " != "true" ]]; then
125- if [[ -n "${{ inputs.azure_env_log_anlytics_workspace_id }} " ]] || [[ -n "${{ inputs.azure_existing_ai_project_resource_id }} " ]]; then
296+ if [[ "$INPUT_EXP " != "true" ]]; then
297+ if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID " ]] || [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID " ]]; then
126298 echo "🔧 AUTO-ENABLING EXP: EXP parameter values were provided but EXP was not explicitly enabled."
127299 echo ""
128300 echo "You provided values for:"
129- [[ -n "${{ inputs.azure_env_log_anlytics_workspace_id }} " ]] && echo " - Azure Log Analytics Workspace ID: '${{ inputs.azure_env_log_anlytics_workspace_id }} '"
130- [[ -n "${{ inputs.azure_existing_ai_project_resource_id }} " ]] && echo " - Azure AI Project Resource ID: '${{ inputs.azure_existing_ai_project_resource_id }} '"
301+ [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID " ]] && echo " - Azure Log Analytics Workspace ID: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID '"
302+ [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID " ]] && echo " - Azure AI Project Resource ID: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID '"
131303 echo ""
132304 echo "✅ Automatically enabling EXP to use these values."
133305 echo "EXP=true" >> $GITHUB_ENV
@@ -180,13 +352,16 @@ jobs:
180352 - name : Set Deployment Region
181353 id : set_region
182354 shell : bash
355+ env :
356+ INPUT_TRIGGER_TYPE : ${{ inputs.trigger_type }}
357+ INPUT_AZURE_LOCATION : ${{ inputs.azure_location }}
183358 run : |
184359 echo "Selected Region from Quota Check: $VALID_REGION"
185360 echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_ENV
186361 echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT
187362
188- if [[ "${{ inputs.trigger_type }} " == "workflow_dispatch" && -n "${{ inputs.azure_location }} " ]]; then
189- USER_SELECTED_LOCATION="${{ inputs.azure_location }} "
363+ if [[ "$INPUT_TRIGGER_TYPE " == "workflow_dispatch" && -n "$INPUT_AZURE_LOCATION " ]]; then
364+ USER_SELECTED_LOCATION="$INPUT_AZURE_LOCATION "
190365 echo "Using user-selected Azure location: $USER_SELECTED_LOCATION"
191366 echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_ENV
192367 echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_OUTPUT
@@ -199,11 +374,13 @@ jobs:
199374 - name : Generate Resource Group Name
200375 id : generate_rg_name
201376 shell : bash
377+ env :
378+ INPUT_RESOURCE_GROUP_NAME : ${{ inputs.resource_group_name }}
202379 run : |
203380 # Check if a resource group name was provided as input
204- if [[ -n "${{ inputs.resource_group_name }} " ]]; then
205- echo "Using provided Resource Group name: ${{ inputs.resource_group_name }} "
206- echo "RESOURCE_GROUP_NAME=${{ inputs.resource_group_name }} " >> $GITHUB_ENV
381+ if [[ -n "$INPUT_RESOURCE_GROUP_NAME " ]]; then
382+ echo "Using provided Resource Group name: $INPUT_RESOURCE_GROUP_NAME "
383+ echo "RESOURCE_GROUP_NAME=$INPUT_RESOURCE_GROUP_NAME " >> $GITHUB_ENV
207384 else
208385 echo "Generating a unique resource group name..."
209386 ACCL_NAME="kmgeneric" # Account name as specified
@@ -245,10 +422,12 @@ jobs:
245422 - name : Determine Docker Image Tag
246423 id : determine_image_tag
247424 shell : bash
425+ env :
426+ INPUT_DOCKER_IMAGE_TAG : ${{ inputs.docker_image_tag }}
248427 run : |
249428 if [[ "${{ env.BUILD_DOCKER_IMAGE }}" == "true" ]]; then
250- if [[ -n "${{ inputs.docker_image_tag }} " ]]; then
251- IMAGE_TAG="${{ inputs.docker_image_tag }} "
429+ if [[ -n "$INPUT_DOCKER_IMAGE_TAG " ]]; then
430+ IMAGE_TAG="$INPUT_DOCKER_IMAGE_TAG "
252431 echo "🔗 Using Docker image tag from build job: $IMAGE_TAG"
253432 else
254433 echo "❌ Docker build job failed or was skipped, but BUILD_DOCKER_IMAGE is true"
@@ -297,33 +476,42 @@ jobs:
297476
298477 - name : Display Workflow Configuration to GitHub Summary
299478 shell : bash
479+ env :
480+ INPUT_TRIGGER_TYPE : ${{ inputs.trigger_type }}
481+ INPUT_RUNNER_OS : ${{ inputs.runner_os }}
482+ INPUT_AZURE_LOCATION : ${{ inputs.azure_location }}
483+ INPUT_RESOURCE_GROUP_NAME : ${{ inputs.resource_group_name }}
484+ WAF_ENABLED_DISPLAY : ${{ env.WAF_ENABLED == 'true' && '✅ Yes' || '❌ No' }}
485+ EXP_DISPLAY : ${{ env.EXP == 'true' && '✅ Yes' || '❌ No' }}
486+ CLEANUP_DISPLAY : ${{ env.CLEANUP_RESOURCES == 'true' && '✅ Yes' || '❌ No' }}
487+ BUILD_DOCKER_DISPLAY : ${{ env.BUILD_DOCKER_IMAGE == 'true' && '✅ Yes' || '❌ No' }}
300488 run : |
301489 echo "## 📋 Workflow Configuration Summary" >> $GITHUB_STEP_SUMMARY
302490 echo "" >> $GITHUB_STEP_SUMMARY
303491 echo "| Configuration | Value |" >> $GITHUB_STEP_SUMMARY
304492 echo "|---------------|-------|" >> $GITHUB_STEP_SUMMARY
305493 echo "| **Trigger Type** | \`${{ github.event_name }}\` |" >> $GITHUB_STEP_SUMMARY
306494 echo "| **Branch** | \`${{ env.BRANCH_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
307- echo "| **Runner OS** | \`${{ inputs.runner_os }} \` |" >> $GITHUB_STEP_SUMMARY
308- echo "| **WAF Enabled** | ${{ env.WAF_ENABLED == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY
309- echo "| **EXP Enabled** | ${{ env.EXP == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY
495+ echo "| **Runner OS** | \`$INPUT_RUNNER_OS \` |" >> $GITHUB_STEP_SUMMARY
496+ echo "| **WAF Enabled** | $WAF_ENABLED_DISPLAY |" >> $GITHUB_STEP_SUMMARY
497+ echo "| **EXP Enabled** | $EXP_DISPLAY |" >> $GITHUB_STEP_SUMMARY
310498 echo "| **Run E2E Tests** | \`${{ env.RUN_E2E_TESTS }}\` |" >> $GITHUB_STEP_SUMMARY
311- echo "| **Cleanup Resources** | ${{ env.CLEANUP_RESOURCES == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY
312- echo "| **Build Docker Image** | ${{ env.BUILD_DOCKER_IMAGE == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY
499+ echo "| **Cleanup Resources** | $CLEANUP_DISPLAY |" >> $GITHUB_STEP_SUMMARY
500+ echo "| **Build Docker Image** | $BUILD_DOCKER_DISPLAY |" >> $GITHUB_STEP_SUMMARY
313501
314- if [[ "${{ inputs.trigger_type }} " == "workflow_dispatch" && -n "${{ inputs.azure_location }} " ]]; then
315- echo "| **Azure Location** | \`${{ inputs.azure_location }} \` (User Selected) |" >> $GITHUB_STEP_SUMMARY
502+ if [[ "$INPUT_TRIGGER_TYPE " == "workflow_dispatch" && -n "$INPUT_AZURE_LOCATION " ]]; then
503+ echo "| **Azure Location** | \`$INPUT_AZURE_LOCATION \` (User Selected) |" >> $GITHUB_STEP_SUMMARY
316504 fi
317505
318- if [[ -n "${{ inputs.resource_group_name }} " ]]; then
319- echo "| **Resource Group** | \`${{ inputs.resource_group_name }} \` (Pre-specified) |" >> $GITHUB_STEP_SUMMARY
506+ if [[ -n "$INPUT_RESOURCE_GROUP_NAME " ]]; then
507+ echo "| **Resource Group** | \`$INPUT_RESOURCE_GROUP_NAME \` (Pre-specified) |" >> $GITHUB_STEP_SUMMARY
320508 else
321509 echo "| **Resource Group** | \`${{ env.RESOURCE_GROUP_NAME }}\` (Auto-generated) |" >> $GITHUB_STEP_SUMMARY
322510 fi
323511
324512 echo "" >> $GITHUB_STEP_SUMMARY
325513
326- if [[ "${{ inputs.trigger_type }} " != "workflow_dispatch" ]]; then
514+ if [[ "$INPUT_TRIGGER_TYPE " != "workflow_dispatch" ]]; then
327515 echo "ℹ️ **Note:** Automatic Trigger - Using Non-WAF + Non-EXP configuration" >> $GITHUB_STEP_SUMMARY
328516 else
329517 echo "ℹ️ **Note:** Manual Trigger - Using user-specified configuration" >> $GITHUB_STEP_SUMMARY
0 commit comments