Skip to content

Commit fc269f5

Browse files
Harmanpreet-MicrosoftHarmanpreet Kaur
andauthored
ci: refactor deployment workflow to include dynamic URL outputs, e2e test orchestration, and improved Makefile targets (#1855)
Co-authored-by: Harmanpreet Kaur <[email protected]>
1 parent 21d3aef commit fc269f5

File tree

7 files changed

+27744
-46
lines changed

7 files changed

+27744
-46
lines changed

.github/workflows/ci.yml

Lines changed: 257 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
- demo
99
schedule:
1010
- cron: '0 8,20 * * *' # Runs at 8:00 AM and 8:00 PM GMT
11+
workflow_dispatch:
1112

1213
permissions:
1314
contents: read
@@ -17,19 +18,24 @@ concurrency:
1718
group: ${{ github.workflow }}-${{ github.ref }}
1819

1920
jobs:
20-
ci:
21+
deploy:
2122
runs-on: ubuntu-latest
2223
env:
2324
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
2425
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
2526
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
2627
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
2728

29+
outputs:
30+
imageTag: ${{ steps.set-image-tag.outputs.imageTag }}
31+
web_url: ${{ steps.extract-urls.outputs.web_url }}
32+
admin_url: ${{ steps.extract-urls.outputs.admin_url }}
33+
DEPLOYMENT_SUCCESS: ${{ steps.final-status.outputs.DEPLOYMENT_SUCCESS }}
34+
2835
steps:
2936
- name: Checkout code
3037
uses: actions/checkout@v4
3138

32-
# Run Quota Check Script
3339
- name: Run Quota Check
3440
id: quota-check
3541
run: |
@@ -43,11 +49,10 @@ jobs:
4349
4450
chmod +x scripts/checkquota.sh
4551
if ! scripts/checkquota.sh; then
46-
# If quota check fails due to insufficient quota, set the flag
4752
if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
4853
echo "QUOTA_FAILED=true" >> $GITHUB_ENV
4954
fi
50-
exit 1 # Fail the pipeline if any other failure occurs
55+
exit 1
5156
fi
5257
5358
- name: Send Notification on Quota Failure
@@ -69,8 +74,6 @@ jobs:
6974
if: env.QUOTA_FAILED == 'true'
7075
run: exit 1
7176

72-
# The pipeline stops here if quota check fails!
73-
7477
- name: Set Deployment Region
7578
run: |
7679
echo "Selected Region: $VALID_REGION"
@@ -88,36 +91,263 @@ jobs:
8891
run: |
8992
if [[ "${{ github.event_name }}" == "schedule" ]]; then
9093
echo "imageTag=latest" >> $GITHUB_ENV
94+
echo "::set-output name=imageTag::latest"
9195
elif [[ "${{ github.ref_name }}" == "main" ]]; then
9296
echo "imageTag=latest" >> $GITHUB_ENV
97+
echo "::set-output name=imageTag::latest"
9398
else
9499
echo "imageTag=${{ github.ref_name }}" >> $GITHUB_ENV
100+
echo "::set-output name=imageTag::${{ github.ref_name }}"
95101
fi
96102
97-
- name: Pre-build image and run make in dev container
103+
- name: Pre-build image and deploy
98104
uses: devcontainers/[email protected]
99105
env:
100-
AZURE_ENV_NAME: ${{ github.run_id }}
101-
AZURE_LOCATION: ${{ env.AZURE_LOCATION }}
106+
AZURE_ENV_NAME: ${{ github.run_id }}
107+
AZURE_LOCATION: ${{ env.AZURE_LOCATION }}
102108
with:
103-
imageName: ghcr.io/azure-samples/chat-with-your-data-solution-accelerator
104-
cacheFrom: ghcr.io/azure-samples/chat-with-your-data-solution-accelerator
105-
imageTag: ${{ env.imageTag }}
106-
runCmd: export optional_args="./code/tests" && make ci && make deploy
107-
refFilterForPush: refs/heads/${{ github.event_name == 'schedule' && 'main' || github.ref_name }}
108-
env: |
109-
AZURE_CLIENT_ID
110-
AZURE_CLIENT_SECRET
111-
AZURE_TENANT_ID
112-
AZURE_SUBSCRIPTION_ID
113-
AZURE_ENV_NAME
114-
AZURE_LOCATION
115-
- name: Tidy up
116-
uses: devcontainers/[email protected]
117-
if: always()
109+
push: never
110+
imageName: ghcr.io/azure-samples/chat-with-your-data-solution-accelerator
111+
cacheFrom: ghcr.io/azure-samples/chat-with-your-data-solution-accelerator
112+
imageTag: ${{ env.imageTag }}
113+
runCmd: |
114+
export optional_args="./code/tests"
115+
116+
# Azure login first
117+
az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID
118+
az account set --subscription $AZURE_SUBSCRIPTION_ID
119+
120+
# Capture deployment output to a log file
121+
make ci 2>&1 | tee ci_output.log
122+
make deploy 2>&1 | tee deploy_output.log
123+
124+
# Try to extract URLs from deployment logs as backup
125+
echo "=== Extracting URLs from deployment logs ==="
126+
grep -oE "https://[a-zA-Z0-9.-]*\.azurewebsites\.net/" deploy_output.log | head -2 | tee extracted_urls.txt || echo "No URLs found in logs"
127+
128+
# Check if we have admin URL in logs
129+
grep -E "Done: Deploying service adminweb" -A 2 deploy_output.log | grep -oE "https://[a-zA-Z0-9.-]*\.azurewebsites\.net/" > log_admin_url.txt || echo "" > log_admin_url.txt
130+
131+
# Check if we have web URL in logs
132+
grep -E "Done: Deploying service web" -A 2 deploy_output.log | grep -oE "https://[a-zA-Z0-9.-]*\.azurewebsites\.net/" > log_web_url.txt || echo "" > log_web_url.txt
133+
134+
echo "URLs from logs:"
135+
echo "Admin URL from logs: $(cat log_admin_url.txt)"
136+
echo "Frontend URL from logs: $(cat log_web_url.txt)"
137+
env: |
138+
AZURE_CLIENT_ID
139+
AZURE_CLIENT_SECRET
140+
AZURE_TENANT_ID
141+
AZURE_SUBSCRIPTION_ID
142+
AZURE_ENV_NAME
143+
AZURE_LOCATION
144+
AUTH_ENABLED=false
145+
AZURE_USE_AUTHENTICATION=false
146+
AZURE_ENABLE_AUTH=false
147+
FORCE_NO_AUTH=true
148+
ENFORCE_AUTH=false
149+
REQUIRE_AUTHENTICATION=false
150+
AUTHENTICATION_ENABLED=false
151+
WEBSITES_AUTH_ENABLED=false
152+
WEBSITE_AUTH_ENABLED=false
153+
AZURE_AUTH_ENABLED=false
154+
ENABLE_AUTHENTICATION=false
155+
DISABLE_AUTHENTICATION=true
156+
NO_AUTH=true
157+
SKIP_AUTH=true
158+
159+
- name: Extract URLs from deployment
160+
id: extract-urls
161+
run: |
162+
# Method 1: Check files created by Makefile
163+
echo "=== Method 1: Files from Makefile ==="
164+
if [ -f "web_url.txt" ]; then
165+
WEB_URL=$(cat web_url.txt | tr -d '\n\r' | xargs)
166+
echo "Web URL from makefile: '$WEB_URL'"
167+
fi
168+
169+
if [ -f "admin_url.txt" ]; then
170+
ADMIN_URL=$(cat admin_url.txt | tr -d '\n\r' | xargs)
171+
echo "Admin URL from makefile: '$ADMIN_URL'"
172+
fi
173+
174+
# Method 2: Check URLs extracted from logs
175+
echo "=== Method 2: URLs from deployment logs ==="
176+
if [ -f "log_web_url.txt" ]; then
177+
LOG_WEB_URL=$(cat log_web_url.txt | tr -d '\n\r' | xargs)
178+
echo "Web URL from logs: '$LOG_WEB_URL'"
179+
if [ -z "$WEB_URL" ] && [ -n "$LOG_WEB_URL" ]; then
180+
WEB_URL="$LOG_WEB_URL"
181+
fi
182+
fi
183+
184+
if [ -f "log_admin_url.txt" ]; then
185+
LOG_ADMIN_URL=$(cat log_admin_url.txt | tr -d '\n\r' | xargs)
186+
echo "Admin URL from logs: '$LOG_ADMIN_URL'"
187+
if [ -z "$ADMIN_URL" ] && [ -n "$LOG_ADMIN_URL" ]; then
188+
ADMIN_URL="$LOG_ADMIN_URL"
189+
fi
190+
fi
191+
192+
# Set outputs
193+
if [ -n "$WEB_URL" ] && [ "$WEB_URL" != "null" ] && [ "$WEB_URL" != "" ]; then
194+
echo "web_url=$WEB_URL" >> $GITHUB_OUTPUT
195+
echo "WEB_WEBSITE_URL=$WEB_URL" >> $GITHUB_ENV
196+
echo "✅ Web URL: $WEB_URL"
197+
else
198+
echo "web_url=" >> $GITHUB_OUTPUT
199+
echo "FRONTEND_WEBSITE_URL=" >> $GITHUB_ENV
200+
echo "❌ Frontend URL: Not found"
201+
fi
202+
203+
if [ -n "$ADMIN_URL" ] && [ "$ADMIN_URL" != "null" ] && [ "$ADMIN_URL" != "" ]; then
204+
echo "admin_url=$ADMIN_URL" >> $GITHUB_OUTPUT
205+
echo "ADMIN_WEBSITE_URL=$ADMIN_URL" >> $GITHUB_ENV
206+
echo "✅ Admin URL: $ADMIN_URL"
207+
else
208+
echo "admin_url=" >> $GITHUB_OUTPUT
209+
echo "ADMIN_WEBSITE_URL=" >> $GITHUB_ENV
210+
echo "❌ Admin URL: Not found"
211+
fi
212+
213+
# Additional debugging
214+
echo "=== All Available Files ==="
215+
ls -la *.txt *.log *.json 2>/dev/null || echo "No relevant files found"
216+
217+
- name: Display URLs
218+
run: |
219+
echo "Web URL: ${{ env.WEB_WEBSITE_URL }}"
220+
echo "Admin URL: ${{ env.ADMIN_WEBSITE_URL }}"
221+
echo "web_url=$WEB_URL" >> $GITHUB_OUTPUT
222+
echo "admin_url=$ADMIN_URL" >> $GITHUB_OUTPUT
223+
224+
- name: Disable Authentication with Script
225+
run: |
226+
chmod +x scripts/disable_auth.sh
227+
./scripts/disable_auth.sh
118228
env:
119-
AZURE_ENV_NAME: ${{ github.run_id }}
120-
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
229+
FRONTEND_WEBSITE_URL: ${{ env.WEB_WEBSITE_URL }}
230+
ADMIN_WEBSITE_URL: ${{ env.ADMIN_WEBSITE_URL }}
231+
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
232+
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
233+
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
234+
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
235+
236+
- name: Export PostgreSQL Host Endpoint from Makefile
237+
run: |
238+
# Only extract the PostgreSQL host endpoint from Makefile output
239+
# Other values are hardcoded in the script
240+
echo "=== Extracting PostgreSQL Host Endpoint ==="
241+
242+
if [ -f "pg_host.txt" ] && [ -s "pg_host.txt" ]; then
243+
PG_HOST_ENDPOINT=$(cat pg_host.txt | tr -d '\n\r' | xargs)
244+
echo "PG_HOST_DESTINATION=$PG_HOST_ENDPOINT" >> $GITHUB_ENV
245+
echo "✅ PostgreSQL Host Endpoint: $PG_HOST_ENDPOINT"
246+
else
247+
echo "❌ PostgreSQL host endpoint not found in pg_host.txt"
248+
echo "PG_HOST_DESTINATION=localhost" >> $GITHUB_ENV
249+
echo "Warning: Using localhost as fallback"
250+
fi
251+
252+
echo "=== PostgreSQL Configuration Summary ==="
253+
echo "Host Endpoint: $PG_HOST_DESTINATION"
254+
echo "Username: admintest (hardcoded)"
255+
echo "Password: Initial_0524 (hardcoded)"
256+
echo "Database: postgres (hardcoded)"
257+
echo "Port: 5432 (hardcoded)"
258+
259+
- name: Set up Python
260+
uses: actions/setup-python@v5
261+
with:
262+
python-version: '3.11'
263+
264+
- name: Install Python dependencies
265+
run: |
266+
pip install psycopg2-binary python-dotenv
267+
268+
269+
- name: Populate PostgreSQL Database
270+
run: |
271+
python - <<EOF
272+
import os
273+
import psycopg2
274+
275+
db_params = {
276+
"user": "admintest",
277+
"password": "Initial_0524",
278+
"host": os.environ.get("PG_HOST_DESTINATION", "localhost"),
279+
"port": "5432",
280+
"dbname": "postgres",
281+
"sslmode": "require"
282+
}
283+
284+
csv_file = "exported_data_vector_score.csv"
285+
target_table = "vector_store"
286+
287+
try:
288+
with psycopg2.connect(**db_params) as conn:
289+
with conn.cursor() as cur:
290+
with open(csv_file, "r", encoding="utf-8") as f:
291+
next(f) # Skip header
292+
cur.copy_expert(f"COPY {target_table} FROM STDIN WITH CSV", f)
293+
conn.commit()
294+
print(f"✅ Imported data from '{csv_file}' into table '{target_table}'.")
295+
except Exception as e:
296+
print(f"❌ Error during import: {e}")
297+
EOF
298+
299+
300+
301+
- name: Final Status Check
302+
id: final-status
303+
run: |
304+
echo "=== Final Deployment Status ==="
305+
echo "Frontend URL: ${{ env.FRONTEND_WEBSITE_URL }}"
306+
echo "Admin URL: ${{ env.ADMIN_WEBSITE_URL }}"
307+
echo ""
308+
echo "🚀 Deployment completed!"
309+
echo "⏰ If you still see authentication errors, wait an additional 10-15 minutes."
310+
echo "🔄 Azure authentication changes can take up to 15 minutes to fully propagate."
311+
echo ""
312+
echo "🌐 Try accessing your applications:"
313+
echo " Frontend: ${{ env.FRONTEND_WEBSITE_URL }}"
314+
echo " Admin: ${{ env.ADMIN_WEBSITE_URL }}"
315+
echo "DEPLOYMENT_SUCCESS=true" >> $GITHUB_OUTPUT
316+
317+
318+
- name: Wait for 5 minutes for propagation
319+
run: sleep 300
320+
321+
322+
e2e-test:
323+
needs: deploy
324+
if: needs.deploy.outputs.DEPLOYMENT_SUCCESS == 'true'
325+
uses: ./.github/workflows/test-automation.yml
326+
with:
327+
web_url: ${{ needs.deploy.outputs.web_url }}
328+
admin_url: ${{ needs.deploy.outputs.admin_url }}
329+
330+
331+
cleanup:
332+
if: always()
333+
needs: [deploy, e2e-test]
334+
runs-on: ubuntu-latest
335+
336+
env:
337+
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
338+
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
339+
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
340+
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
341+
AZURE_ENV_NAME: ${{ github.run_id }}
342+
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
343+
imageTag: ${{ needs.deploy.outputs.imageTag }}
344+
345+
steps:
346+
- name: Checkout code
347+
uses: actions/checkout@v4
348+
349+
- name: Destroy resources
350+
uses: devcontainers/[email protected]
121351
with:
122352
push: never
123353
imageName: ghcr.io/azure-samples/chat-with-your-data-solution-accelerator
@@ -135,15 +365,13 @@ jobs:
135365
if: failure()
136366
run: |
137367
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
138-
# Construct the email body
139368
EMAIL_BODY=$(cat <<EOF
140369
{
141-
"body": "<p>Dear Team,</p><p>We would like to inform you that the CWYD 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>"
370+
"body": "<p>Dear Team,</p><p>The CWYD Automation process has encountered an issue and has failed to complete successfully.</p><p><strong>Build URL:</strong> ${RUN_URL}</p><p>Please investigate.</p><p>Best regards,<br>Your Automation Team</p>"
142371
}
143372
EOF
144373
)
145374
146-
# Send the notification
147375
curl -X POST "${{ secrets.LOGIC_APP_URL }}" \
148376
-H "Content-Type: application/json" \
149377
-d "$EMAIL_BODY" || echo "Failed to send notification"

.github/workflows/test-automation.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
name: Test Automation CWYD
22
on:
3-
push:
4-
branches:
5-
- main
6-
- dev
7-
paths:
8-
- 'tests/e2e-test/**'
9-
schedule:
10-
- cron: '0 13 * * 3' # Runs at 1 PM UTC once a week on Wednesday
11-
workflow_dispatch:
3+
workflow_call:
4+
inputs:
5+
web_url:
6+
required: true
7+
type: string
8+
admin_url:
9+
required: true
10+
type: string
1211

13-
env:
14-
web_url: ${{ vars.CWYD_WEB_URL }}
15-
admin_url: ${{ vars.CWYD_ADMIN_URL }}
16-
accelerator_name: "Chat with your Data"
1712

1813
jobs:
1914
test:
2015
runs-on: ubuntu-latest
16+
env:
17+
web_url: ${{ inputs.web_url }}
18+
admin_url: ${{ inputs.admin_url }}
19+
accelerator_name: "Chat with your Data"
20+
2121
steps:
2222
- name: Checkout repository
2323
uses: actions/checkout@v4

0 commit comments

Comments
 (0)