Skip to content

Commit 9f0b9f0

Browse files
Merge pull request #107 from microsoft/main
chore: Down merging to dev
2 parents 0adf997 + 3d94d62 commit 9f0b9f0

21 files changed

Lines changed: 2545 additions & 27 deletions

.azuredevops/azure-pipeline-infrastructure.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ parameters:
2929
- name: tags
3030
displayName: Resource Tags
3131
type: object
32-
default:
33-
SecurityControl: 'Ignore'
32+
default: {}
3433
- name: enableMonitoring
3534
displayName: Enable Monitoring
3635
type: boolean

.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.12-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": "DevContainer for Container Migration Solution Accelerator",
3-
"image": "mcr.microsoft.com/devcontainers/python:3.12-bullseye",
3+
"build": {
4+
"dockerfile": "Dockerfile"
5+
},
46
"features": {
57
"ghcr.io/dhoeric/features/hadolint:1": {},
68
"ghcr.io/jsburckhardt/devcontainer-features/uv:1": {},

.github/workflows/azure-dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v4
1717

18-
- uses: microsoft/template-validation-action@Latest
18+
- uses: microsoft/template-validation-action@v0.4.3
1919
with:
2020
validateAzd: ${{ vars.AZD_VALIDATE }}
2121
useDevContainer: ${{ vars.AZD_USE_DEV_CONTAINER }}

.github/workflows/ci.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
name: Validate Deployment
2+
3+
permissions:
4+
contents: read
5+
actions: read
6+
27
on:
38
push:
49
branches:
@@ -35,21 +40,20 @@ jobs:
3540
steps:
3641
- name: Checkout Code
3742
uses: actions/checkout@v4
38-
- name: Setup Azure CLI
39-
run: |
40-
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
41-
az --version
43+
4244
- name: Login to Azure
4345
run: |
4446
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
4547
- name: Run Quota Check
4648
id: quota-check
49+
env:
50+
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
51+
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
52+
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
53+
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
54+
AZURE_REGIONS: ${{ vars.AZURE_REGIONS }}
55+
GPT_MIN_CAPACITY: ${{ env.GPT_MIN_CAPACITY }}
4756
run: |
48-
export AZURE_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}
49-
export AZURE_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}
50-
export AZURE_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
51-
export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
52-
export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
5357
chmod +x scripts/checkquota.sh
5458
if ! scripts/checkquota.sh; then
5559
# If quota check fails due to insufficient quota, set the flag
@@ -168,10 +172,6 @@ jobs:
168172
env:
169173
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
170174
steps:
171-
- name: Setup Azure CLI
172-
run: |
173-
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
174-
az --version
175175
- name: Login to Azure
176176
run: |
177177
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}

