Skip to content

Commit 601ab7f

Browse files
committed
Archive deprecated LaunchDarkly flags on import
1 parent 0e0176f commit 601ab7f

5 files changed

Lines changed: 33 additions & 2 deletions

File tree

api/integrations/launch_darkly/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
LAUNCH_DARKLY_IMPORTED_TAG_COLOR = "#3d4db6"
88
LAUNCH_DARKLY_IMPORTED_DEFAULT_TAG_LABEL = "Imported"
9+
LAUNCH_DARKLY_IMPORTED_DEPRECATED_TAG_LABEL = "Deprecated"
910

1011
BACKOFF_MAX_RETRIES = 5
1112
BACKOFF_DEFAULT_RETRY_AFTER_SECONDS = 10

api/integrations/launch_darkly/services.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from integrations.launch_darkly.client import LaunchDarklyClient
2828
from integrations.launch_darkly.constants import (
2929
LAUNCH_DARKLY_IMPORTED_DEFAULT_TAG_LABEL,
30+
LAUNCH_DARKLY_IMPORTED_DEPRECATED_TAG_LABEL,
3031
LAUNCH_DARKLY_IMPORTED_TAG_COLOR,
3132
)
3233
from integrations.launch_darkly.exceptions import LaunchDarklyRateLimitError
@@ -117,7 +118,11 @@ def _create_tags_from_ld(
117118
) -> dict[str, Tag]:
118119
tags_by_ld_tag = {}
119120

120-
for ld_tag in (*ld_tags, LAUNCH_DARKLY_IMPORTED_DEFAULT_TAG_LABEL):
121+
for ld_tag in (
122+
*ld_tags,
123+
LAUNCH_DARKLY_IMPORTED_DEFAULT_TAG_LABEL,
124+
LAUNCH_DARKLY_IMPORTED_DEPRECATED_TAG_LABEL,
125+
):
121126
tags_by_ld_tag[ld_tag], _ = Tag.objects.update_or_create(
122127
label=ld_tag,
123128
project_id=project_id,
@@ -894,6 +899,8 @@ def _create_feature_from_ld(
894899
tags_by_ld_tag[LAUNCH_DARKLY_IMPORTED_DEFAULT_TAG_LABEL],
895900
*(tags_by_ld_tag[ld_tag] for ld_tag in ld_flag["tags"]),
896901
]
902+
if ld_flag["deprecated"]:
903+
tags.append(tags_by_ld_tag[LAUNCH_DARKLY_IMPORTED_DEPRECATED_TAG_LABEL])
897904

898905
feature, _ = Feature.objects.update_or_create(
899906
project_id=project_id,
@@ -902,7 +909,7 @@ def _create_feature_from_ld(
902909
"description": ld_flag.get("description"),
903910
"default_enabled": False,
904911
"type": feature_type,
905-
"is_archived": ld_flag["archived"],
912+
"is_archived": ld_flag["archived"] or ld_flag["deprecated"],
906913
},
907914
)
908915
feature.tags.set(tags)

api/tests/unit/integrations/launch_darkly/client_responses/get_flags.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"offVariation": 1,
3636
"onVariation": 0
3737
},
38+
"deprecated": true,
3839
"description": "",
3940
"environments": {
4041
"production": {
@@ -162,6 +163,7 @@
162163
"offVariation": 1,
163164
"onVariation": 0
164165
},
166+
"deprecated": false,
165167
"description": "",
166168
"environments": {
167169
"production": {
@@ -289,6 +291,7 @@
289291
"offVariation": 1,
290292
"onVariation": 0
291293
},
294+
"deprecated": false,
292295
"description": "",
293296
"environments": {
294297
"production": {
@@ -420,6 +423,7 @@
420423
"offVariation": 1,
421424
"onVariation": 0
422425
},
426+
"deprecated": false,
423427
"description": "",
424428
"environments": {
425429
"production": {
@@ -558,6 +562,7 @@
558562
"offVariation": 1,
559563
"onVariation": 0
560564
},
565+
"deprecated": false,
561566
"description": "",
562567
"environments": {
563568
"production": {

api/tests/unit/integrations/launch_darkly/test_services.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ def test_process_import_request__success__expected_status( # type: ignore[no-un
141141
("testtag", "#3d4db6"),
142142
("testtag2", "#3d4db6"),
143143
("Imported", "#3d4db6"),
144+
("Deprecated", "#3d4db6"),
144145
}
145146
assert set(
146147
Feature.objects.filter(project=project).values_list("name", "tags__label")
147148
) == {
148149
("flag1", "Imported"),
150+
("flag1", "Deprecated"),
149151
("flag2_value", "Imported"),
150152
("flag3_multivalue", "Imported"),
151153
("flag4_multivalue", "Imported"),
@@ -158,6 +160,10 @@ def test_process_import_request__success__expected_status( # type: ignore[no-un
158160
("TEST_COMBINED_TARGET", "Imported"),
159161
}
160162

163+
# Deprecated flags are archived.
164+
deprecated_feature = Feature.objects.get(project=project, name="flag1")
165+
assert deprecated_feature.is_archived is True
166+
161167
# Standard feature states have expected values.
162168
boolean_standard_feature = Feature.objects.get(project=project, name="flag1")
163169
boolean_standard_feature_states_by_env_name = {

docs/docs/administration-and-security/data-management/import-from-launchdarkly.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,15 @@ Multivariate LaunchDarkly flags will be imported into Flagsmith as MultiVariate
6565
Multivariate values will be taken from the `variations` field of within LaunchDarkly.
6666

6767
Values set to serve when targeting is off will be imported as control values.
68+
69+
#### Archived and deprecated flags
70+
71+
Archived flags in LaunchDarkly are imported as archived flags in Flagsmith.
72+
73+
Deprecated flags in LaunchDarkly are also imported as archived flags in Flagsmith. They receive a "Deprecated" tag to distinguish them from flags that were archived in LaunchDarkly.
74+
75+
:::warning
76+
77+
In LaunchDarkly, deprecated flags continue to evaluate normally. In Flagsmith, archived flags return fallback values. Unarchive deprecated flags after import if older application versions still request them.
78+
79+
:::

0 commit comments

Comments
 (0)