-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRUN_LOCAL.ps1
More file actions
308 lines (261 loc) · 12.6 KB
/
RUN_LOCAL.ps1
File metadata and controls
308 lines (261 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
<#
.SYNOPSIS
Runs all SQL pipelines against the LOCAL Supabase database.
.DESCRIPTION
Executes every pipeline SQL file in the correct order against:
postgresql://postgres:postgres@127.0.0.1:54322/postgres
This script is SAFE to run repeatedly (all pipelines are idempotent).
It does NOT touch the remote Supabase instance.
.NOTES
Prerequisites:
- Docker Desktop running with local Supabase containers
- Local Supabase started: supabase start
- No psql installation required (uses docker exec)
Usage:
.\RUN_LOCAL.ps1
.\RUN_LOCAL.ps1 -Category chips
.\RUN_LOCAL.ps1 -DryRun
.\RUN_LOCAL.ps1 -RunQA
.\RUN_LOCAL.ps1 -Category chips -RunQA
.\RUN_LOCAL.ps1 -Enrich
.\RUN_LOCAL.ps1 -Enrich -RunQA
#>
[CmdletBinding()]
param(
[Parameter(HelpMessage = "Run only a specific category pipeline (e.g., 'chips', 'zabka'). If omitted, runs all.")]
[string]$Category = "",
[Parameter(HelpMessage = "Print the SQL files that would be executed without running them.")]
[switch]$DryRun,
[Parameter(HelpMessage = "Run the full QA suite (via RUN_QA.ps1) after pipeline execution.")]
[switch]$RunQA,
[Parameter(HelpMessage = "Run ingredient/allergen enrichment via enrich_ingredients.py after pipeline execution. Requires internet (OFF API).")]
[switch]$Enrich
)
# ─── Configuration ───────────────────────────────────────────────────────────
$CONTAINER = "supabase_db_tryvit"
$DB_NAME = "postgres"
$DB_USER = "postgres"
$PIPELINE_ROOT = Join-Path $PSScriptRoot "db" "pipelines"
# ─── Preflight Checks ───────────────────────────────────────────────────────
Write-Host ""
Write-Host "================================================" -ForegroundColor Cyan
Write-Host " TryVit — Local Pipeline Runner" -ForegroundColor Cyan
Write-Host "================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host " Target: LOCAL (docker exec $CONTAINER)" -ForegroundColor Green
Write-Host ""
# Check Docker is available
$dockerCmd = Get-Command docker -ErrorAction SilentlyContinue
if (-not $dockerCmd) {
Write-Host "ERROR: docker not found on PATH." -ForegroundColor Red
Write-Host "Install Docker Desktop from https://www.docker.com/products/docker-desktop/" -ForegroundColor Yellow
exit 1
}
# Test connection via docker exec
Write-Host "Testing database connection..." -ForegroundColor Yellow
try {
$testResult = docker exec $CONTAINER psql -U $DB_USER -d $DB_NAME -c "SELECT 1;" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Cannot connect to local database." -ForegroundColor Red
Write-Host "Is Docker running? Is Supabase started? (supabase start)" -ForegroundColor Yellow
Write-Host "Output: $testResult" -ForegroundColor DarkGray
exit 1
}
Write-Host "Connection OK." -ForegroundColor Green
}
catch {
Write-Host "ERROR: docker exec failed — $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# ─── Discover Pipeline Files ────────────────────────────────────────────────
if (-not (Test-Path $PIPELINE_ROOT)) {
Write-Host "ERROR: Pipeline root not found: $PIPELINE_ROOT" -ForegroundColor Red
exit 1
}
# Get category folders
if ($Category -ne "") {
$categoryPath = Join-Path $PIPELINE_ROOT $Category
if (-not (Test-Path $categoryPath)) {
Write-Host "ERROR: Category folder not found: $categoryPath" -ForegroundColor Red
Write-Host "Available categories:" -ForegroundColor Yellow
Get-ChildItem -Path $PIPELINE_ROOT -Directory | ForEach-Object { Write-Host " - $($_.Name)" -ForegroundColor Yellow }
exit 1
}
$categoryFolders = @(Get-Item $categoryPath)
}
else {
$categoryFolders = Get-ChildItem -Path $PIPELINE_ROOT -Directory | Sort-Object Name
}
# Collect all SQL files in execution order
$allFiles = @()
foreach ($folder in $categoryFolders) {
$sqlFiles = Get-ChildItem -Path $folder.FullName -Filter "PIPELINE__*.sql" | Sort-Object Name
if ($sqlFiles.Count -eq 0) {
Write-Host " SKIP: $($folder.Name) (no pipeline files)" -ForegroundColor DarkGray
continue
}
foreach ($file in $sqlFiles) {
$allFiles += $file
}
}
if ($allFiles.Count -eq 0) {
Write-Host "No pipeline files found to execute." -ForegroundColor Yellow
exit 0
}
# ─── Execution ──────────────────────────────────────────────────────────────
Write-Host ""
Write-Host "Pipeline files to execute ($($allFiles.Count) total):" -ForegroundColor Cyan
Write-Host "─────────────────────────────────────────────────" -ForegroundColor DarkGray
$currentCategory = ""
foreach ($file in $allFiles) {
$cat = $file.Directory.Name
if ($cat -ne $currentCategory) {
Write-Host ""
Write-Host " [$cat]" -ForegroundColor Magenta
$currentCategory = $cat
}
Write-Host " $($file.Name)" -ForegroundColor White
}
Write-Host ""
if ($DryRun) {
Write-Host "DRY RUN — no SQL was executed." -ForegroundColor Yellow
exit 0
}
# Execute each file
$successCount = 0
$failCount = 0
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
foreach ($file in $allFiles) {
$relativePath = $file.FullName.Replace($PSScriptRoot, "").TrimStart("\", "/")
# Show batch progress for batched pipeline files
$batchLabel = ""
if ($file.Name -match '_batch_(\d{3})_') {
$batchNum = $Matches[1]
$stepPrefix = ($file.Name -split '_batch_')[0]
$totalBatches = @($allFiles | Where-Object { $_.Name -like "$stepPrefix*_batch_*" }).Count
$batchLabel = " [batch $batchNum/$totalBatches]"
}
Write-Host " RUN $relativePath$batchLabel" -ForegroundColor Yellow -NoNewline
$sqlContent = Get-Content $file.FullName -Raw
$output = $sqlContent | docker exec -i $CONTAINER psql -U $DB_USER -d $DB_NAME --single-transaction -v ON_ERROR_STOP=1 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓" -ForegroundColor Green
$successCount++
}
else {
Write-Host " ✗ FAILED" -ForegroundColor Red
Write-Host " $output" -ForegroundColor DarkRed
$failCount++
# Stop on first error to prevent cascading failures
Write-Host ""
Write-Host "ABORTED: Stopping pipeline due to error." -ForegroundColor Red
break
}
}
$stopwatch.Stop()
# ─── Summary ────────────────────────────────────────────────────────────────
Write-Host ""
Write-Host "================================================" -ForegroundColor Cyan
Write-Host " Execution Summary" -ForegroundColor Cyan
Write-Host "================================================" -ForegroundColor Cyan
Write-Host " Succeeded: $successCount" -ForegroundColor Green
Write-Host " Failed: $failCount" -ForegroundColor $(if ($failCount -gt 0) { "Red" } else { "Green" })
Write-Host " Duration: $($stopwatch.Elapsed.TotalSeconds.ToString('F1'))s" -ForegroundColor White
Write-Host " Target: LOCAL (docker exec $CONTAINER)" -ForegroundColor Green
Write-Host ""
if ($failCount -gt 0) {
exit 1
}
# ─── Refresh Materialized Views ─────────────────────────────────────────────────────
Write-Host "Refreshing materialized views..." -ForegroundColor Yellow
$mvOutput = "SELECT refresh_all_materialized_views();" | docker exec -i $CONTAINER psql -U $DB_USER -d $DB_NAME 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓ All materialized views refreshed" -ForegroundColor Green
}
else {
Write-Host " ⚠ MV refresh failed (non-blocking): $mvOutput" -ForegroundColor DarkYellow
}
# ─── Ingredient/Allergen Enrichment (optional) ─────────────────────────────────────
if ($Enrich) {
Write-Host ""
Write-Host "================================================" -ForegroundColor Cyan
Write-Host " Ingredient & Allergen Enrichment" -ForegroundColor Cyan
Write-Host "================================================" -ForegroundColor Cyan
Write-Host ""
$enrichScript = Join-Path $PSScriptRoot "enrich_ingredients.py"
$postEnrichSql = Join-Path $PSScriptRoot "db" "ci_post_enrichment.sql"
$pythonExe = Join-Path $PSScriptRoot ".venv" "Scripts" "python.exe"
if (-not (Test-Path $enrichScript)) {
Write-Host "ERROR: enrich_ingredients.py not found: $enrichScript" -ForegroundColor Red
exit 1
}
if (-not (Test-Path $pythonExe)) {
Write-Host "ERROR: Python venv not found: $pythonExe" -ForegroundColor Red
Write-Host "Create it with: python -m venv .venv && .\.venv\Scripts\pip install -r requirements.txt" -ForegroundColor Yellow
exit 1
}
# Step 1: Run enrichment script (fetches from OFF API, generates migration SQL)
Write-Host "Step 1: Fetching ingredient data from OFF API..." -ForegroundColor Yellow
$env:PYTHONIOENCODING = "utf-8"
& $pythonExe $enrichScript
if ($LASTEXITCODE -ne 0) {
Write-Host "WARNING: Enrichment script exited with errors (some products may not have been enriched)." -ForegroundColor DarkYellow
Write-Host " This is expected — not all products are on Open Food Facts." -ForegroundColor DarkGray
}
# Step 2: Apply the generated migration
$enrichMigrations = Get-ChildItem -Path (Join-Path $PSScriptRoot "supabase" "migrations") -Filter "*populate_ingredients_allergens*" | Sort-Object Name | Select-Object -Last 1
if ($enrichMigrations) {
Write-Host "Step 2: Applying enrichment migration: $($enrichMigrations.Name)..." -ForegroundColor Yellow
$output = Get-Content $enrichMigrations.FullName -Raw | docker exec -i $CONTAINER psql -U $DB_USER -d $DB_NAME -v ON_ERROR_STOP=1 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓ Enrichment migration applied" -ForegroundColor Green
}
else {
Write-Host " ✗ Enrichment migration FAILED" -ForegroundColor Red
Write-Host " $($output | Select-Object -Last 5)" -ForegroundColor DarkRed
exit 1
}
}
else {
Write-Host " ⚠ No enrichment migration found — skipping apply step." -ForegroundColor DarkYellow
}
# Step 3: Compute concern scores and re-score all categories
if (Test-Path $postEnrichSql) {
Write-Host "Step 3: Computing concern scores and re-scoring all categories..." -ForegroundColor Yellow
$output = Get-Content $postEnrichSql -Raw | docker exec -i $CONTAINER psql -U $DB_USER -d $DB_NAME -v ON_ERROR_STOP=1 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓ Post-enrichment scoring complete" -ForegroundColor Green
}
else {
Write-Host " ✗ Post-enrichment scoring FAILED" -ForegroundColor Red
Write-Host " $($output | Select-Object -Last 5)" -ForegroundColor DarkRed
exit 1
}
}
# Step 4: Refresh materialized views
Write-Host "Step 4: Refreshing materialized views..." -ForegroundColor Yellow
$mvOutput = "SELECT refresh_all_materialized_views();" | docker exec -i $CONTAINER psql -U $DB_USER -d $DB_NAME 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Host " ✓ All materialized views refreshed" -ForegroundColor Green
}
else {
Write-Host " ⚠ MV refresh failed (non-blocking): $mvOutput" -ForegroundColor DarkYellow
}
Write-Host ""
Write-Host "Enrichment complete." -ForegroundColor Green
}
# ─── QA Checks (optional) ──────────────────────────────────────────────────────────
if ($RunQA) {
$qaScript = Join-Path $PSScriptRoot "RUN_QA.ps1"
if (-not (Test-Path $qaScript)) {
Write-Host "WARNING: RUN_QA.ps1 not found: $qaScript" -ForegroundColor Yellow
}
else {
Write-Host ""
& $qaScript
if ($LASTEXITCODE -ne 0) {
exit 1
}
}
}
exit 0