Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions .github/workflows/test-automation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: Test Automation MACAE

on:
push:
branches:
- main
- dev
paths:
- 'tests/e2e-test/**'
schedule:
- cron: '0 13 * * *' # Runs at 1 PM UTC
workflow_dispatch:

env:
url: ${{ vars.MACAE_WEB_URL }}
api_url: ${{ vars.MACAE_API_URL }}
accelerator_name: "MACAE"

jobs:
test:

runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.13'

- name: Azure CLI Login
uses: azure/login@v2
with:
creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'

- name: Start Container App
id: start-container-app
uses: azure/cli@v2
with:
azcliversion: 'latest'
inlineScript: |
az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.MACAE_RG }}/providers/Microsoft.App/containerApps/${{ vars.MACAE_BACKEND_CONTAINER_NAME }}/start?api-version=2025-01-01"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r tests/e2e-test/requirements.txt

- name: Ensure browsers are installed
run: python -m playwright install --with-deps chromium

- name: Run tests(1)
id: test1
run: |
xvfb-run pytest --headed --html=report/report.html --self-contained-html
working-directory: tests/e2e-test
continue-on-error: true

- name: Sleep for 30 seconds
if: ${{ steps.test1.outcome == 'failure' }}
run: sleep 30s
shell: bash

- name: Run tests(2)
id: test2
if: ${{ steps.test1.outcome == 'failure' }}
run: |
xvfb-run pytest --headed --html=report/report.html --self-contained-html
working-directory: tests/e2e-test
continue-on-error: true

- name: Sleep for 60 seconds
if: ${{ steps.test2.outcome == 'failure' }}
run: sleep 60s
shell: bash

- name: Run tests(3)
id: test3
if: ${{ steps.test2.outcome == 'failure' }}
run: |
xvfb-run pytest --headed --html=report/report.html --self-contained-html
working-directory: tests/e2e-test

