Browse Source

chore(aci): comparison json schema for LatestAdoptedReleaseHandler (#83877)

Cathy Teng 1 month ago
parent
commit
a6fc081ed0

+ 3 - 2
src/sentry/rules/age.py

@@ -1,9 +1,10 @@
 from __future__ import annotations
 
 import operator
+from enum import StrEnum
 
 
-class ModelAgeType:
+class ModelAgeType(StrEnum):
     OLDEST = "oldest"
     NEWEST = "newest"
 
@@ -11,7 +12,7 @@ class ModelAgeType:
 model_age_choices = [(ModelAgeType.OLDEST, "oldest"), (ModelAgeType.NEWEST, "newest")]
 
 
-class AgeComparisonType:
+class AgeComparisonType(StrEnum):
     OLDER = "older"
     NEWER = "newer"
 

+ 1 - 1
src/sentry/rules/filters/age_comparison.py

@@ -72,7 +72,7 @@ class AgeComparisonFilter(EventFilter):
 
         _, delta_time = timeranges[time]
 
-        passes_: bool = age_comparison_map[comparison_type](
+        passes_: bool = age_comparison_map[AgeComparisonType(comparison_type)](
             first_seen + (value * delta_time), current_time
         )
         return passes_

+ 12 - 1
src/sentry/workflow_engine/handlers/condition/latest_adopted_release_handler.py

@@ -2,7 +2,7 @@ from typing import Any
 
 from sentry.models.environment import Environment
 from sentry.models.release import follows_semver_versioning_scheme
-from sentry.rules.age import AgeComparisonType
+from sentry.rules.age import AgeComparisonType, ModelAgeType
 from sentry.rules.filters.latest_adopted_release_filter import (
     get_first_last_release_for_env,
     is_newer_release,
@@ -18,6 +18,17 @@ from sentry.workflow_engine.types import DataConditionHandler, WorkflowJob
 
 @condition_handler_registry.register(Condition.LATEST_ADOPTED_RELEASE)
 class LatestAdoptedReleaseConditionHandler(DataConditionHandler[WorkflowJob]):
+    comparison_json_schema = {
+        "type": "object",
+        "properties": {
+            "release_age_type": {"type": "string", "enum": [*ModelAgeType]},
+            "age_comparison": {"type": "string", "enum": [*AgeComparisonType]},
+            "environment": {"type": "string"},
+        },
+        "required": ["release_age_type", "age_comparison", "environment"],
+        "additionalProperties": False,
+    }
+
     @staticmethod
     def evaluate_value(job: WorkflowJob, comparison: Any) -> bool:
         release_age_type = comparison["release_age_type"]

+ 3 - 0
tests/sentry/workflow_engine/handlers/condition/test_age_comparison_handler.py

@@ -57,6 +57,9 @@ class TestAgeComparisonCondition(ConditionTestCase):
         assert dc.condition_group == dcg
 
     def test_json_schema(self):
+        self.dc.comparison.update({"comparison_type": AgeComparisonType.NEWER})
+        self.dc.save()
+
         self.dc.comparison.update({"time": "asdf"})
         with pytest.raises(ValidationError):
             self.dc.save()

+ 20 - 0
tests/sentry/workflow_engine/handlers/condition/test_latest_adopted_release_handler.py

@@ -1,8 +1,12 @@
 from datetime import UTC, datetime, timedelta
 from unittest.mock import patch
 
+import pytest
+from jsonschema import ValidationError
+
 from sentry.models.environment import Environment
 from sentry.models.release import Release
+from sentry.rules.age import AgeComparisonType
 from sentry.rules.filters.latest_adopted_release_filter import (
     LatestAdoptedReleaseFilter,
     get_first_last_release_for_group_cache_key,
@@ -87,6 +91,22 @@ class TestLatestAdoptedReleaseCondition(ConditionTestCase):
         assert dc.condition_result is True
         assert dc.condition_group == dcg
 
+    def test_json_schema(self):
+        self.dc.comparison.update({"age_comparison": AgeComparisonType.OLDER})
+        self.dc.save()
+
+        self.dc.comparison.update({"age_comparison": "new"})
+        with pytest.raises(ValidationError):
+            self.dc.save()
+
+        self.dc.comparison.update({"release_age_type": "new"})
+        with pytest.raises(ValidationError):
+            self.dc.save()
+
+        self.dc.comparison.update({"environment": 123})
+        with pytest.raises(ValidationError):
+            self.dc.save()
+
     def test_semver(self):
         # Test no release
         self.assert_does_not_pass(self.dc, self.job)