Skip to content

Commit d8a4ef7

Browse files
Merge pull request #786 from microsoft/main
chore: Down merging to dev
2 parents 6710b90 + 092af3a commit d8a4ef7

18 files changed

Lines changed: 49320 additions & 206 deletions

.devcontainer/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM mcr.microsoft.com/devcontainers/python:3.11-bullseye
2+
3+
# Remove Yarn repository to avoid GPG key expiration issue
4+
RUN rm -f /etc/apt/sources.list.d/yarn.list

.devcontainer/devcontainer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"name": "Multi Agent Custom Automation Engine Solution Accelerator",
3-
"image": "mcr.microsoft.com/devcontainers/python:3.11-bullseye",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
},
46
"features": {
57
"ghcr.io/devcontainers/features/docker-in-docker:2": {"version": "latest"},
68
"ghcr.io/azure/azure-dev/azd:latest": {},

.github/workflows/azure-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
uses: actions/checkout@v4
1919
# Step 2: Validate the Azure template using microsoft/template-validation-action
2020
- name: Validate Azure Template
21-
uses: microsoft/template-validation-action@Latest
21+
uses: microsoft/template-validation-action@bae4895d0a8abd4f0d5aad68ae8647b3027f4c91
2222
with:
2323
validateAzd: true
2424
useDevContainer: false

.github/workflows/deploy-linux.yml

Lines changed: 182 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
name: Deploy-Test-Cleanup (v2) Linux
2+
3+
permissions:
4+
contents: read
5+
actions: read
26
on:
37
workflow_run:
48
workflows: ["Build Docker and Optional Push v4"]
@@ -82,19 +86,187 @@ on:
8286
- cron: "0 11,23 * * *" # Runs at 11:00 AM and 11:00 PM GMT
8387

8488
jobs:
89+
validate-inputs:
90+
runs-on: ubuntu-latest
91+
outputs:
92+
validation_passed: ${{ steps.validate.outputs.passed }}
93+
azure_location: ${{ steps.validate.outputs.azure_location }}
94+
resource_group_name: ${{ steps.validate.outputs.resource_group_name }}
95+
waf_enabled: ${{ steps.validate.outputs.waf_enabled }}
96+
exp: ${{ steps.validate.outputs.exp }}
97+
build_docker_image: ${{ steps.validate.outputs.build_docker_image }}
98+
cleanup_resources: ${{ steps.validate.outputs.cleanup_resources }}
99+
run_e2e_tests: ${{ steps.validate.outputs.run_e2e_tests }}
100+
azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }}
101+
azure_existing_ai_project_resource_id: ${{ steps.validate.outputs.azure_existing_ai_project_resource_id }}
102+
existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }}
103+
steps:
104+
- name: Validate Workflow Input Parameters
105+
id: validate
106+
shell: bash
107+
env:
108+
INPUT_AZURE_LOCATION: ${{ github.event.inputs.azure_location }}
109+
INPUT_RESOURCE_GROUP_NAME: ${{ github.event.inputs.resource_group_name }}
110+
INPUT_WAF_ENABLED: ${{ github.event.inputs.waf_enabled }}
111+
INPUT_EXP: ${{ github.event.inputs.EXP }}
112+
INPUT_BUILD_DOCKER_IMAGE: ${{ github.event.inputs.build_docker_image }}
113+
INPUT_CLEANUP_RESOURCES: ${{ github.event.inputs.cleanup_resources }}
114+
INPUT_RUN_E2E_TESTS: ${{ github.event.inputs.run_e2e_tests }}
115+
INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}
116+
INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}
117+
INPUT_EXISTING_WEBAPP_URL: ${{ github.event.inputs.existing_webapp_url }}
118+
run: |
119+
echo "🔍 Validating workflow input parameters..."
120+
VALIDATION_FAILED=false
121+
122+
# Validate azure_location (Azure region format)
123+
LOCATION="${INPUT_AZURE_LOCATION:-australiaeast}"
124+
125+
if [[ ! "$LOCATION" =~ ^[a-z0-9]+$ ]]; then
126+
echo "❌ ERROR: azure_location '$LOCATION' is invalid. Must contain only lowercase letters and numbers"
127+
VALIDATION_FAILED=true
128+
else
129+
echo "✅ azure_location: '$LOCATION' is valid"
130+
fi
131+
132+
# Validate resource_group_name (Azure naming convention, optional)
133+
if [[ -n "$INPUT_RESOURCE_GROUP_NAME" ]]; then
134+
if [[ ! "$INPUT_RESOURCE_GROUP_NAME" =~ ^[a-zA-Z0-9._\(\)-]+$ ]] || [[ "$INPUT_RESOURCE_GROUP_NAME" =~ \.$ ]]; then
135+
echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' is invalid. Must contain only alphanumerics, periods, underscores, hyphens, and parentheses. Cannot end with period."
136+
VALIDATION_FAILED=true
137+
elif [[ ${#INPUT_RESOURCE_GROUP_NAME} -gt 90 ]]; then
138+
echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' exceeds 90 characters (length: ${#INPUT_RESOURCE_GROUP_NAME})"
139+
VALIDATION_FAILED=true
140+
else
141+
echo "✅ resource_group_name: '$INPUT_RESOURCE_GROUP_NAME' is valid"
142+
fi
143+
else
144+
echo "✅ resource_group_name: Not provided (will be auto-generated)"
145+
fi
146+
147+
# Validate waf_enabled (boolean)
148+
WAF_ENABLED="${INPUT_WAF_ENABLED:-false}"
149+
if [[ "$WAF_ENABLED" != "true" && "$WAF_ENABLED" != "false" ]]; then
150+
echo "❌ ERROR: waf_enabled must be 'true' or 'false', got: '$WAF_ENABLED'"
151+
VALIDATION_FAILED=true
152+
else
153+
echo "✅ waf_enabled: '$WAF_ENABLED' is valid"
154+
fi
155+
156+
# Validate EXP (boolean)
157+
EXP_ENABLED="${INPUT_EXP:-false}"
158+
if [[ "$EXP_ENABLED" != "true" && "$EXP_ENABLED" != "false" ]]; then
159+
echo "❌ ERROR: EXP must be 'true' or 'false', got: '$EXP_ENABLED'"
160+
VALIDATION_FAILED=true
161+
else
162+
echo "✅ EXP: '$EXP_ENABLED' is valid"
163+
fi
164+
165+
# Validate build_docker_image (boolean)
166+
BUILD_DOCKER="${INPUT_BUILD_DOCKER_IMAGE:-false}"
167+
if [[ "$BUILD_DOCKER" != "true" && "$BUILD_DOCKER" != "false" ]]; then
168+
echo "❌ ERROR: build_docker_image must be 'true' or 'false', got: '$BUILD_DOCKER'"
169+
VALIDATION_FAILED=true
170+
else
171+
echo "✅ build_docker_image: '$BUILD_DOCKER' is valid"
172+
fi
173+
174+
# Validate cleanup_resources (boolean)
175+
CLEANUP_RESOURCES="${INPUT_CLEANUP_RESOURCES:-false}"
176+
if [[ "$CLEANUP_RESOURCES" != "true" && "$CLEANUP_RESOURCES" != "false" ]]; then
177+
echo "❌ ERROR: cleanup_resources must be 'true' or 'false', got: '$CLEANUP_RESOURCES'"
178+
VALIDATION_FAILED=true
179+
else
180+
echo "✅ cleanup_resources: '$CLEANUP_RESOURCES' is valid"
181+
fi
182+
183+
# Validate run_e2e_tests (specific allowed values)
184+
TEST_OPTION="${INPUT_RUN_E2E_TESTS:-GoldenPath-Testing}"
185+
if [[ "$TEST_OPTION" != "GoldenPath-Testing" && "$TEST_OPTION" != "Smoke-Testing" && "$TEST_OPTION" != "None" ]]; then
186+
echo "❌ ERROR: run_e2e_tests must be one of: GoldenPath-Testing, Smoke-Testing, None, got: '$TEST_OPTION'"
187+
VALIDATION_FAILED=true
188+
else
189+
echo "✅ run_e2e_tests: '$TEST_OPTION' is valid"
190+
fi
191+
192+
# Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, Azure Resource ID format)
193+
if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then
194+
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
195+
echo "❌ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:"
196+
echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}"
197+
echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'"
198+
VALIDATION_FAILED=true
199+
else
200+
echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format"
201+
fi
202+
else
203+
echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Not provided (optional)"
204+
fi
205+
206+
# Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, Azure Resource ID format)
207+
if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then
208+
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
209+
echo "❌ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:"
210+
echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}"
211+
echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'"
212+
VALIDATION_FAILED=true
213+
else
214+
echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format"
215+
fi
216+
else
217+
echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Not provided (optional)"
218+
fi
219+
220+
# Validate existing_webapp_url (optional, must start with https)
221+
if [[ -n "$INPUT_EXISTING_WEBAPP_URL" ]]; then
222+
if [[ ! "$INPUT_EXISTING_WEBAPP_URL" =~ ^https:// ]]; then
223+
echo "❌ ERROR: existing_webapp_url must start with 'https://', got: '$INPUT_EXISTING_WEBAPP_URL'"
224+
VALIDATION_FAILED=true
225+
else
226+
echo "✅ existing_webapp_url: '$INPUT_EXISTING_WEBAPP_URL' is valid"
227+
fi
228+
else
229+
echo "✅ existing_webapp_url: Not provided (will perform deployment)"
230+
fi
231+
232+
# Fail workflow if any validation failed
233+
if [[ "$VALIDATION_FAILED" == "true" ]]; then
234+
echo ""
235+
echo "❌ Parameter validation failed. Please correct the errors above and try again."
236+
exit 1
237+
fi
238+
239+
echo ""
240+
echo "✅ All input parameters validated successfully!"
241+
242+
# Output validated values
243+
echo "passed=true" >> $GITHUB_OUTPUT
244+
echo "azure_location=$LOCATION" >> $GITHUB_OUTPUT
245+
echo "resource_group_name=$INPUT_RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT
246+
echo "waf_enabled=$WAF_ENABLED" >> $GITHUB_OUTPUT
247+
echo "exp=$EXP_ENABLED" >> $GITHUB_OUTPUT
248+
echo "build_docker_image=$BUILD_DOCKER" >> $GITHUB_OUTPUT
249+
echo "cleanup_resources=$CLEANUP_RESOURCES" >> $GITHUB_OUTPUT
250+
echo "run_e2e_tests=$TEST_OPTION" >> $GITHUB_OUTPUT
251+
echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" >> $GITHUB_OUTPUT
252+
echo "azure_existing_ai_project_resource_id=$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" >> $GITHUB_OUTPUT
253+
echo "existing_webapp_url=$INPUT_EXISTING_WEBAPP_URL" >> $GITHUB_OUTPUT
254+
85255
Run:
256+
needs: validate-inputs
257+
if: needs.validate-inputs.outputs.validation_passed == 'true'
86258
uses: ./.github/workflows/deploy-orchestrator.yml
87259
with:
88260
runner_os: ubuntu-latest
89-
azure_location: ${{ github.event.inputs.azure_location || 'australiaeast' }}
90-
resource_group_name: ${{ github.event.inputs.resource_group_name || '' }}
91-
waf_enabled: ${{ github.event.inputs.waf_enabled == 'true' }}
92-
EXP: ${{ github.event.inputs.EXP == 'true' }}
93-
build_docker_image: ${{ github.event.inputs.build_docker_image == 'true' }}
94-
cleanup_resources: ${{ github.event.inputs.cleanup_resources == 'true' }}
95-
run_e2e_tests: ${{ github.event.inputs.run_e2e_tests || 'GoldenPath-Testing' }}
96-
AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID || '' }}
97-
AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID || '' }}
98-
existing_webapp_url: ${{ github.event.inputs.existing_webapp_url || '' }}
261+
azure_location: ${{ needs.validate-inputs.outputs.azure_location || 'australiaeast' }}
262+
resource_group_name: ${{ needs.validate-inputs.outputs.resource_group_name || '' }}
263+
waf_enabled: ${{ needs.validate-inputs.outputs.waf_enabled == 'true' }}
264+
EXP: ${{ needs.validate-inputs.outputs.exp == 'true' }}
265+
build_docker_image: ${{ needs.validate-inputs.outputs.build_docker_image == 'true' }}
266+
cleanup_resources: ${{ needs.validate-inputs.outputs.cleanup_resources == 'true' }}
267+
run_e2e_tests: ${{ needs.validate-inputs.outputs.run_e2e_tests || 'GoldenPath-Testing' }}
268+
AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }}
269+
AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ needs.validate-inputs.outputs.azure_existing_ai_project_resource_id || '' }}
270+
existing_webapp_url: ${{ needs.validate-inputs.outputs.existing_webapp_url || '' }}
99271
trigger_type: ${{ github.event_name }}
100272
secrets: inherit

