Skip to content

Commit 51b0c77

Browse files
ci: Added post-deployment workflow and script execution logic (#2168)
1 parent be3edba commit 51b0c77

4 files changed

Lines changed: 245 additions & 50 deletions

File tree

.github/workflows/job-deploy.yml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,13 +557,25 @@ jobs:
557557
DATABASE_TYPE: ${{ inputs.DATABASE_TYPE }}
558558
secrets: inherit
559559

560+
# Run post-deployment setup (Function App client key + PostgreSQL tables)
561+
post-deployment-setup:
562+
needs: [azure-setup, deploy-linux, deploy-windows]
563+
if: |
564+
always() &&
565+
(needs.deploy-linux.result == 'success' || needs.deploy-windows.result == 'success')
566+
uses: ./.github/workflows/job-post-deployment-setup.yml
567+
with:
568+
RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
569+
secrets: inherit
570+
560571
# Call PostgreSQL setup workflow when DATABASE_TYPE is PostgreSQL
561572
import-sample-data-postgresql:
562-
needs: [azure-setup, deploy-linux, deploy-windows]
573+
needs: [azure-setup, deploy-linux, deploy-windows, post-deployment-setup]
563574
if: |
564575
always() &&
565576
inputs.DATABASE_TYPE == 'PostgreSQL' &&
566-
(needs.deploy-linux.result == 'success' || needs.deploy-windows.result == 'success')
577+
(needs.deploy-linux.result == 'success' || needs.deploy-windows.result == 'success') &&
578+
needs.post-deployment-setup.result == 'success'
567579
uses: ./.github/workflows/import-sample-data-postgresql.yml
568580
with:
569581
RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
@@ -572,11 +584,12 @@ jobs:
572584

573585
# Call CosmosDB/Azure Search setup workflow when DATABASE_TYPE is CosmosDB
574586
import-sample-data-cosmosdb:
575-
needs: [azure-setup, deploy-linux, deploy-windows]
587+
needs: [azure-setup, deploy-linux, deploy-windows, post-deployment-setup]
576588
if: |
577589
always() &&
578590
inputs.DATABASE_TYPE == 'CosmosDB' &&
579-
(needs.deploy-linux.result == 'success' || needs.deploy-windows.result == 'success')
591+
(needs.deploy-linux.result == 'success' || needs.deploy-windows.result == 'success') &&
592+
needs.post-deployment-setup.result == 'success'
580593
uses: ./.github/workflows/import-sample-data-cosmosdb.yml
581594
with:
582595
RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Post-Deployment Setup
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
RESOURCE_GROUP_NAME:
7+
description: 'Azure Resource Group name'
8+
required: true
9+
type: string
10+
workflow_call:
11+
inputs:
12+
RESOURCE_GROUP_NAME:
13+
description: 'Azure Resource Group name'
14+
required: true
15+
type: string
16+
17+
permissions:
18+
id-token: write
19+
contents: read
20+
21+
jobs:
22+
post-deployment-setup:
23+
runs-on: ubuntu-latest
24+
environment: production
25+
steps:
26+
- name: Checkout Code
27+
uses: actions/checkout@v4
28+
29+
- name: Login to Azure
30+
uses: azure/login@v2
31+
with:
32+
client-id: ${{ secrets.AZURE_CLIENT_ID }}
33+
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
34+
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
35+
36+
- name: Setup Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: '3.11'
40+
41+
- name: Install Python Dependencies
42+
shell: bash
43+
run: |
44+
pip install psycopg2-binary azure-identity
45+
46+
- name: Run Post-Deployment Setup (Attempt 1)
47+
id: setup1
48+
shell: bash
49+
env:
50+
RESOURCE_GROUP: ${{ inputs.RESOURCE_GROUP_NAME }}
51+
run: |
52+
chmod +x scripts/post_deployment_setup.sh
53+
bash scripts/post_deployment_setup.sh "$RESOURCE_GROUP"
54+
continue-on-error: true
55+
56+
- name: Wait 20 seconds before retry
57+
if: ${{ steps.setup1.outcome == 'failure' }}
58+
shell: bash
59+
run: sleep 20s
60+
61+
- name: Run Post-Deployment Setup (Attempt 2)
62+
id: setup2
63+
if: ${{ steps.setup1.outcome == 'failure' }}
64+
shell: bash
65+
env:
66+
RESOURCE_GROUP: ${{ inputs.RESOURCE_GROUP_NAME }}
67+
run: |
68+
chmod +x scripts/post_deployment_setup.sh
69+
bash scripts/post_deployment_setup.sh "$RESOURCE_GROUP"
70+
continue-on-error: true
71+
72+
- name: Wait 40 seconds before final retry
73+
if: ${{ steps.setup2.outcome == 'failure' }}
74+
shell: bash
75+
run: sleep 40s
76+
77+
- name: Run Post-Deployment Setup (Attempt 3)
78+
id: setup3
79+
if: ${{ steps.setup2.outcome == 'failure' }}
80+
shell: bash
81+
env:
82+
RESOURCE_GROUP: ${{ inputs.RESOURCE_GROUP_NAME }}
83+
run: |
84+
chmod +x scripts/post_deployment_setup.sh
85+
bash scripts/post_deployment_setup.sh "$RESOURCE_GROUP"
86+
87+
- name: Generate Post-Deployment Summary
88+
if: always()
89+
shell: bash
90+
run: |
91+
echo "## 🔧 Post-Deployment Setup Summary" >> $GITHUB_STEP_SUMMARY
92+
echo "" >> $GITHUB_STEP_SUMMARY
93+
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
94+
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
95+
echo "| **Job Status** | ${{ job.status == 'success' && '✅ Success' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
96+
echo "| **Resource Group** | \`${{ inputs.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
97+
98+
- name: Logout from Azure
99+
if: always()
100+
shell: bash
101+
run: |
102+
az logout || true
103+
echo "Logged out from Azure."

scripts/post_deployment_setup.ps1

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,40 @@ $pgAdminCmd = "ad-admin"
3535
$entraCheck = az postgres flexible-server microsoft-entra-admin --help 2>$null
3636
if ($LASTEXITCODE -eq 0) { $pgAdminCmd = "microsoft-entra-admin" }
3737

38+
# -------------------------------------------------------
39+
# Detect identity type: interactive user vs service principal
40+
# -------------------------------------------------------
41+
$identityType = "user"
42+
$currentIdentityOid = $null
43+
$currentIdentityDisplay = $null
44+
$principalType = "User"
45+
46+
# Try signed-in user first
47+
$currentIdentityOid = az ad signed-in-user show --query "id" -o tsv 2>$null
48+
if ($currentIdentityOid) {
49+
$identityType = "user"
50+
$currentIdentityDisplay = az ad signed-in-user show --query "userPrincipalName" -o tsv 2>$null
51+
$principalType = "User"
52+
Write-Host "✓ Detected identity type: User ($currentIdentityDisplay)"
53+
} else {
54+
# Fallback to service principal
55+
$spAppId = az account show --query "user.name" -o tsv 2>$null
56+
if ($spAppId -and $spAppId -ne "null") {
57+
$currentIdentityOid = az ad sp show --id $spAppId --query "id" -o tsv 2>$null
58+
$currentIdentityDisplay = az ad sp show --id $spAppId --query "displayName" -o tsv 2>$null
59+
if ($currentIdentityOid) {
60+
$identityType = "servicePrincipal"
61+
$principalType = "ServicePrincipal"
62+
Write-Host "✓ Detected identity type: Service Principal ($currentIdentityDisplay, OID: $currentIdentityOid)"
63+
}
64+
}
65+
}
66+
67+
if (-not $currentIdentityOid) {
68+
Write-Warning "⚠ Could not determine current identity (user or service principal)."
69+
Write-Warning " Some operations (Key Vault role assignment, PostgreSQL admin) may be skipped."
70+
}
71+
3872
# Track resources that need public access restored to Disabled
3973
$resourcesToRestore = @()
4074

@@ -108,16 +142,15 @@ else {
108142
$keyVaultName = ($keyVaults -split "`n")[0].Trim()
109143
Write-Host "✓ Discovered Key Vault: $keyVaultName"
110144

111-
# Ensure the current user has 'Key Vault Secrets User' role on the Key Vault
112-
$currentUserOid = az ad signed-in-user show --query "id" -o tsv 2>$null
113-
if ($currentUserOid) {
145+
# Ensure the current identity has 'Key Vault Secrets User' role on the Key Vault
146+
if ($currentIdentityOid) {
114147
$kvResourceId = az keyvault show --name $keyVaultName --resource-group $ResourceGroupName --query "id" -o tsv 2>$null
115148
if ($kvResourceId) {
116149
$kvSecretsUserRoleId = "4633458b-17de-408a-b874-0445c86b69e6"
117-
$existingAssignment = az role assignment list --assignee $currentUserOid --role $kvSecretsUserRoleId --scope $kvResourceId --query "[0].id" -o tsv 2>$null
150+
$existingAssignment = az role assignment list --assignee $currentIdentityOid --role $kvSecretsUserRoleId --scope $kvResourceId --query "[0].id" -o tsv 2>$null
118151
if (-not $existingAssignment) {
119-
Write-Host "✓ Assigning 'Key Vault Secrets User' role to current user on Key Vault..."
120-
$roleOutput = az role assignment create --assignee-object-id $currentUserOid --assignee-principal-type User --role $kvSecretsUserRoleId --scope $kvResourceId 2>&1 | Out-String
152+
Write-Host "✓ Assigning 'Key Vault Secrets User' role to current ${identityType} on Key Vault..."
153+
$roleOutput = az role assignment create --assignee-object-id $currentIdentityOid --assignee-principal-type $principalType --role $kvSecretsUserRoleId --scope $kvResourceId 2>&1 | Out-String
121154
if ($LASTEXITCODE -ne 0) {
122155
Write-Warning "⚠ Failed to assign Key Vault Secrets User role."
123156
Write-Warning " $roleOutput"
@@ -126,11 +159,11 @@ else {
126159
Start-Sleep -Seconds 30
127160
}
128161
} else {
129-
Write-Host "✓ Current user already has 'Key Vault Secrets User' role on Key Vault."
162+
Write-Host "✓ Current ${identityType} already has 'Key Vault Secrets User' role on Key Vault."
130163
}
131164
}
132165
} else {
133-
Write-Warning "⚠ Could not determine current user OID. Skipping Key Vault role assignment."
166+
Write-Warning "⚠ Could not determine current identity OID. Skipping Key Vault role assignment."
134167
}
135168

136169
# Check if Key Vault public access is disabled (WAF/private networking)
@@ -235,14 +268,14 @@ else {
235268
--start-ip-address $publicIp `
236269
--end-ip-address $publicIp 2>$null | Out-Null
237270

238-
# Get current user info for local Entra auth to PostgreSQL
239-
$currentUserUpn = az ad signed-in-user show --query "userPrincipalName" -o tsv 2>$null
240-
$currentUserOid = az ad signed-in-user show --query "id" -o tsv 2>$null
241-
if (-not $currentUserUpn -or -not $currentUserOid) {
242-
Write-Error "✗ Could not determine current signed-in user. Ensure you are logged in with 'az login'."
271+
# Use previously detected identity for PostgreSQL Entra auth
272+
if (-not $currentIdentityOid -or -not $currentIdentityDisplay) {
273+
Write-Error "✗ Could not determine current identity. Ensure you are logged in with 'az login'."
243274
exit 1
244275
}
245-
Write-Host "✓ Current user: $currentUserUpn ($currentUserOid)"
276+
$currentUserUpn = $currentIdentityDisplay
277+
$currentUserOid = $currentIdentityOid
278+
Write-Host "✓ Current ${identityType}: $currentUserUpn ($currentUserOid)"
246279

247280
# Ensure current user is a PostgreSQL Entra administrator
248281
$existingAdmins = az postgres flexible-server $pgAdminCmd list --resource-group $ResourceGroupName --server-name $serverName --query "[].objectId" -o tsv 2>$null
@@ -254,23 +287,23 @@ else {
254287
}
255288
$addedPgAdmin = $false
256289
if (-not $isAdmin) {
257-
Write-Host "✓ Adding current user as PostgreSQL Entra administrator..."
290+
Write-Host "✓ Adding current ${identityType} as PostgreSQL Entra administrator..."
258291
$adminOutput = az postgres flexible-server $pgAdminCmd create `
259292
--resource-group $ResourceGroupName `
260293
--server-name $serverName `
261294
--display-name $currentUserUpn `
262295
--object-id $currentUserOid `
263-
--type User 2>&1 | Out-String
296+
--type $principalType 2>&1 | Out-String
264297
if ($LASTEXITCODE -ne 0) {
265-
Write-Warning "⚠ Failed to add current user as PostgreSQL admin. Table creation may fail."
298+
Write-Warning "⚠ Failed to add current ${identityType} as PostgreSQL admin. Table creation may fail."
266299
Write-Warning " $adminOutput"
267300
} else {
268301
$addedPgAdmin = $true
269302
Write-Host "✓ PostgreSQL admin added. Waiting 60s for propagation..."
270303
Start-Sleep -Seconds 60
271304
}
272305
} else {
273-
Write-Host "✓ Current user is already a PostgreSQL Entra administrator."
306+
Write-Host "✓ Current ${identityType} is already a PostgreSQL Entra administrator."
274307
}
275308

276309
try {

0 commit comments

Comments
 (0)