From 8fe2107d1422addc2dd5c3368088b9e3aeb3cd53 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Thu, 3 Sep 2026 16:23:08 +0100 Subject: [PATCH 1/2] fix(tests): make segment rule and condition ordering deterministic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SegmentRule and Condition use ConfiguredOrderManager, which only adds `.order_by("id")` when the explicit-ordering settings are enabled. They default to off, so in tests the queryset carries no ordering at all and rows come back in whatever order the database happens to return. Several tests depend on that order — the LaunchDarkly `large_segments` snapshots compare serialised `rules_data`, so any reordering of rules or conditions changes the output. They pass today because Postgres happens to return rows in insertion order for these queries, not because anything guarantees it. That is latent flakiness: nothing stops a plan change, an update, or autovacuum altering it. Enable both settings for tests so the ordering the code implicitly expects is the ordering it gets. This also makes the same suites deterministic on MySQL and Oracle, which is how it was found — Flagsmith/flagsmith-ee#224. Both derived names are set rather than the SEGMENT_RULES_CONDITIONS_EXPLICIT_ORDERING_ENABLED parent, because common.py resolves the derived settings at import time, so setting only the parent in test.py has no effect. For the same reason this cannot be done per test: ConfiguredOrderManager reads the value when the manager is constructed. Co-Authored-By: Claude Opus 5 --- api/app/settings/test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/app/settings/test.py b/api/app/settings/test.py index 72bd7920c906..6d429135a7bd 100644 --- a/api/app/settings/test.py +++ b/api/app/settings/test.py @@ -14,6 +14,13 @@ INSTALLED_APPS = INSTALLED_APPS + ["flagsmith_ldap"] LDAP_DEFAULT_FLAGSMITH_ORGANISATION_ID = None +# Otherwise rule and condition ordering is whatever the database returns. +# ConfiguredOrderManager reads these when the manager is constructed, so they +# cannot be set per test, and both derived names are needed because common.py +# resolves them at import time. +SEGMENT_CONDITIONS_EXPLICIT_ORDERING_ENABLED = True +SEGMENT_RULES_EXPLICIT_ORDERING_ENABLED = True + # We dont want to track tests ENABLE_TELEMETRY = False MAX_PROJECTS_IN_FREE_PLAN = 10 From 3ce2aeed0125d5271ee6bd5c588da34a6c709a4a Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Fri, 4 Sep 2026 08:47:32 +0100 Subject: [PATCH 2/2] Improve comment --- api/app/settings/test.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/app/settings/test.py b/api/app/settings/test.py index 6d429135a7bd..5450b1dceaee 100644 --- a/api/app/settings/test.py +++ b/api/app/settings/test.py @@ -15,9 +15,7 @@ LDAP_DEFAULT_FLAGSMITH_ORGANISATION_ID = None # Otherwise rule and condition ordering is whatever the database returns. -# ConfiguredOrderManager reads these when the manager is constructed, so they -# cannot be set per test, and both derived names are needed because common.py -# resolves them at import time. +# Can cause issues downstream when using other database engines. SEGMENT_CONDITIONS_EXPLICIT_ORDERING_ENABLED = True SEGMENT_RULES_EXPLICIT_ORDERING_ENABLED = True