- name: Upload test report
id: upload_report
uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: test-report
path: tests/e2e-test/report/*

- name: Send Notification
if: always()
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
REPORT_URL=${{ steps.upload_report.outputs.artifact-url }}
IS_SUCCESS=${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }}
# Construct the email body
if [ "$IS_SUCCESS" = "true" ]; then
EMAIL_BODY=$(cat <<EOF
{
"body": "<p>Dear Team,</p><p>We would like to inform you that the ${{ env.accelerator_name }} Test Automation process has completed successfully.</p><p><strong>Run URL:</strong> <a href=\"${RUN_URL}\">${RUN_URL}</a><br></p><p><strong>Test Report:</strong> <a href=\"${REPORT_URL}\">${REPORT_URL}</a></p><p>Best regards,<br>Your Automation Team</p>",
"subject": "${{ env.accelerator_name }} Test Automation - Success"
}
EOF
)
else
EMAIL_BODY=$(cat <<EOF
{
"body": "<p>Dear Team,</p><p>We would like to inform you that the ${{ env.accelerator_name }} Test Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Run URL:</strong> <a href=\"${RUN_URL}\">${RUN_URL}</a><br> ${OUTPUT}</p><p><strong>Test Report:</strong> <a href=\"${REPORT_URL}\">${REPORT_URL}</a></p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>",
"subject": "${{ env.accelerator_name }} Test Automation - Failure"
}
EOF
)
fi

# Send the notification
curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
-H "Content-Type: application/json" \
-d "$EMAIL_BODY" || echo "Failed to send notification"

- name: Stop Container App
if: always()
uses: azure/cli@v2
with:
azcliversion: 'latest'
inlineScript: |
az rest -m post -u "/subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ vars.MACAE_RG }}/providers/Microsoft.App/containerApps/${{ vars.MACAE_BACKEND_CONTAINER_NAME }}/stop?api-version=2025-01-01"
az logout
18 changes: 17 additions & 1 deletion azure.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
name: multi-agent-custom-automation-engine-solution-accelerator
metadata:
template: [email protected]
template: [email protected]
hooks:
preprovision:
posix:
shell: sh
run: >
chmod u+r+x ./infra/scripts/validate_model_deployment_quota.sh; chmod u+r+x ./infra/scripts/validate_model_quota.sh; ./infra/scripts/validate_model_deployment_quota.sh --subscription "$AZURE_SUBSCRIPTION_ID" --location "${AZURE_ENV_OPENAI_LOCATION:-swedencentral}" --models-parameter "aiModelDeployments"
interactive: false
continueOnError: false

windows:
shell: pwsh
run: >
$location = if ($env:AZURE_ENV_OPENAI_LOCATION) { $env:AZURE_ENV_OPENAI_LOCATION } else { "swedencentral" };
./infra/scripts/validate_model_deployment_quotas.ps1 -SubscriptionId $env:AZURE_SUBSCRIPTION_ID -Location $location -ModelsParameter "aiModelDeployments"
interactive: false
continueOnError: false
75 changes: 75 additions & 0 deletions infra/main.parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"aiModelDeployments": {
"value": [
{
"name": "gpt",
"model": {
"name": "gpt-4o",
"version": "2024-08-06",
"format": "OpenAI"
},
"sku": {
"name": "GlobalStandard",
"capacity": 140
}
}
]
},
"environmentName": {
"value": "${AZURE_ENV_NAME}"
},
"location": {
"value": "${AZURE_LOCATION}"
},
"backendExists": {
"value": "${SERVICE_BACKEND_RESOURCE_EXISTS=false}"
},
"backendDefinition": {
"value": {
"settings": [
{
"name": "",
"value": "${VAR}",
"_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
"_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment."
},
{
"name": "",
"value": "${VAR_S}",
"secret": true,
"_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
"_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment."
}
]
}
},
"frontendExists": {
"value": "${SERVICE_FRONTEND_RESOURCE_EXISTS=false}"
},
"frontendDefinition": {
"value": {
"settings": [
{
"name": "",
"value": "${VAR}",
"_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
"_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment."
},
{
"name": "",
"value": "${VAR_S}",
"secret": true,
"_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.",
"_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment."
}
]
}
},
"principalId": {
"value": "${AZURE_PRINCIPAL_ID}"
}
}
}
2 changes: 1 addition & 1 deletion infra/scripts/quota_check_params.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ az account set --subscription "$AZURE_SUBSCRIPTION_ID"
echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)"

# Default Regions to check (Comma-separated, now configurable)
DEFAULT_REGIONS="eastus,uksouth,eastus2,northcentralus,swedencentral,westus,westus2,southcentralus,canadacentral"
DEFAULT_REGIONS="australiaeast,eastus2,francecentral,japaneast,norwayeast,swedencentral,uksouth,westus"
IFS=',' read -r -a DEFAULT_REGION_ARRAY <<< "$DEFAULT_REGIONS"

# Read parameters (if any)
Expand Down
88 changes: 88 additions & 0 deletions infra/scripts/validate_model_deployment_quota.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash

SUBSCRIPTION_ID=""
LOCATION=""
MODELS_PARAMETER=""

while [[ $# -gt 0 ]]; do
case "$1" in
--subscription)
SUBSCRIPTION_ID="$2"
shift 2
;;
--location)
LOCATION="$2"
shift 2
;;
--models-parameter)
MODELS_PARAMETER="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done

# Verify all required parameters are provided and echo missing ones
MISSING_PARAMS=()

if [[ -z "$SUBSCRIPTION_ID" ]]; then
MISSING_PARAMS+=("subscription")
fi

if [[ -z "$LOCATION" ]]; then
MISSING_PARAMS+=("location")
fi

if [[ -z "$MODELS_PARAMETER" ]]; then
MISSING_PARAMS+=("models-parameter")
fi

if [[ ${#MISSING_PARAMS[@]} -ne 0 ]]; then
echo "❌ ERROR: Missing required parameters: ${MISSING_PARAMS[*]}"
echo "Usage: $0 --subscription <SUBSCRIPTION_ID> --location <LOCATION> --models-parameter <MODELS_PARAMETER>"
exit 1
fi

aiModelDeployments=$(jq -c ".parameters.$MODELS_PARAMETER.value[]" ./infra/main.parameters.json)

if [ $? -ne 0 ]; then
echo "Error: Failed to parse main.parameters.json. Ensure jq is installed and the JSON file is valid."
exit 1
fi

az account set --subscription "$SUBSCRIPTION_ID"
echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)"

quotaAvailable=true

while IFS= read -r deployment; do
name=$(echo "$deployment" | jq -r '.name')
model=$(echo "$deployment" | jq -r '.model.name')
type=$(echo "$deployment" | jq -r '.sku.name')
capacity=$(echo "$deployment" | jq -r '.sku.capacity')

echo "🔍 Validating model deployment: $name ..."
./infra/scripts/validate_model_quota.sh --location "$LOCATION" --model "$model" --capacity $capacity --deployment-type $type

# Check if the script failed
exit_code=$?
if [ $exit_code -ne 0 ]; then
if [ $exit_code -eq 2 ]; then
# Skip printing any quota validation error — already handled inside the validation script
exit 1
fi
echo "❌ ERROR: Quota validation failed for model deployment: $name"
quotaAvailable=false
fi
done <<< "$(echo "$aiModelDeployments")"

if [ "$quotaAvailable" = false ]; then
echo "❌ ERROR: One or more model deployments failed validation."
exit 1
else
echo "✅ All model deployments passed quota validation successfully."
exit 0
fi
Loading
Loading