Skip to content

Commit 48e62c8

Browse files
authored
Merge branch 'main' into staging
2 parents 2876904 + 0958c86 commit 48e62c8

5 files changed

Lines changed: 95 additions & 7 deletions

File tree

.dev/rebuild-cache.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import { createClient } from '@supabase/supabase-js'
2020
import { config } from 'dotenv'
2121
import { execSync } from 'child_process'
22+
import { readFileSync, existsSync } from 'fs'
23+
import { resolve, dirname } from 'path'
24+
import { fileURLToPath } from 'url'
2225
import area from '@turf/area'
2326

2427
// Load .env file for local development (GitHub Actions sets env vars directly)
@@ -162,6 +165,47 @@ async function rebuildCache() {
162165
console.log('⚙️ Processing service areas...')
163166
const serviceAreas = buildServiceAreasFromEvents(events, geometryMap)
164167

168+
// STEP 3.5: Load news.csv if it exists
169+
console.log('📰 Loading news data...')
170+
let newsItems = []
171+
try {
172+
const __dirname = dirname(fileURLToPath(import.meta.url))
173+
const newsPath = resolve(__dirname, '..', 'news.csv')
174+
if (existsSync(newsPath)) {
175+
const newsCSV = readFileSync(newsPath, 'utf-8')
176+
const lines = newsCSV.trim().split('\n')
177+
if (lines.length > 1) {
178+
const header = lines[0].split(',')
179+
for (let i = 1; i < lines.length; i++) {
180+
const line = lines[i].trim()
181+
if (!line) continue
182+
// Simple CSV parse (handles quoted fields)
183+
const fields = []
184+
let current = '', inQuotes = false
185+
for (let j = 0; j < line.length; j++) {
186+
const ch = line[j]
187+
if (inQuotes) {
188+
if (ch === '"' && line[j + 1] === '"') { current += '"'; j++ }
189+
else if (ch === '"') { inQuotes = false }
190+
else { current += ch }
191+
} else {
192+
if (ch === '"') { inQuotes = true }
193+
else if (ch === ',') { fields.push(current); current = '' }
194+
else { current += ch }
195+
}
196+
}
197+
fields.push(current)
198+
const newsItem = {}
199+
header.forEach((col, idx) => { newsItem[col.trim()] = (fields[idx] || '').trim() })
200+
if (newsItem.headline) newsItems.push(newsItem)
201+
}
202+
}
203+
}
204+
console.log(` Found ${newsItems.length} news items`)
205+
} catch (err) {
206+
console.warn('⚠️ Failed to load news.csv:', err.message)
207+
}
208+
165209
// STEP 4: Create final data structure
166210
// Transform geometries to camelCase for frontend
167211
const geometriesForFrontend = geometriesWithData.map(geo => ({
@@ -188,6 +232,7 @@ async function rebuildCache() {
188232
}
189233
},
190234
events: events,
235+
news: newsItems,
191236
geometries: geometriesForFrontend,
192237
service_areas: serviceAreas,
193238
date_range: {

.dev/schema.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
"access_policy_changed",
3232
"service_model_updated",
3333
"platform_updated",
34-
"fleet_partner_changed"
34+
"fleet_partner_changed",
35+
"direct_booking_updated"
3536
],
3637
"description": "Type of event"
3738
},
@@ -210,6 +211,10 @@
210211
"fleet_partner_changed": {
211212
"requiredFields": ["company", "city", "fleet_partner"],
212213
"description": "Fleet management partner change"
214+
},
215+
"direct_booking_updated": {
216+
"requiredFields": ["company", "city", "direct_booking"],
217+
"description": "Direct booking availability change"
213218
}
214219
},
215220

.github/workflows/deploy-data.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ on:
55
branches: [main, staging]
66
paths:
77
- 'events.csv'
8+
- 'news.csv'
89
- 'geometries/**'
910

1011
pull_request:
1112
branches: [main, staging]
1213
paths:
1314
- 'events.csv'
15+
- 'news.csv'
1416
- 'geometries/**'
1517

1618
workflow_dispatch:

LIVE_SURFACE.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Live Surface: av-map-data
2+
3+
This file documents the currently active production surface area for the `av-map-data` repo.
4+
5+
## Production Entrypoints
6+
7+
- Canonical data files:
8+
- `events.csv`
9+
- `geometries/*.geojson`
10+
- CI pipeline: `.github/workflows/deploy-data.yml`
11+
12+
## Active Runtime Flow
13+
14+
1. `validate` job runs `pytest tests/ -v`
15+
2. `update-cache` job runs on non-PR events after validation
16+
3. CSV import: `.dev/import-csv.py`
17+
4. Geometry upload: `.dev/upload-geometries.js`
18+
5. Geometry metadata sync: `.dev/sync-geometries-table.js`
19+
6. Cache rebuild and upload: `.dev/rebuild-cache.js`
20+
21+
## Critical Dependencies
22+
23+
- GitHub Actions for validation and publish automation
24+
- Supabase database tables (`av_events*`, geometry metadata tables)
25+
- Supabase storage buckets (cache + geometry buckets)
26+
- Python 3.11 + Node 20 in CI
27+
28+
## Active Environment Variables
29+
30+
- `SUPABASE_URL`
31+
- `SUPABASE_SERVICE_KEY`
32+
- `STAGING` (controls staging vs production target)
33+
- `GITHUB_ACTIONS` (CI behavior toggle)
34+
35+
## Source of Truth for Data Contract
36+
37+
- Schema contract: `.dev/schema.json`
38+
- Validation tests: `tests/test_validation.py`
39+
- Contributor guidance: `CONTRIBUTING.md`
40+
41+
These three must remain aligned for event types, required fields, and geometry naming rules.

tests/test_validation.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,7 @@ def test_date_format(csv_file):
8585

8686
def test_event_types(csv_file):
8787
"""Test that event types are valid."""
88-
valid_event_types = [
89-
'service_created', 'service_ended', 'geometry_updated',
90-
'vehicle_types_updated', 'supervision_updated', 'fares_policy_changed',
91-
'access_policy_changed', 'service_model_updated', 'platform_updated', 'fleet_partner_changed',
92-
'direct_booking_updated', 'service_testing', 'service_announced'
93-
]
88+
valid_event_types = get_event_types()
9489
errors = []
9590

9691
with open(csv_file, 'r') as f:

0 commit comments

Comments
 (0)