diff --git a/api/features/workflows/core/models.py b/api/features/workflows/core/models.py index 1e4c7d2ac9c1..cd26ccc000aa 100644 --- a/api/features/workflows/core/models.py +++ b/api/features/workflows/core/models.py @@ -263,14 +263,20 @@ def prevent_change_request_delete_if_committed(self) -> None: @property def live_from(self) -> datetime | None: + # Note: a change request can only have one of either + # feature_states, change_sets or environment_feature_versions + # First we check if there are feature states associated with the change request # and, if so, we return the live_from of the feature state with the earliest # live_from. if first_feature_state := self.feature_states.order_by("live_from").first(): return first_feature_state.live_from - # Then we do the same for environment feature versions. Note that a change request - # can not have feature states and environment feature versions. + # Then we check the change sets. + elif first_change_set := self.change_sets.order_by("live_from").first(): + return first_change_set.live_from + + # Finally, we do the same for environment feature versions. elif first_environment_feature_version := self.environment_feature_versions.order_by( "live_from" ).first(): diff --git a/api/tests/unit/features/workflows/core/test_unit_workflows_models.py b/api/tests/unit/features/workflows/core/test_unit_workflows_models.py index c7fa0febcdc1..e17cbbafdd6f 100644 --- a/api/tests/unit/features/workflows/core/test_unit_workflows_models.py +++ b/api/tests/unit/features/workflows/core/test_unit_workflows_models.py @@ -1,5 +1,7 @@ +import json from datetime import timedelta +import freezegun import pytest from django.contrib.sites.models import Site from django.utils import timezone @@ -16,7 +18,10 @@ from audit.related_object_type import RelatedObjectType from environments.models import Environment from features.models import Feature, FeatureState -from features.versioning.models import EnvironmentFeatureVersion +from features.versioning.models import ( + EnvironmentFeatureVersion, + VersionChangeSet, +) from features.versioning.versioning_service import get_environment_flags_list from features.workflows.core.exceptions import ( CannotApproveOwnChangeRequest, @@ -731,3 +736,40 @@ def test_committing_change_request_with_environment_feature_versions_creates_pub related_object_type=RelatedObjectType.EF_VERSION.name, log=ENVIRONMENT_FEATURE_VERSION_PUBLISHED_MESSAGE % feature.name, ).exists() + + +def test_change_request_live_from_for_change_request_with_change_set( + feature: Feature, + environment_v2_versioning: Environment, + admin_user: FFAdminUser, +) -> None: + # Given + change_request = ChangeRequest.objects.create( + title="Test CR", + environment=environment_v2_versioning, + user=admin_user, + ) + VersionChangeSet.objects.create( + change_request=change_request, + feature=feature, + feature_states_to_update=json.dumps( + [ + { + "feature_segment": None, + "enabled": True, + "feature_state_value": { + "type": "unicode", + "string_value": "updated", + }, + } + ] + ), + ) + + # When + now = timezone.now() + with freezegun.freeze_time(now): + change_request.commit(admin_user) + + # Then + assert change_request.live_from == now