Skip to content

Commit 731122d

Browse files
Merge branch 'dev' of https://github.com/microsoft/document-generation-solution-accelerator into PSL-17061-AIFoundry-dev
2 parents 33578aa + b690929 commit 731122d

36 files changed

Lines changed: 869 additions & 41 deletions

.github/workflows/deploy.yml

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
1-
name: Validate Deployment
1+
name: DocGen Deploy-Test-Cleanup Pipeline
22

33
on:
4-
push:
4+
workflow_run:
5+
workflows: ["Build Docker and Optional Push"]
6+
types:
7+
- completed
58
branches:
69
- main
10+
- dev
11+
- demo
12+
713
schedule:
814
- cron: '0 9,21 * * *' # Runs at 9:00 AM and 9:00 PM GMT
915

1016
env:
11-
GPT_MIN_CAPACITY: 10
12-
TEXT_EMBEDDING_MIN_CAPACITY: 10
17+
GPT_MIN_CAPACITY: 250
18+
TEXT_EMBEDDING_MIN_CAPACITY: 40
19+
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
1320

1421
jobs:
1522
deploy:
1623
runs-on: ubuntu-latest
24+
outputs:
25+
RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
26+
WEBAPP_URL: ${{ steps.get_output.outputs.WEBAPP_URL }}
1727
steps:
1828
- name: Checkout Code
1929
uses: actions/checkout@v3
@@ -54,7 +64,7 @@ jobs:
5464
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
5565
EMAIL_BODY=$(cat <<EOF
5666
{
57-
"body": "<p>Dear Team,</p><p>The quota check has failed, and the pipeline cannot proceed.</p><p><strong>Build URL:</strong> ${RUN_URL}</p><p>Please take necessary action.</p><p>Best regards,<br>Your Automation Team</p>"
67+
"body": "<p>Dear Team,</p><p>The quota check has failed, and the pipeline cannot proceed.</p><p><strong>Build URL:</strong> <a href=\"${RUN_URL}\">${RUN_URL}</a></p><p>Please take necessary action.</p><p>Best regards,<br>Your Automation Team</p>"
5868
}
5969
EOF
6070
)
@@ -97,14 +107,15 @@ jobs:
97107
else
98108
echo "Resource group already exists."
99109
fi
110+
echo "RESOURCE_GROUP_NAME=${{ env.RESOURCE_GROUP_NAME }}" >> $GITHUB_OUTPUT
100111
101112
- name: Generate Unique Solution Prefix
102113
id: generate_solution_prefix
103114
run: |
104115
set -e
105-
COMMON_PART="pslr"
116+
COMMON_PART="psldg"
106117
TIMESTAMP=$(date +%s)
107-
UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 3)
118+
UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 6)
108119
UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
109120
echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
110121
echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
@@ -113,22 +124,99 @@ jobs:
113124
id: deploy
114125
run: |
115126
set -e
127+
# set image tag based on branch
128+
if [[ "${{ env.BRANCH_NAME }}" == "main" ]]; then
129+
IMAGE_TAG="latest"
130+
elif [[ "${{ env.BRANCH_NAME }}" == "dev" ]]; then
131+
IMAGE_TAG="dev"
132+
elif [[ "${{ env.BRANCH_NAME }}" == "demo" ]]; then
133+
IMAGE_TAG="demo"
134+
else
135+
IMAGE_TAG="latest"
136+
fi
137+
116138
az deployment group create \
139+
--name ${{ env.SOLUTION_PREFIX }}-deployment \
117140
--resource-group ${{ env.RESOURCE_GROUP_NAME }} \
118141
--template-file infra/main.json \
119142
--parameters \
120143
environmentName="${{ env.SOLUTION_PREFIX }}" \
121144
secondaryLocation="northcentralus" \
122145
deploymentType="GlobalStandard" \
123-
gptModelName="gpt-4o" \
146+
gptModelName="gpt-4.1" \
124147
azureOpenaiAPIVersion="2024-05-01-preview" \
125148
gptDeploymentCapacity=${{ env.GPT_MIN_CAPACITY }} \
126149
embeddingModel="text-embedding-ada-002" \
127150
embeddingDeploymentCapacity=${{ env.TEXT_EMBEDDING_MIN_CAPACITY }} \
128-
imageTag="latest"
129-
151+
imageTag="${IMAGE_TAG}"
152+
153+
- name: Get Deployment Output and extract Values
154+
id: get_output
155+
run: |
156+
set -e
157+
echo "Fetching deployment output..."
158+
BICEP_OUTPUT=$(az deployment group show --name ${{ env.SOLUTION_PREFIX }}-deployment --resource-group ${{ env.RESOURCE_GROUP_NAME }} --query "properties.outputs" -o json)
159+
echo "Extracting deployment output..."
160+
WEBAPP_URL=$(echo $BICEP_OUTPUT | jq -r '.weB_APP_URL.value')
161+
echo "WEBAPP_URL=$WEBAPP_URL" >> $GITHUB_OUTPUT
162+
STORAGE_ACCOUNT_NAME=$(echo $BICEP_OUTPUT | jq -r '.storagE_ACCOUNT_NAME.value')
163+
echo "STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT_NAME" >> $GITHUB_ENV
164+
STORAGE_CONTAINER_NAME=$(echo $BICEP_OUTPUT | jq -r '.storagE_CONTAINER_NAME.value')
165+
echo "STORAGE_CONTAINER_NAME=$STORAGE_CONTAINER_NAME" >> $GITHUB_ENV
166+
KEY_VAULT_NAME=$(echo $BICEP_OUTPUT | jq -r '.keY_VAULT_NAME.value')
167+
echo "KEY_VAULT_NAME=$KEY_VAULT_NAME" >> $GITHUB_ENV
168+
COSMOSDB_ACCOUNT_NAME=$(echo $BICEP_OUTPUT | jq -r '.cosmosdB_ACCOUNT_NAME.value')
169+
echo "COSMOSDB_ACCOUNT_NAME=$COSMOSDB_ACCOUNT_NAME" >> $GITHUB_ENV
170+
echo "Deployment output: $BICEP_OUTPUT"
171+
172+
- name: Run Post-Deployment Script
173+
id: post_deploy
174+
run: |
175+
set -e
176+
az account set --subscription "${{ secrets.AZURE_SUBSCRIPTION_ID }}"
177+
178+
echo "Running post-deployment script..."
179+
bash ./infra/scripts/copy_kb_files.sh \
180+
"${{ env.STORAGE_ACCOUNT_NAME }}" \
181+
"${{ env.STORAGE_CONTAINER_NAME }}" \
182+
"${{ secrets.AZURE_CLIENT_ID }}"
183+
bash ./infra/scripts/run_create_index_scripts.sh \
184+
"${{ env.KEY_VAULT_NAME }}" \
185+
"${{ secrets.AZURE_CLIENT_ID }}"
186+
187+
- name: Logout from Azure
188+
if: always()
189+
run: |
190+
az logout
191+
echo "Logged out from Azure."
192+
193+
194+
e2e-test:
195+
needs: deploy
196+
uses: ./.github/workflows/test-automation.yml
197+
with:
198+
DOCGEN_URL: ${{ needs.deploy.outputs.WEBAPP_URL }}
199+
secrets: inherit
200+
201+
cleanup-deployment:
202+
if: always() && needs.deploy.outputs.RESOURCE_GROUP_NAME != ''
203+
needs: [deploy, e2e-test]
204+
runs-on: ubuntu-latest
205+
env:
206+
RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
207+
steps:
208+
- name: Setup Azure CLI
209+
run: |
210+
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
211+
az --version # Verify installation
212+
213+
- name: Login to Azure
214+
run: |
215+
az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
216+
az account set --subscription "${{ secrets.AZURE_SUBSCRIPTION_ID }}"
217+
130218
- name: Extract AI Services and Key Vault Names
131-
if: always() && steps.check_create_rg.outcome == 'success'
219+
if: always()
132220
run: |
133221
echo "Fetching AI Services and Key Vault names before deletion..."
134222
@@ -288,17 +376,23 @@ jobs:
288376
289377
290378
- name: Send Notification on Failure
291-
if: failure()
379+
if: failure() || needs.deploy.result == 'failure'
292380
run: |
293381
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
294382
295383
EMAIL_BODY=$(cat <<EOF
296384
{
297-
"body": "<p>Dear Team,</p><p>We would like to inform you that the DocGen Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Build URL:</strong> ${RUN_URL}<br> ${OUTPUT}</p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>"
385+
"body": "<p>Dear Team,</p><p>We would like to inform you that the DocGen Deployment Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Build URL:</strong> <a href=\"${RUN_URL}\">${RUN_URL}</a><br></p><p>Please investigate the matter at your earliest convenience.</p><p>Best regards,<br>Your Automation Team</p>"
298386
}
299387
EOF
300388
)
301389
302390
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
303391
-H "Content-Type: application/json" \
304392
-d "$EMAIL_BODY" || echo "Failed to send notification"
393+
394+
- name: Logout from Azure
395+
if: always()
396+
run: |
397+
az logout
398+
echo "Logged out from Azure."

