Operations
Runbooks & operations
Cron quick reference
| Cron | Job | Gate |
|---|---|---|
*/6 * * * * | reconcile | reconcile_needed.py decides; ingest.py + data_export.py |
*/30 12-21 * * 5,6,0 | reconcile (race ticks) | same, 30-min cadence on race weekends |
0 */2 * * 5,6,0 | charts | charts_todo.py; skip if todo empty; teammate pairs RUS,ANT / NOR,PIA / LEC,HAM |
0 6,12,18 * * 5,6,0 | assets | latest completed round + next; all 8 session codes |
17 7 * * * | digest | free_tier_digest.py → Slack |
*/5 * * * * | queue | process_chart_requests.py + process_telemetry_requests.py |
On-demand runs
gh workflow run pr-ci.yml --ref main # Actions tab → PR CI → Run workflow
python charts_todo.py --season "$(date -u +%Y)" # inspect pending chart work
python index_export.py --season "$(date -u +%Y)" # refresh CDN indexes after manual exports
Custom chart requests
Flow: user picks drivers in Deep Dive → row in f1_chart_requests → minute-cron runs generate.py --only <chart> --drivers <codes> → PNG in analysis_charts → app polls it in. Deduped by stable driver_key (upper · sorted · --joined). Customizable charts: driver_compare, season_scorecard, dominance_flat, track_dominance, parallax_stack, speed_trace, driver_radar (registry: web/src/services/chartRequestService.ts → CUSTOMIZABLE_CHARTS).
Secrets inventory
- CI (Actions secrets):
R2_ACCOUNT_ID,R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY,R2_BUCKET,BLOB_PUBLIC_BASE,SUPABASE_URL,SUPABASE_SERVICE_ROLE_KEY,SLACK_ALERTS_WEBHOOK. - Frontend (Vercel /
.env.example):VITE_SUPABASE_URL,VITE_SUPABASE_PUBLISHABLE_KEY,VITE_SUPABASE_PROJECT_IDrequired;VITE_F1_PROXY_ENABLED,VITE_DB_SERVING_ENABLED, GA4/Clarity/AdSense optional (no-op when unset). - Edge:
BMC_WEBHOOK_SECRETviasupabase secrets set.
Never commit service-role keys. Browser code takes only the publishable/anon key (RLS-protected). Service-role lives in Actions secrets and local shells only.
Failure triage
- Charts job all-calls-failed ⇒ exit 1; partial failures log
FAILED:lines but keep green. Check Jolpica/OpenF1 availability andapi_metricsfor 429s. - Empty upstream right after a session is normal (multi-hour Jolpica lag) — retry with backoff, never mark final.
- 404 = genuinely absent (
empty, stop retrying); 429/5xx/521/522/timeout = transient (retry).