.github/workflows/deploy-orchestrator.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: Deployment orchestrator
22

3+
permissions:
4+
contents: read
5+
actions: read
6+
37
on:
48
workflow_call:
59
inputs:
@@ -74,7 +78,7 @@ jobs:
7478
secrets: inherit
7579

7680
deploy:
77-
if: "!cancelled() && (inputs.trigger_type != 'workflow_dispatch' || inputs.existing_webapp_url == '' || inputs.existing_webapp_url == null)"
81+
if: "!cancelled() && (needs.docker-build.result == 'success' || needs.docker-build.result == 'skipped') && (inputs.trigger_type != 'workflow_dispatch' || inputs.existing_webapp_url == '' || inputs.existing_webapp_url == null)"
7882
needs: docker-build
7983
uses: ./.github/workflows/job-deploy.yml
8084
with:

.github/workflows/deploy-waf.yml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: Validate WAF Deployment v4
22

3+
permissions:
4+
contents: read
5+
actions: read
36
on:
47
push:
58
branches:
@@ -20,16 +23,16 @@ jobs:
2023

2124
- name: Run Quota Check
2225
id: quota-check
26+
env:
27+
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
28+
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
29+
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
30+
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
31+
GPT_MIN_CAPACITY: ${{ env.GPT_MIN_CAPACITY }}
32+
O4_MINI_MIN_CAPACITY: ${{ env.O4_MINI_MIN_CAPACITY }}
33+
GPT41_MINI_MIN_CAPACITY: ${{ env.GPT41_MINI_MIN_CAPACITY }}
34+
AZURE_REGIONS: ${{ vars.AZURE_REGIONS }}
2335
run: |
24-
export AZURE_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}
25-
export AZURE_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}
26-
export AZURE_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
27-
export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
28-
export GPT_MIN_CAPACITY="1"
29-
export O4_MINI_MIN_CAPACITY="1"
30-
export GPT41_MINI_MIN_CAPACITY="1"
31-
export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
32-
3336
chmod +x infra/scripts/checkquota.sh
3437
if ! infra/scripts/checkquota.sh; then
3538
# If quota check fails due to insufficient quota, set the flag
@@ -63,11 +66,6 @@ jobs:
6366
echo "Selected Region: $VALID_REGION"
6467
echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_ENV
6568
66-
- name: Setup Azure CLI
67-
run: |
68-
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
69-
az --version # Verify installation
70-
7169
- name: Login to Azure
7270
run: |
7371
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}

0 commit comments

Comments
 (0)