.github/workflows/deploy-linux.yml

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
name: Deploy-Test-Cleanup (v2) Linux
2+
3+
permissions:
4+
contents: read
5+
actions: read
6+
7+
on:
8+
push:
9+
branches:
10+
- main
11+
- dev
12+
- demo
13+
pull_request:
14+
branches:
15+
- dev
16+
schedule:
17+
- cron: '0 9,21 * * *' # Runs at 9:00 AM and 9:00 PM GMT
18+
workflow_dispatch:
19+
inputs:
20+
azure_location:
21+
description: 'Azure Location For Deployment'
22+
required: false
23+
default: 'australiaeast'
24+
type: choice
25+
options:
26+
- 'australiaeast'
27+
- 'centralus'
28+
- 'eastasia'
29+
- 'eastus2'
30+
- 'japaneast'
31+
- 'northeurope'
32+
- 'southeastasia'
33+
- 'uksouth'
34+
resource_group_name:
35+
description: 'Resource Group Name (Optional)'
36+
required: false
37+
default: ''
38+
type: string
39+
40+
waf_enabled:
41+
description: 'Enable WAF'
42+
required: false
43+
default: false
44+
type: boolean
45+
EXP:
46+
description: 'Enable EXP'
47+
required: false
48+
default: false
49+
type: boolean
50+
build_docker_image:
51+
description: 'Build And Push Docker Image (Optional)'
52+
required: false
53+
default: false
54+
type: boolean
55+
56+
cleanup_resources:
57+
description: 'Cleanup Deployed Resources'
58+
required: false
59+
default: false
60+
type: boolean
61+
62+
AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
63+
description: 'Log Analytics Workspace ID (Optional)'
64+
required: false
65+
default: ''
66+
type: string
67+
AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
68+
description: 'AI Project Resource ID (Optional)'
69+
required: false
70+
default: ''
71+
type: string
72+
existing_webapp_url:
73+
description: 'Existing WebApp URL (Skips Deployment)'
74+
required: false
75+
default: ''
76+
type: string
77+
78+
jobs:
79+
validate-inputs:
80+
runs-on: ubuntu-latest
81+
outputs:
82+
validation_passed: ${{ steps.validate.outputs.passed }}
83+
azure_location: ${{ steps.validate.outputs.azure_location }}
84+
resource_group_name: ${{ steps.validate.outputs.resource_group_name }}
85+
waf_enabled: ${{ steps.validate.outputs.waf_enabled }}
86+
exp: ${{ steps.validate.outputs.exp }}
87+
build_docker_image: ${{ steps.validate.outputs.build_docker_image }}
88+
cleanup_resources: ${{ steps.validate.outputs.cleanup_resources }}
89+
azure_env_log_analytics_workspace_id: ${{ steps.validate.outputs.azure_env_log_analytics_workspace_id }}
90+
azure_existing_ai_project_resource_id: ${{ steps.validate.outputs.azure_existing_ai_project_resource_id }}
91+
existing_webapp_url: ${{ steps.validate.outputs.existing_webapp_url }}
92+
steps:
93+
- name: Validate Workflow Input Parameters
94+
id: validate
95+
shell: bash
96+
env:
97+
INPUT_AZURE_LOCATION: ${{ github.event.inputs.azure_location }}
98+
INPUT_RESOURCE_GROUP_NAME: ${{ github.event.inputs.resource_group_name }}
99+
INPUT_WAF_ENABLED: ${{ github.event.inputs.waf_enabled }}
100+
INPUT_EXP: ${{ github.event.inputs.EXP }}
101+
INPUT_BUILD_DOCKER_IMAGE: ${{ github.event.inputs.build_docker_image }}
102+
INPUT_CLEANUP_RESOURCES: ${{ github.event.inputs.cleanup_resources }}
103+
INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}
104+
INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}
105+
INPUT_EXISTING_WEBAPP_URL: ${{ github.event.inputs.existing_webapp_url }}
106+
run: |
107+
echo "🔍 Validating workflow input parameters..."
108+
VALIDATION_FAILED=false
109+
110+
# Validate azure_location (Azure region format)
111+
LOCATION="${INPUT_AZURE_LOCATION:-australiaeast}"
112+
113+
if [[ ! "$LOCATION" =~ ^[a-z0-9]+$ ]]; then
114+
echo "❌ ERROR: azure_location '$LOCATION' is invalid. Must contain only lowercase letters and numbers"
115+
VALIDATION_FAILED=true
116+
else
117+
echo "✅ azure_location: '$LOCATION' is valid"
118+
fi
119+
120+
# Validate resource_group_name (Azure naming convention, optional)
121+
if [[ -n "$INPUT_RESOURCE_GROUP_NAME" ]]; then
122+
if [[ ! "$INPUT_RESOURCE_GROUP_NAME" =~ ^[a-zA-Z0-9._\(\)-]+$ ]] || [[ "$INPUT_RESOURCE_GROUP_NAME" =~ \.$ ]]; then
123+
echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' is invalid. Must contain only alphanumerics, periods, underscores, hyphens, and parentheses. Cannot end with period."
124+
VALIDATION_FAILED=true
125+
elif [[ ${#INPUT_RESOURCE_GROUP_NAME} -gt 90 ]]; then
126+
echo "❌ ERROR: resource_group_name '$INPUT_RESOURCE_GROUP_NAME' exceeds 90 characters (length: ${#INPUT_RESOURCE_GROUP_NAME})"
127+
VALIDATION_FAILED=true
128+
else
129+
echo "✅ resource_group_name: '$INPUT_RESOURCE_GROUP_NAME' is valid"
130+
fi
131+
else
132+
echo "✅ resource_group_name: Not provided (will be auto-generated)"
133+
fi
134+
135+
# Validate waf_enabled (boolean)
136+
WAF_ENABLED="${INPUT_WAF_ENABLED:-false}"
137+
if [[ "$WAF_ENABLED" != "true" && "$WAF_ENABLED" != "false" ]]; then
138+
echo "❌ ERROR: waf_enabled must be 'true' or 'false', got: '$WAF_ENABLED'"
139+
VALIDATION_FAILED=true
140+
else
141+
echo "✅ waf_enabled: '$WAF_ENABLED' is valid"
142+
fi
143+
144+
# Validate EXP (boolean)
145+
EXP_ENABLED="${INPUT_EXP:-false}"
146+
if [[ "$EXP_ENABLED" != "true" && "$EXP_ENABLED" != "false" ]]; then
147+
echo "❌ ERROR: EXP must be 'true' or 'false', got: '$EXP_ENABLED'"
148+
VALIDATION_FAILED=true
149+
else
150+
echo "✅ EXP: '$EXP_ENABLED' is valid"
151+
fi
152+
153+
# Validate build_docker_image (boolean)
154+
BUILD_DOCKER="${INPUT_BUILD_DOCKER_IMAGE:-false}"
155+
if [[ "$BUILD_DOCKER" != "true" && "$BUILD_DOCKER" != "false" ]]; then
156+
echo "❌ ERROR: build_docker_image must be 'true' or 'false', got: '$BUILD_DOCKER'"
157+
VALIDATION_FAILED=true
158+
else
159+
echo "✅ build_docker_image: '$BUILD_DOCKER' is valid"
160+
fi
161+
162+
# Validate cleanup_resources (boolean)
163+
CLEANUP_RESOURCES="${INPUT_CLEANUP_RESOURCES:-false}"
164+
if [[ "$CLEANUP_RESOURCES" != "true" && "$CLEANUP_RESOURCES" != "false" ]]; then
165+
echo "❌ ERROR: cleanup_resources must be 'true' or 'false', got: '$CLEANUP_RESOURCES'"
166+
VALIDATION_FAILED=true
167+
else
168+
echo "✅ cleanup_resources: '$CLEANUP_RESOURCES' is valid"
169+
fi
170+
171+
# Validate AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID (optional, Azure Resource ID format)
172+
if [[ -n "$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" ]]; then
173+
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
174+
echo "❌ ERROR: AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID is invalid. Must be a valid Azure Resource ID format:"
175+
echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}"
176+
echo " Got: '$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID'"
177+
VALIDATION_FAILED=true
178+
else
179+
echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Valid Resource ID format"
180+
fi
181+
else
182+
echo "✅ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: Not provided (optional)"
183+
fi
184+
185+
# Validate AZURE_EXISTING_AI_PROJECT_RESOURCE_ID (optional, Azure Resource ID format)
186+
if [[ -n "$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" ]]; then
187+
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
188+
echo "❌ ERROR: AZURE_EXISTING_AI_PROJECT_RESOURCE_ID is invalid. Must be a valid Azure Resource ID format:"
189+
echo " /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.CognitiveServices/accounts/{accountName}/projects/{projectName}"
190+
echo " Got: '$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID'"
191+
VALIDATION_FAILED=true
192+
else
193+
echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Valid Resource ID format"
194+
fi
195+
else
196+
echo "✅ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: Not provided (optional)"
197+
fi
198+
199+
# Validate existing_webapp_url (optional, must start with https)
200+
if [[ -n "$INPUT_EXISTING_WEBAPP_URL" ]]; then
201+
if [[ ! "$INPUT_EXISTING_WEBAPP_URL" =~ ^https:// ]]; then
202+
echo "❌ ERROR: existing_webapp_url must start with 'https://', got: '$INPUT_EXISTING_WEBAPP_URL'"
203+
VALIDATION_FAILED=true
204+
else
205+
echo "✅ existing_webapp_url: '$INPUT_EXISTING_WEBAPP_URL' is valid"
206+
fi
207+
else
208+
echo "✅ existing_webapp_url: Not provided (will perform deployment)"
209+
fi
210+
211+
# Fail workflow if any validation failed
212+
if [[ "$VALIDATION_FAILED" == "true" ]]; then
213+
echo ""
214+
echo "❌ Parameter validation failed. Please correct the errors above and try again."
215+
exit 1
216+
fi
217+
218+
echo ""
219+
echo "✅ All input parameters validated successfully!"
220+
221+
# Output validated values
222+
echo "passed=true" >> $GITHUB_OUTPUT
223+
echo "azure_location=$LOCATION" >> $GITHUB_OUTPUT
224+
echo "resource_group_name=$INPUT_RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT
225+
echo "waf_enabled=$WAF_ENABLED" >> $GITHUB_OUTPUT
226+
echo "exp=$EXP_ENABLED" >> $GITHUB_OUTPUT
227+
echo "build_docker_image=$BUILD_DOCKER" >> $GITHUB_OUTPUT
228+
echo "cleanup_resources=$CLEANUP_RESOURCES" >> $GITHUB_OUTPUT
229+
echo "azure_env_log_analytics_workspace_id=$INPUT_AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID" >> $GITHUB_OUTPUT
230+
echo "azure_existing_ai_project_resource_id=$INPUT_AZURE_EXISTING_AI_PROJECT_RESOURCE_ID" >> $GITHUB_OUTPUT
231+
echo "existing_webapp_url=$INPUT_EXISTING_WEBAPP_URL" >> $GITHUB_OUTPUT
232+
233+
Run:
234+
needs: validate-inputs
235+
if: needs.validate-inputs.outputs.validation_passed == 'true'
236+
uses: ./.github/workflows/deploy-orchestrator.yml
237+
with:
238+
runner_os: ubuntu-latest
239+
azure_location: ${{ needs.validate-inputs.outputs.azure_location || 'australiaeast' }}
240+
resource_group_name: ${{ needs.validate-inputs.outputs.resource_group_name || '' }}
241+
waf_enabled: ${{ needs.validate-inputs.outputs.waf_enabled == 'true' }}
242+
EXP: ${{ needs.validate-inputs.outputs.exp == 'true' }}
243+
build_docker_image: ${{ needs.validate-inputs.outputs.build_docker_image == 'true' }}
244+
cleanup_resources: ${{ needs.validate-inputs.outputs.cleanup_resources == 'true' }}
245+
AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ needs.validate-inputs.outputs.azure_env_log_analytics_workspace_id || '' }}
246+
AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ needs.validate-inputs.outputs.azure_existing_ai_project_resource_id || '' }}
247+
existing_webapp_url: ${{ needs.validate-inputs.outputs.existing_webapp_url || '' }}
248+
trigger_type: ${{ github.event_name }}
249+
secrets: inherit

0 commit comments

Comments
 (0)