Skip to content

Commit 48b9198

Browse files
committed
feat(session-28): Add L33-L35 production data + deployment script
- agent_policies.json: 4 agent policies (copilot, sprint-agent, veritas-audit, control-plane) - quality_gates.json: 4 project quality gates (51-ACA, 37-data-model, 07-foundation, 48-eva-veritas) - github_rules.json: 4 branch protection configs (main branch rules per project) - deploy-to-msub.ps1: Simplified single-ACR deployment script Data files force-added (override .gitignore) as these are source data, not Cosmos exports. Closes #14 (L33-L35 production data seeding)
1 parent 3648197 commit 48b9198

File tree

4 files changed

+772
-0
lines changed

4 files changed

+772
-0
lines changed

deploy-to-msub.ps1

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
#!/usr/bin/env pwsh
2+
<#
3+
.SYNOPSIS
4+
Deploy 37-data-model to msub-eva-data-model Container App (2-subscription deployment).
5+
6+
.DESCRIPTION
7+
Step 1: Build image in target ACR (msubsandacr202603031449) under MarcoSub subscription
8+
Step 2: Update Container App (msub-eva-data-model) to new image
9+
Step 3: Verify deployment (health check, agent-summary, L33-L35 endpoints)
10+
11+
.PARAMETER Tag
12+
Image tag (default: date-time stamp like 20260306-0900)
13+
14+
.PARAMETER SkipBuild
15+
Skip ACR build (use existing image)
16+
17+
.PARAMETER SkipVerify
18+
Skip post-deployment verification
19+
20+
.EXAMPLE
21+
.\deploy-to-msub.ps1
22+
# Builds and deploys with auto-generated tag
23+
24+
.EXAMPLE
25+
.\deploy-to-msub.ps1 -Tag "session-28-pr12"
26+
# Deploys with custom tag
27+
28+
.EXAMPLE
29+
.\deploy-to-msub.ps1 -SkipBuild -Tag "20260305-2022"
30+
# Deploys existing image without rebuilding
31+
#>
32+
33+
param(
34+
[string]$Tag = "",
35+
[switch]$SkipBuild,
36+
[switch]$SkipVerify
37+
)
38+
39+
Set-StrictMode -Version Latest
40+
$ErrorActionPreference = "Stop"
41+
42+
# ── Configuration ──────────────────────────────────────────────────────────────
43+
$SOURCE_SUBSCRIPTION = "e5ca0637-198e-4ff9-bc6a-30dcb8f1f8f1" # DevEval
44+
$TARGET_SUBSCRIPTION = "c59ee575-eb2a-4b51-a865-4b618f9add0a" # MarcoSub
45+
46+
$SOURCE_ACR = "marcoeva"
47+
$TARGET_ACR = "msubsandacr202603031449"
48+
$IMAGE_NAME = "eva/eva-data-model"
49+
50+
$CONTAINER_APP = "msub-eva-data-model"
51+
$RESOURCE_GROUP = "EVA-Sandbox-dev"
52+
$CLOUD_URL = "https://msub-eva-data-model.victoriousgrass-30debbd3.canadacentral.azurecontainerapps.io"
53+
54+
# ── Helper Functions ───────────────────────────────────────────────────────────
55+
function Write-Step {
56+
param([string]$Message)
57+
Write-Host "`n━━━ $Message ━━━" -ForegroundColor Cyan
58+
}
59+
60+
function Write-Success {
61+
param([string]$Message)
62+
Write-Host "$Message" -ForegroundColor Green
63+
}
64+
65+
function Write-Info {
66+
param([string]$Message)
67+
Write-Host " $Message" -ForegroundColor Gray
68+
}
69+
70+
function Write-Warn {
71+
param([string]$Message)
72+
Write-Host "$Message" -ForegroundColor Yellow
73+
}
74+
75+
function Write-Error-Message {
76+
param([string]$Message)
77+
Write-Host "$Message" -ForegroundColor Red
78+
}
79+
80+
# ── Generate Tag if not provided ───────────────────────────────────────────────
81+
if (-not $Tag) {
82+
$timestamp = Get-Date -Format "yyyyMMdd-HHmm"
83+
$Tag = $timestamp
84+
Write-Info "Auto-generated tag: $Tag"
85+
}
86+
87+
$FULL_IMAGE = "${IMAGE_NAME}:${Tag}"
88+
Write-Info "Image: $FULL_IMAGE"
89+
90+
# ── STEP 1: Build in Target ACR (Simplified - Single Subscription) ────────────
91+
if (-not $SkipBuild) {
92+
Write-Step "Step 1: Build image in target ACR ($TARGET_ACR)"
93+
94+
Write-Info "Switching to MarcoSub subscription..."
95+
az account set --subscription $TARGET_SUBSCRIPTION
96+
97+
$currentSub = az account show --query name -o tsv
98+
Write-Info "Current subscription: $currentSub"
99+
100+
Write-Info "Building Docker image in ACR..."
101+
Write-Info "Command: az acr build --registry $TARGET_ACR --image $FULL_IMAGE --file Dockerfile ."
102+
103+
$buildStartTime = Get-Date
104+
az acr build --registry $TARGET_ACR --image $FULL_IMAGE --file Dockerfile .
105+
106+
if ($LASTEXITCODE -ne 0) {
107+
Write-Error-Message "ACR build failed with exit code $LASTEXITCODE"
108+
exit 1
109+
}
110+
111+
$buildDuration = (Get-Date) - $buildStartTime
112+
Write-Success "Image built successfully in $([int]$buildDuration.TotalSeconds)s"
113+
Write-Info "Image: ${TARGET_ACR}.azurecr.io/${FULL_IMAGE}"
114+
115+
# Verify image exists in ACR
116+
Write-Info "Verifying image in ACR..."
117+
$tags = az acr repository show-tags --name $TARGET_ACR --repository $IMAGE_NAME --output json | ConvertFrom-Json
118+
119+
if ($tags -contains $Tag) {
120+
Write-Success "Image verified in ACR: ${TARGET_ACR}.azurecr.io/${FULL_IMAGE}"
121+
} else {
122+
Write-Error-Message "Image not found in ACR after build"
123+
exit 1
124+
}
125+
} else {
126+
Write-Warn "Skipping build (using existing image: $FULL_IMAGE)"
127+
}
128+
129+
# ── STEP 2: Update Container App ──────────────────────────────────────────────
130+
Write-Step "Step 2: Update Container App ($CONTAINER_APP)"
131+
132+
Write-Info "Updating Container App to new image..."
133+
Write-Info "Command: az containerapp update --name $CONTAINER_APP --resource-group $RESOURCE_GROUP --image ${TARGET_ACR}.azurecr.io/${FULL_IMAGE}"
134+
135+
az containerapp update `
136+
--name $CONTAINER_APP `
137+
--resource-group $RESOURCE_GROUP `
138+
--image "${TARGET_ACR}.azurecr.io/${FULL_IMAGE}"
139+
140+
if ($LASTEXITCODE -ne 0) {
141+
Write-Error-Message "Container App update failed with exit code $LASTEXITCODE"
142+
exit 1
143+
}
144+
145+
Write-Success "Container App updated successfully"
146+
147+
# Get new revision name
148+
$revision = az containerapp revision list `
149+
--name $CONTAINER_APP `
150+
--resource-group $RESOURCE_GROUP `
151+
--query "[0].name" `
152+
--output tsv
153+
154+
Write-Info "New revision: $revision"
155+
156+
# ── STEP 3: Verify Deployment ─────────────────────────────────────────────────
157+
if (-not $SkipVerify) {
158+
Write-Step "Step 3: Verify Deployment"
159+
160+
Write-Info "Waiting 60 seconds for Container App to restart..."
161+
Start-Sleep -Seconds 60
162+
163+
# Health check
164+
Write-Info "Testing health endpoint..."
165+
try {
166+
$health = Invoke-RestMethod "$CLOUD_URL/health" -ErrorAction Stop
167+
$uptime = $health.uptime_seconds
168+
169+
if ($uptime -lt 120) {
170+
Write-Success "Health check PASS (uptime: ${uptime}s - recently restarted)"
171+
} else {
172+
Write-Warn "Health check PASS but uptime unexpected (${uptime}s - may not have restarted)"
173+
}
174+
} catch {
175+
Write-Error-Message "Health check FAILED: $_"
176+
exit 1
177+
}
178+
179+
# Agent summary check
180+
Write-Info "Testing agent-summary endpoint..."
181+
try {
182+
$summary = Invoke-RestMethod "$CLOUD_URL/model/agent-summary" -ErrorAction Stop
183+
$layerCount = ($summary.layers.PSObject.Properties | Measure-Object).Count
184+
$evidenceCount = $summary.layers.evidence
185+
186+
Write-Success "Agent summary PASS"
187+
Write-Info " Layers: $layerCount"
188+
Write-Info " Evidence: $evidenceCount"
189+
190+
# Check for Session 28 layers (L33-L35)
191+
$hasL33 = $null -ne $summary.layers.agent_policies
192+
$hasL34 = $null -ne $summary.layers.quality_gates
193+
$hasL35 = $null -ne $summary.layers.github_rules
194+
195+
if ($hasL33 -and $hasL34 -and $hasL35) {
196+
Write-Success "Session 28 layers detected (L33-L35: ✓)"
197+
Write-Info " L33 agent_policies: $($summary.layers.agent_policies) objects"
198+
Write-Info " L34 quality_gates: $($summary.layers.quality_gates) objects"
199+
Write-Info " L35 github_rules: $($summary.layers.github_rules) objects"
200+
} else {
201+
Write-Warn "Session 28 layers NOT detected"
202+
Write-Info " L33 agent_policies: $(if($hasL33){''}else{''})"
203+
Write-Info " L34 quality_gates: $(if($hasL34){''}else{''})"
204+
Write-Info " L35 github_rules: $(if($hasL35){''}else{''})"
205+
}
206+
} catch {
207+
Write-Error-Message "Agent summary check FAILED: $_"
208+
exit 1
209+
}
210+
211+
# Test L33-L35 endpoints
212+
Write-Info "Testing Session 28 endpoints..."
213+
214+
$endpoints = @(
215+
"/model/agent_policies/",
216+
"/model/quality_gates/",
217+
"/model/github_rules/"
218+
)
219+
220+
$passCount = 0
221+
$failCount = 0
222+
223+
foreach ($endpoint in $endpoints) {
224+
try {
225+
$response = Invoke-RestMethod "$CLOUD_URL$endpoint" -ErrorAction Stop
226+
$count = ($response.data | Measure-Object).Count
227+
Write-Success " $endpoint → 200 OK ($count objects)"
228+
$passCount++
229+
} catch {
230+
Write-Error-Message " $endpoint → FAILED: $_"
231+
$failCount++
232+
}
233+
}
234+
235+
if ($failCount -eq 0) {
236+
Write-Success "All Session 28 endpoints operational ($passCount/$($endpoints.Count))"
237+
} else {
238+
Write-Warn "Some endpoints failed ($passCount/$($endpoints.Count) passed, $failCount failed)"
239+
}
240+
241+
} else {
242+
Write-Warn "Skipping verification (use -SkipVerify to skip)"
243+
}
244+
245+
# ── Summary ────────────────────────────────────────────────────────────────────
246+
Write-Step "Deployment Complete"
247+
Write-Success "Image: ${TARGET_ACR}.azurecr.io/${FULL_IMAGE}"
248+
Write-Success "Container App: $CONTAINER_APP (revision: $revision)"
249+
Write-Success "Cloud URL: $CLOUD_URL"
250+
251+
Write-Host "`nNext steps:" -ForegroundColor Cyan
252+
Write-Host " 1. Test endpoints manually: $CLOUD_URL/model/agent-guide" -ForegroundColor Gray
253+
Write-Host " 2. Update STATUS.md with deployment timestamp" -ForegroundColor Gray
254+
Write-Host " 3. Monitor Container App logs: az containerapp logs show -n $CONTAINER_APP -g $RESOURCE_GROUP --follow" -ForegroundColor Gray
255+
256+
exit 0

0 commit comments

Comments
 (0)