Skip to content

Commit 26cfd81

Browse files
authored
fix: don't sort condition sets with variant overrides to the top (#330)
* fix: don't sort condition sets with variant overrides to the top * fix test * update test * update version and change log
1 parent e868e23 commit 26cfd81

File tree

4 files changed

+30
-44
lines changed

4 files changed

+30
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 6.7.6 - 2025-09-16
2+
3+
- fix: don't sort condition sets with variant overrides to the top
4+
- fix: Prevent core Client methods from raising exceptions
5+
16
# 6.7.5 - 2025-09-16
27

38
- feat: Django middleware now supports async request handling.

posthog/feature_flags.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,7 @@ def match_feature_flag_properties(
220220
) or []
221221
valid_variant_keys = [variant["key"] for variant in flag_variants]
222222

223-
# Stable sort conditions with variant overrides to the top. This ensures that if overrides are present, they are
224-
# evaluated first, and the variant override is applied to the first matching condition.
225-
sorted_flag_conditions = sorted(
226-
flag_conditions,
227-
key=lambda condition: 0 if condition.get("variant") else 1,
228-
)
229-
230-
for condition in sorted_flag_conditions:
223+
for condition in flag_conditions:
231224
try:
232225
# if any one condition resolves to True, we can shortcircuit and return
233226
# the matching variant

posthog/test/test_feature_flags.py

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,73 +2804,61 @@ def test_flag_with_invalid_variant_overrides(self, patch_flags):
28042804
self.assertEqual(patch_flags.call_count, 0)
28052805

28062806
@mock.patch("posthog.client.flags")
2807-
def test_flag_with_multiple_variant_overrides(self, patch_flags):
2808-
patch_flags.return_value = {"featureFlags": {"beta-feature": "variant-1"}}
2807+
def test_conditions_evaluated_in_order(self, patch_flags):
2808+
patch_flags.return_value = {"featureFlags": {"order-test": "server-variant"}}
28092809
client = Client(FAKE_TEST_API_KEY, personal_api_key="test")
28102810
client.feature_flags = [
28112811
{
28122812
"id": 1,
2813-
"name": "Beta Feature",
2814-
"key": "beta-feature",
2813+
"name": "Order Test Flag",
2814+
"key": "order-test",
28152815
"active": True,
2816-
"rollout_percentage": 100,
28172816
"filters": {
28182817
"groups": [
28192818
{
28202819
"rollout_percentage": 100,
2821-
# The override applies even if the first condition matches all and gives everyone their default group
28222820
},
28232821
{
28242822
"properties": [
28252823
{
28262824
"key": "email",
28272825
"type": "person",
2828-
"value": "test@posthog.com",
2829-
"operator": "exact",
2826+
"value": "@vip.com",
2827+
"operator": "icontains",
28302828
}
28312829
],
28322830
"rollout_percentage": 100,
2833-
"variant": "second-variant",
2831+
"variant": "vip-variant",
28342832
},
2835-
{"rollout_percentage": 50, "variant": "third-variant"},
28362833
],
28372834
"multivariate": {
28382835
"variants": [
28392836
{
2840-
"key": "first-variant",
2841-
"name": "First Variant",
2842-
"rollout_percentage": 50,
2837+
"key": "control",
2838+
"name": "Control",
2839+
"rollout_percentage": 100,
28432840
},
28442841
{
2845-
"key": "second-variant",
2846-
"name": "Second Variant",
2847-
"rollout_percentage": 25,
2848-
},
2849-
{
2850-
"key": "third-variant",
2851-
"name": "Third Variant",
2852-
"rollout_percentage": 25,
2842+
"key": "vip-variant",
2843+
"name": "VIP Variant",
2844+
"rollout_percentage": 0,
28532845
},
28542846
]
28552847
},
28562848
},
28572849
}
28582850
]
2859-
self.assertEqual(
2860-
client.get_feature_flag(
2861-
"beta-feature",
2862-
"test_id",
2863-
person_properties={"email": "[email protected]"},
2864-
),
2865-
"second-variant",
2866-
)
2867-
self.assertEqual(
2868-
client.get_feature_flag("beta-feature", "example_id"), "third-variant"
2869-
)
2870-
self.assertEqual(
2871-
client.get_feature_flag("beta-feature", "another_id"), "second-variant"
2851+
2852+
# Even though [email protected] would match the second condition with variant override,
2853+
# they should match the first condition and get control
2854+
result = client.get_feature_flag(
2855+
"order-test",
2856+
"user123",
2857+
person_properties={"email": "[email protected]"},
28722858
)
2873-
# decide not called because this can be evaluated locally
2859+
self.assertEqual(result, "control")
2860+
2861+
# server not called because this can be evaluated locally
28742862
self.assertEqual(patch_flags.call_count, 0)
28752863

28762864
@mock.patch("posthog.client.flags")

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "6.7.5"
1+
VERSION = "6.7.6"
22

33
if __name__ == "__main__":
44
print(VERSION, end="") # noqa: T201

0 commit comments

Comments
 (0)