plausible's custom tier has been RED since the v3 upgrade PR
(plausible#5), most recently on
build 1224. install, upgrade, backup and restore all pass; only the three custom tests fail.
Both causes are in the tests, not the recipe.
1. v3 only ingests events for a site that belongs to a TEAM
_register_site inserted a row into sites and nothing else. That was sufficient for v2
(plausible/analytics). Under v3 (ghcr.io/plausible/community-edition) a teamless site is not
"known" to the ingestion path, so every event is discarded — while POST /api/event still returns 202 and the postgres row still exists. The only visible symptom is that nothing ever reaches
ClickHouse, which reads as a silent ingestion stall:
AssertionError: event name='pageview' pathname='/ccci-pageview-roundtrip' ... never reached
ClickHouse events_v2 within 210s (last POST status=202, last count=0)
ClickHouse records the real reason itself, in ingest_counters. Verified on cc-ci against v3.2.1,
same site row both times:
site state
ingest_counters
events_v2
no team (what the test did)
dropped_not_found
0
team linked
buffered
rows land
_register_site now provisions a team and links the site. The block is guarded on the schema
actually having teams + sites.team_id, so it is a no-op on v2 — which matters because the
upgrade tier deploys the older base version first.
2. The post-restore health wait was too short for v3
test_plausible_root_serves waited 60s for /api/health. The custom tier runs after
backup/restore, which disrupts postgres under the app and restarts it, and v3 boots through sleep 10 → db createdb → db migrate → cache warmers before health flips to 200. Widened to 300s, still far inside the recipe's own declared HTTP_TIMEOUT = 1200.
What this does NOT do
Neither change weakens an assertion. The event tests still require the row to arrive in ClickHouse and match what was sent (name, pathname, hostname); the health test still requires a hard 200
from the real readiness endpoint. Only the fixture and the wait changed.
Verification
Full cold suite against the recipe PR head (upgrade-4.0.0+v3.2.1, 867ebfaf) with this branch:
install : pass upgrade : pass backup : pass restore : pass custom : pass
level=5 of 5
VERDICT: GREEN
All three previously-failing tests pass: test_pageview_event_roundtrip, test_custom_event_roundtrip, test_plausible_root_serves.
Dependent pair
This is the CI half of a pair. !testme on plausible#5 runs the deployed cc-ci tests, so that PR
stays RED until this one merges. Merge this first, then re-run !testme there.
Not merged by automation — for operator review.
## What
`plausible`'s custom tier has been RED since the v3 upgrade PR
([plausible#5](https://git.autonomic.zone/recipe-maintainers/plausible/pulls/5)), most recently on
build 1224. `install`, `upgrade`, `backup` and `restore` all pass; only the three custom tests fail.
Both causes are in the tests, not the recipe.
### 1. v3 only ingests events for a site that belongs to a TEAM
`_register_site` inserted a row into `sites` and nothing else. That was sufficient for v2
(`plausible/analytics`). Under v3 (`ghcr.io/plausible/community-edition`) a teamless site is not
"known" to the ingestion path, so every event is discarded — while `POST /api/event` still returns
**202** and the postgres row still exists. The only visible symptom is that nothing ever reaches
ClickHouse, which reads as a silent ingestion stall:
```
AssertionError: event name='pageview' pathname='/ccci-pageview-roundtrip' ... never reached
ClickHouse events_v2 within 210s (last POST status=202, last count=0)
```
ClickHouse records the real reason itself, in `ingest_counters`. Verified on cc-ci against v3.2.1,
same site row both times:
| site state | `ingest_counters` | `events_v2` |
|---|---|---|
| no team (what the test did) | `dropped_not_found` | 0 |
| team linked | `buffered` | rows land |
`_register_site` now provisions a team and links the site. The block is guarded on the schema
actually having `teams` + `sites.team_id`, so it is a **no-op on v2** — which matters because the
upgrade tier deploys the older base version first.
### 2. The post-restore health wait was too short for v3
`test_plausible_root_serves` waited **60s** for `/api/health`. The custom tier runs *after*
backup/restore, which disrupts postgres under the app and restarts it, and v3 boots through
`sleep 10` → `db createdb` → `db migrate` → cache warmers before health flips to 200. Widened to
**300s**, still far inside the recipe's own declared `HTTP_TIMEOUT = 1200`.
## What this does NOT do
Neither change weakens an assertion. The event tests still require the row to arrive in ClickHouse
**and** match what was sent (name, pathname, hostname); the health test still requires a hard `200`
from the real readiness endpoint. Only the fixture and the wait changed.
## Verification
Full cold suite against the recipe PR head (`upgrade-4.0.0+v3.2.1`, `867ebfaf`) with this branch:
```
install : pass upgrade : pass backup : pass restore : pass custom : pass
level=5 of 5
VERDICT: GREEN
```
All three previously-failing tests pass:
`test_pageview_event_roundtrip`, `test_custom_event_roundtrip`, `test_plausible_root_serves`.
## Dependent pair
This is the CI half of a pair. `!testme` on plausible#5 runs the **deployed** cc-ci tests, so that PR
stays RED until this one merges. Merge this first, then re-run `!testme` there.
Not merged by automation — for operator review.
plausible v3 (community-edition) only ingests events for a site that belongs to
a TEAM. The custom tier registered a site row and nothing else, which was enough
for v2 — under v3 the POST still acks 202 and the row still exists in postgres,
but every event is discarded. ClickHouse records the reason itself in
ingest_counters as dropped_not_found, and events_v2 stays empty, so it presents
as a silent ingestion stall.
Verified on cc-ci against v3.2.1: identical site row with no team ->
dropped_not_found and 0 rows; with a team linked -> buffered and the rows land.
_register_site now provisions a team and links the site, guarded on the schema
actually having teams so it stays a no-op on v2 (the upgrade tier deploys the
older base first).
Separately, the custom health check waited 60s for /api/health. That tier runs
after backup/restore, which disrupts postgres under the app and restarts it, and
v3 boots through sleep 10 + createdb + migrate + cache warmers before health
flips to 200. Widened to 300s, still far inside the recipe HTTP_TIMEOUT of 1200.
The assertion is unchanged: a hard 200 from the real readiness endpoint.
Neither change weakens a test - the event tests still require the row to arrive
in ClickHouse and match what was sent.
The first cut of this fix added a team INSERT next to the existing sites INSERT.
That fixed the symptom and kept the cause: a fixture that knows the apps table
layout breaks whenever the app changes it, which is exactly what happened here.
_register_site now calls Plausible.Sites.create/2 through the app release console,
so the app provisions whatever its data model currently requires - including the
team it introduced in v3. Verified against BOTH versions on cc-ci: the identical
expression works on v2.0.0, which has no teams table at all, and on v3.2.1. No
version gate is needed because the fixture no longer depends on the schema.
The HTTP provisioning API (POST /api/v1/sites) would have been first choice, but
it is gated behind a paid plan and answers :upgrade_required on CE. That is
recorded in the code so the next person does not re-derive it.
tests/STYLE.md writes the rule down, along with the others this failure exercised:
gate on version rather than supporting both schemas (old-version tests can just be
deleted - the older version is only exercised through the upgrade tier); correct
the fixture or the wait but never the assertion; assert stored state rather than a
202 ack; size waits from the recipes declared readiness; and read the apps own
telemetry before deciding a test is stale.
Full cold suite against the recipe PR head: level 5 of 5, GREEN.
Updated: the fixture no longer touches the database, and a style guide is added
The first cut added a teams INSERT beside the existing sites INSERT. That fixed the symptom and
kept the cause — a fixture that knows the app's table layout breaks whenever the app changes it,
which is precisely what happened here.
_register_site now calls Plausible.Sites.create/2 through the app's release console, so the
app provisions whatever its data model currently requires, including the team it introduced in v3.
Verified against both versions on cc-ci: the identical expression works on v2.0.0, which has
no teams table at all, and on v3.2.1. No version gate is needed, because the fixture no longer
depends on the schema — which is a better outcome than a fixture carefully written to handle both.
The HTTP provisioning API (POST /api/v1/sites) would have been the first choice, but it is gated
behind a paid plan and answers :upgrade_required on CE. That's recorded in the code so nobody
re-derives it.
New: tests/STYLE.md
The rule that would have prevented this — set state up through the app's own interface, not its
database — is now written down, with this failure as the worked example, along with the others it
exercised: gate on version rather than supporting both schemas (old-version tests can simply be
deleted, since the older version is only exercised through the upgrade tier); correct the fixture or
the wait but never the assertion; assert stored state rather than a 202 ack; size waits from the
recipe's declared readiness; and read the app's own telemetry before deciding a test is stale.
/recipe-upgrade --with-tests, /ci-test-review and /cc-ci-tests-update are all now pointed at it
before they edit a test (orchestrator commit 6c91373).
Re-verified
Full cold suite against the recipe PR head with the rewritten fixture:
### Updated: the fixture no longer touches the database, and a style guide is added
The first cut added a `teams` INSERT beside the existing `sites` INSERT. That fixed the symptom and
kept the cause — a fixture that knows the app's table layout breaks whenever the app changes it,
which is precisely what happened here.
`_register_site` now calls **`Plausible.Sites.create/2`** through the app's release console, so the
app provisions whatever its data model currently requires, including the team it introduced in v3.
**Verified against both versions on cc-ci:** the identical expression works on **v2.0.0**, which has
no `teams` table at all, and on **v3.2.1**. No version gate is needed, because the fixture no longer
depends on the schema — which is a better outcome than a fixture carefully written to handle both.
The HTTP provisioning API (`POST /api/v1/sites`) would have been the first choice, but it is gated
behind a paid plan and answers `:upgrade_required` on CE. That's recorded in the code so nobody
re-derives it.
### New: `tests/STYLE.md`
The rule that would have prevented this — **set state up through the app's own interface, not its
database** — is now written down, with this failure as the worked example, along with the others it
exercised: gate on version rather than supporting both schemas (old-version tests can simply be
deleted, since the older version is only exercised through the upgrade tier); correct the fixture or
the wait but never the assertion; assert stored state rather than a 202 ack; size waits from the
recipe's declared readiness; and read the app's own telemetry before deciding a test is stale.
`/recipe-upgrade --with-tests`, `/ci-test-review` and `/cc-ci-tests-update` are all now pointed at it
before they edit a test (orchestrator commit `6c91373`).
### Re-verified
Full cold suite against the recipe PR head with the rewritten fixture:
```
install : pass upgrade : pass backup : pass restore : pass custom : pass
level = 5 of 5 VERDICT: GREEN
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
plausible's custom tier has been RED since the v3 upgrade PR(plausible#5), most recently on
build 1224.
install,upgrade,backupandrestoreall pass; only the three custom tests fail.Both causes are in the tests, not the recipe.
1. v3 only ingests events for a site that belongs to a TEAM
_register_siteinserted a row intositesand nothing else. That was sufficient for v2(
plausible/analytics). Under v3 (ghcr.io/plausible/community-edition) a teamless site is not"known" to the ingestion path, so every event is discarded — while
POST /api/eventstill returns202 and the postgres row still exists. The only visible symptom is that nothing ever reaches
ClickHouse, which reads as a silent ingestion stall:
ClickHouse records the real reason itself, in
ingest_counters. Verified on cc-ci against v3.2.1,same site row both times:
ingest_countersevents_v2dropped_not_foundbuffered_register_sitenow provisions a team and links the site. The block is guarded on the schemaactually having
teams+sites.team_id, so it is a no-op on v2 — which matters because theupgrade tier deploys the older base version first.
2. The post-restore health wait was too short for v3
test_plausible_root_serveswaited 60s for/api/health. The custom tier runs afterbackup/restore, which disrupts postgres under the app and restarts it, and v3 boots through
sleep 10→db createdb→db migrate→ cache warmers before health flips to 200. Widened to300s, still far inside the recipe's own declared
HTTP_TIMEOUT = 1200.What this does NOT do
Neither change weakens an assertion. The event tests still require the row to arrive in ClickHouse
and match what was sent (name, pathname, hostname); the health test still requires a hard
200from the real readiness endpoint. Only the fixture and the wait changed.
Verification
Full cold suite against the recipe PR head (
upgrade-4.0.0+v3.2.1,867ebfaf) with this branch:All three previously-failing tests pass:
test_pageview_event_roundtrip,test_custom_event_roundtrip,test_plausible_root_serves.Dependent pair
This is the CI half of a pair.
!testmeon plausible#5 runs the deployed cc-ci tests, so that PRstays RED until this one merges. Merge this first, then re-run
!testmethere.Not merged by automation — for operator review.
Updated: the fixture no longer touches the database, and a style guide is added
The first cut added a
teamsINSERT beside the existingsitesINSERT. That fixed the symptom andkept the cause — a fixture that knows the app's table layout breaks whenever the app changes it,
which is precisely what happened here.
_register_sitenow callsPlausible.Sites.create/2through the app's release console, so theapp provisions whatever its data model currently requires, including the team it introduced in v3.
Verified against both versions on cc-ci: the identical expression works on v2.0.0, which has
no
teamstable at all, and on v3.2.1. No version gate is needed, because the fixture no longerdepends on the schema — which is a better outcome than a fixture carefully written to handle both.
The HTTP provisioning API (
POST /api/v1/sites) would have been the first choice, but it is gatedbehind a paid plan and answers
:upgrade_requiredon CE. That's recorded in the code so nobodyre-derives it.
New:
tests/STYLE.mdThe rule that would have prevented this — set state up through the app's own interface, not its
database — is now written down, with this failure as the worked example, along with the others it
exercised: gate on version rather than supporting both schemas (old-version tests can simply be
deleted, since the older version is only exercised through the upgrade tier); correct the fixture or
the wait but never the assertion; assert stored state rather than a 202 ack; size waits from the
recipe's declared readiness; and read the app's own telemetry before deciding a test is stale.
/recipe-upgrade --with-tests,/ci-test-reviewand/cc-ci-tests-updateare all now pointed at itbefore they edit a test (orchestrator commit
6c91373).Re-verified
Full cold suite against the recipe PR head with the rewritten fixture: