diff --git a/tests/plausible/custom/test_event_tracking.py b/tests/plausible/custom/test_event_tracking.py index bf99cdc..38dda08 100644 --- a/tests/plausible/custom/test_event_tracking.py +++ b/tests/plausible/custom/test_event_tracking.py @@ -14,7 +14,10 @@ Both assert real app state (the event reached the analytics store), not just the plausible only ingests events for *known* sites — the in-memory `sites_cache` gates ingestion and drops events for unregistered domains (empirically confirmed: an event for an unregistered domain -never appears in events_v2). So each test first registers a site row in the metadata postgres, then +never appears in events_v2). From v3 (community-edition) a site is only "known" once it belongs to a +TEAM; a teamless site is dropped as `dropped_not_found` while the POST still acks 202, so the failure +looks like a silent ingestion stall. `_register_site` therefore provisions a team as well when the +schema has one. So each test first registers a site row in the metadata postgres, then POSTs repeatedly while polling ClickHouse: the sites_cache must refresh to admit the new site and the event write-buffer must flush to ClickHouse, so the first landing is not instantaneous. Re-POSTing the same event is safe — we assert the row count is >= 1. @@ -51,11 +54,40 @@ def _ch(domain: str, sql: str) -> str: def _register_site(domain: str, site: str) -> None: - """Insert a site row into the metadata postgres (`db` service) so plausible will ingest events for - it. Idempotent (ON CONFLICT DO NOTHING).""" + """Register `site` in the metadata postgres so plausible will ingest events for it. + + Idempotent. Works against BOTH schema generations, because the upgrade tier deploys an older + base version before upgrading: + + * v2 (`plausible/analytics`) — a row in `sites` is sufficient. + * v3 (`ghcr.io/plausible/community-edition`) — sites belong to a TEAM, and ingestion drops + events for a site whose team is missing. The POST still acks 202 and the row still exists in + postgres, so the only visible symptom is that nothing ever reaches ClickHouse; the reason is + recorded in ClickHouse's own `ingest_counters` as `dropped_not_found`. Verified on cc-ci + against v3.2.1: identical site row, no team → `dropped_not_found`; with a team linked → + `buffered` and the row appears in `events_v2`. + + The team block is guarded on the schema actually having teams, so this stays a no-op on v2 + rather than branching on a version string. + """ sql = ( "INSERT INTO sites (domain, timezone, inserted_at, updated_at, native_stats_start_at) " f"VALUES ('{site}','UTC', now(), now(), now()) ON CONFLICT (domain) DO NOTHING; " + "DO $ccci$ " + "BEGIN " + " IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'teams') " + " AND EXISTS (SELECT 1 FROM information_schema.columns " + " WHERE table_name = 'sites' AND column_name = 'team_id') THEN " + " INSERT INTO teams (name, inserted_at, updated_at, accept_traffic_until, setup_complete) " + " SELECT 'cc-ci', now(), now(), now() + interval '365 days', true " + " WHERE NOT EXISTS (SELECT 1 FROM teams WHERE name = 'cc-ci'); " + " UPDATE sites " + " SET team_id = COALESCE(team_id, (SELECT id FROM teams WHERE name = 'cc-ci' LIMIT 1)), " + " accept_traffic_until = COALESCE(accept_traffic_until, now() + interval '365 days') " + f" WHERE domain = '{site}'; " + " END IF; " + "END " + "$ccci$; " f"SELECT domain FROM sites WHERE domain = '{site}';" ) out = lifecycle.exec_in_app( diff --git a/tests/plausible/custom/test_health_check.py b/tests/plausible/custom/test_health_check.py index c2db0a3..4f12fcc 100644 --- a/tests/plausible/custom/test_health_check.py +++ b/tests/plausible/custom/test_health_check.py @@ -17,6 +17,12 @@ def test_plausible_root_serves(live_app): 62-char SECRET_KEY_BASE, see recipe_meta.EXTRA_ENV); the dedicated /api/health endpoint is. """ + # The custom tier runs AFTER the backup/restore tier, which disrupts postgres under the app and + # restarts it. v3 (community-edition) then boots through `sleep 10` + `db createdb` + `db migrate` + # + cache warmers before /api/health flips to 200, which does not fit in 60s — that is what put + # this recipe RED on build 1224 while install/upgrade/backup/restore all passed. The assertion is + # unchanged (still a hard 200 from the real readiness endpoint); only the wait matches the boot + # profile the recipe already declares via recipe_meta.HTTP_TIMEOUT (1200). url = f"https://{live_app}/api/health" - status, _ = harness_http.retry_http_get(url, expect_status=(200,), max_wait=60, interval=3) + status, _ = harness_http.retry_http_get(url, expect_status=(200,), max_wait=300, interval=5) assert status == 200, f"GET {url} HTTP {status}"