.github/workflows/python-app.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- name: Test with pytest
3030
run: |
3131
export PYTHONPATH=$(pwd)/src
32-
pytest -v --show-capture=stdout -k "not integration"
32+
pytest -v --show-capture=stdout -k "not integration" ./src/tests
3333
3434
test_windows:
3535
runs-on:
@@ -47,4 +47,4 @@ jobs:
4747
- name: Test with pytest
4848
run: |
4949
$env:PYTHONPATH="$pwd\src"
50-
pytest -v --show-capture=stdout -k "not integration"
50+
pytest -v --show-capture=stdout -k "not integration" ./src/tests
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Test Automation DocGen
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
DOCGEN_URL:
7+
required: true
8+
type: string
9+
description: "Web URL for DocGen"
10+
secrets:
11+
EMAILNOTIFICATION_LOGICAPP_URL_TA:
12+
required: false
13+
description: "Logic App URL for email notifications"
14+
15+
env:
16+
url: ${{ inputs.DOCGEN_URL }}
17+
accelerator_name: "DocGen"
18+
19+
jobs:
20+
test:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v4
28+
with:
29+
python-version: '3.13'
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install -r tests/e2e-test/requirements.txt
35+
36+
- name: Ensure browsers are installed
37+
run: python -m playwright install --with-deps chromium
38+
39+
- name: Open URL
40+
run: |
41+
echo "Opening URL: ${{ env.url }}"
42+
python -m webbrowser "${{ env.url }}"
43+
44+
- name: Sleep for 30 seconds
45+
run: sleep 30s
46+
shell: bash
47+
48+
- name: Run tests(1)
49+
id: test1
50+
run: |
51+
xvfb-run pytest --headed --html=report/report.html --self-contained-html
52+
working-directory: tests/e2e-test
53+
continue-on-error: true
54+
55+
- name: Sleep for 30 seconds
56+
if: ${{ steps.test1.outcome == 'failure' }}
57+
run: sleep 30s
58+
shell: bash
59+
60+
- name: Run tests(2)
61+
if: ${{ steps.test1.outcome == 'failure' }}
62+
id: test2
63+
run: |
64+
xvfb-run pytest --headed --html=report/report.html --self-contained-html
65+
working-directory: tests/e2e-test
66+
continue-on-error: true
67+
68+
- name: Sleep for 60 seconds
69+
if: ${{ steps.test2.outcome == 'failure' }}
70+
run: sleep 60s
71+
shell: bash
72+
73+
- name: Run tests(3)
74+
if: ${{ steps.test2.outcome == 'failure' }}
75+
id: test3
76+
run: |
77+
xvfb-run pytest --headed --html=report/report.html --self-contained-html
78+
working-directory: tests/e2e-test
79+
80+
- name: Upload test report
81+
id: upload_report
82+
uses: actions/upload-artifact@v4
83+
if: ${{ !cancelled() }}
84+
with:
85+
name: test-report
86+
path: tests/e2e-test/report/*
87+
88+
- name: Send Notification
89+
if: always()
90+
run: |
91+
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
92+
REPORT_URL=${{ steps.upload_report.outputs.artifact-url }}
93+
IS_SUCCESS=${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }}
94+
# Construct the email body
95+
if [ "$IS_SUCCESS" = "true" ]; then
96+
EMAIL_BODY=$(cat <<EOF
97+
{
98+
"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>",
99+
"subject": "${{ env.accelerator_name }} Test Automation - Success"
100+
}
101+
EOF
102+
)
103+
else
104+
EMAIL_BODY=$(cat <<EOF
105+
{
106+
"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>",
107+
"subject": "${{ env.accelerator_name }} Test Automation - Failure"
108+
}
109+
EOF
110+
)
111+
fi
112+
113+
# Send the notification
114+
curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
115+
-H "Content-Type: application/json" \
116+
-d "$EMAIL_BODY" || echo "Failed to send notification"

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
3636
- name: Run Backend Tests with Coverage
3737
run: |
38-
if python -m pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=coverage-junit.xml; then
38+
if python -m pytest --cov=. --cov-report=xml --cov-report=html --cov-report=term-missing --junitxml=coverage-junit.xml ./src/tests; then
3939
echo "Tests completed, checking coverage."
4040
# Only fail if coverage does not meet criteria
4141
if [ -f coverage.xml ]; then

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ _Note: This is not meant to outline all costs as selected SKUs, scaled use, cust
9999
| [Azure AI Search](https://learn.microsoft.com/en-us/azure/search/) | Standard tier, S1. Pricing is based on the number of documents and operations. Information retrieval at scale for vector and text content in traditional or generative search scenarios. | [Pricing](https://azure.microsoft.com/pricing/details/search/) |
100100
| [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/blobs/) | Standard tier, LRS. Pricing is based on storage and operations. Blob storage in the clopud, optimized for storing massive amounts of unstructured data. | [Pricing](https://azure.microsoft.com/pricing/details/storage/blobs/) |
101101
| [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/) | Standard tier. Pricing is based on the number of operations. Maintain keys that access and encrypt your cloud resources, apps, and solutions. | [Pricing](https://azure.microsoft.com/pricing/details/key-vault/) |
102-
| [Azure AI Services](https://learn.microsoft.com/en-us/azure/ai-services/) | S0 tier, defaults to gpt-4o and text-embedding-ada-002 models. Pricing is based on token count. | [Pricing](https://azure.microsoft.com/pricing/details/cognitive-services/) |
102+
| [Azure AI Services](https://learn.microsoft.com/en-us/azure/ai-services/) | S0 tier, defaults to gpt-4.1 and text-embedding-ada-002 models. Pricing is based on token count. | [Pricing](https://azure.microsoft.com/pricing/details/cognitive-services/) |
103103
| [Azure Container App](https://learn.microsoft.com/en-us/azure/container-apps/) | Consumption tier with 0.5 CPU, 1GiB memory/storage. Pricing is based on resource allocation, and each month allows for a certain amount of free usage. Allows you to run containerized applications without worrying about orchestration or infrastructure. | [Pricing](https://azure.microsoft.com/pricing/details/container-apps/) |
104104
| [Azure Container Registry](https://learn.microsoft.com/en-us/azure/container-registry/) | Basic tier. Build, store, and manage container images and artifacts in a private registry for all types of container deployments | [Pricing](https://azure.microsoft.com/pricing/details/container-registry/) |
105105
| [Log analytics](https://learn.microsoft.com/en-us/azure/azure-monitor/) | Pay-as-you-go tier. Costs based on data ingested. Collect and analyze on telemetry data generated by Azure. | [Pricing](https://azure.microsoft.com/pricing/details/monitor/) |

docs/AzureGPTQuotaSettings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
3. **Go to** the `Management Center` from the bottom-left navigation menu.
66
4. Select `Quota`
77
- Click on the `GlobalStandard` dropdown.
8-
- Select the required **GPT model** (`GPT-4, GPT-4o`) or **Embeddings model** (`text-embedding-ada-002`).
8+
- Select the required **GPT model** (`GPT-4.1`) or **Embeddings model** (`text-embedding-ada-002`).
99
- Choose the **region** where the deployment is hosted.
1010
5. Request More Quota or delete any unused model deployments as needed.

docs/CustomizingAzdParameters.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ By default this template will use the environment name as the prefix to prevent
1313
| `AZURE_ENV_NAME` | string | `docgen` | Sets the environment name prefix for all Azure resources. |
1414
| `AZURE_ENV_SECONDARY_LOCATION` | string | `eastus2` | Specifies a secondary Azure region. |
1515
| `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `Standard` | Defines the model deployment type (allowed: `Standard`, `GlobalStandard`). |
16-
| `AZURE_ENV_MODEL_NAME` | string | `gpt-4o` | Specifies the GPT model name (allowed: `gpt-4`, `gpt-4o`). |
16+
| `AZURE_ENV_MODEL_NAME` | string | `gpt-4.1` | Specifies the GPT model name (allowed: `gpt-4`, `gpt-4o`). |
1717
| `AZURE_ENV_MODEL_VERSION` | string | `2024-05-13` | Set the Azure model version (allowed values: `2024-08-06`). |
1818
| `AZURE_ENV_OPENAI_API_VERSION` | string | `2024-05-01-preview` | Specifies the API version for Azure OpenAI. |
1919
| `AZURE_ENV_MODEL_CAPACITY` | integer | `30` | Sets the GPT model capacity (based on what's available in your subscription). |
@@ -23,8 +23,10 @@ By default this template will use the environment name as the prefix to prevent
2323
| `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID` | string | `<Existing Workspace Id>` | Reuses an existing Log Analytics Workspace instead of creating a new one. |
2424

2525

26+
2627
## How to Set a Parameter
2728

29+
2830
To customize any of the above values, run the following command **before** `azd up`:
2931

3032
```bash

0 commit comments

Comments
 (0)