Conferring a product on two ladders writes its tier-change rows in no fixed order, so a golden test fails now and then #218
Open
opened 2026-10-12 02:10:18 +00:00 by cgalo5758
·
0 comments
Labels
Clear labels
accessibility
area/billing
area/catalog
area/discourse
area/domains
area/entitlements
area/fedwiki
area/identity
area/integrations
area/licensing
area/member-ui
area/meta
area/operator-ui
area/ops
area/testing
duplicate
good-first-issue
invalid
privacy
security
upstream
wontfix
A barrier for people using assistive technology or a keyboard alone.
The Stripe mirror, checkout, subscriptions, invoices, fulfillment.
Products, prices, plan ladders, purchasability.
The Discourse integration.
The domains registry, claims, placements, the certificate ask.
Entitlement sets, rules, grants, pools, provisioning.
The Federated Wiki integration and farm sync.
Sign-in, sessions, persons, organizations, workspaces, roles.
The provider registry, outbox and webhooks in general.
Licenses, the contributor agreement, SPDX headers.
Member pages.
The repository itself, its contributing guide, CI, the tracker and the workflow.
Operator pages, forms, lists, the design system.
Deployment, configuration, migrations, workflows, instance settings.
The test stack, screens, lint, walkthroughs.
Closed because another issue already covers it.
Small, self-contained, and explained enough to be a first contribution.
Closed because it is not a ticket for this repository.
Touches what a person's data reveals.
Touches authentication, authorization, secrets or data exposure.
Waits on another repository or project before it can move.
Closed because it will not be done, with the reason in the last comment.
kind
bug
The software does something other than what it promises; closed when it again does what it promises.
kind
debt
Code, tests or tooling to clean up with nothing visible changing; closed when they are cleaner.
kind
design
A question to settle before work can be defined; closed when the decision is written down.
kind
docs
Documentation that is wrong or missing; closed when it says the right thing.
kind
enhancement
Something the software does not do yet; closed when it does.
priority
critical
Blocks the active milestone or harms members now.
priority
high
Next in line inside the active milestone.
priority
low
Inside the active milestone, when nothing else is left.
priority
medium
Inside the active milestone, after the high ones.
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: wiki-cafe/member-console#218
Reference in New Issue
Block a user
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 a contributor runs into
TestPlanActsGolden/default-already-atininternal/serverhas failed once with two rows of its expected output (internal/server/testdata/plan_acts/default-already-at.json) in swapped order, and it passes when run again.A plan ladder is an ordered list of tiers, each tier a product, and a product can sit on more than one ladder. Every tier change an organization's pool goes through is a row in
core.pool_provision_transitions. In this test the default product, Basic, sits on two ladders, Main and Twin. Placing the organization on its type's default plan confers Basic once, throughcore.confer, which writes oneinitiaterow for each ladder. The golden expects Main's row first; the failing run listed Twin's first.The test lists the rows
ORDER BY transition_id(internal/server/plan_acts_golden_db_test.go:397). Transition ids come fromuuidv7()and rise in the order the rows are written, so the golden's order is the write order.core.confer(internal/db/migrations/00023_grant_resumption.sql) writes the new position's rows in a loop over the product's ladders,FOR v_shape IN SELECT ... FROM core.product_conferral_shapes(line 634), with one INSERT per ladder (line 661). That query has no ORDER BY, so the ladders come in whatever order the query plan returns them. The loop that writes theendrows of a provision the conferral replaces (line 602) has no ORDER BY either, so a replaced provision on two ladders is ended in either order too.Why it costs
A golden that fails by chance teaches people to rerun it, and a real change to the row order then gets rerun too. The order reaches more than this test: two other tests list transitions by transition id (
internal/entitlements/grant_resumption_fixture_test.go:460,internal/fulfillment/trace_db_test.go:371), and the Tier changes list breaks its ties on the transition id (ListTransitionsByPoolininternal/entitlements/queries/pool_provision_transitions.sql), so it can show the rows one conferral writes for two ladders in either order.Where
core.conferininternal/db/migrations/00023_grant_resumption.sql;internal/server/plan_acts_golden_db_test.go.Done when
core.conferwrites the rows of one conferral in ladder order: both loops order by the ladder id, in a new migration that replaces the function, with a Down that restores today's body. Ladder ids areuuidv7()as well, so the rows follow the order the ladders were created, which is the orderdefault-already-atexpects; its golden does not change.The other fix is a golden query that does not depend on write order, sorting by a key such as the provision, the transition type and the ladder. It fixes this test alone, reorders every plan-act golden that lists transitions, and leaves the other two tests and the Tier changes list as they are. The migration is the better fix.
Related: #179 asks for an id shared by the rows one act writes; that id would group them, not order them.