Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/sentry/overwatch/endpoints/overwatch_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from rest_framework.request import Request
from rest_framework.response import Response

from sentry import features
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.authentication import AuthenticationSiloLimit, StandardAuthentication
Expand Down Expand Up @@ -87,6 +88,9 @@ def authenticate_token(self, request: Request, token: str) -> tuple[Any, Any]:

def _can_use_prevent_ai_features(org: Organization) -> bool:
"""Check if organization has opted in to Prevent AI features."""
if not features.has("organizations:gen-ai-features", org):
return False

hide_ai_features = org.get_option("sentry:hide_ai_features", HIDE_AI_FEATURES_DEFAULT)
pr_review_test_generation_enabled = bool(
org.get_option(
Expand Down
3 changes: 3 additions & 0 deletions src/sentry/seer/endpoints/seer_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ def get_organization_project_ids(*, org_id: int) -> dict:


def _can_use_prevent_ai_features(org: Organization) -> bool:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems not ideal that there are two copies of this function, can follow up on this

if not features.has("organizations:gen-ai-features", org):
return False

hide_ai_features = org.get_option("sentry:hide_ai_features", HIDE_AI_FEATURES_DEFAULT)
pr_review_test_generation_enabled = bool(
org.get_option(
Expand Down
56 changes: 29 additions & 27 deletions tests/sentry/overwatch/endpoints/test_overwatch_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,29 +344,30 @@ def test_returns_org_ids_with_consent(self):
params = {"repoId": repo_id}
auth = self._auth_header_for_get(url, params, "test-secret")

resp = self.client.get(url, params, HTTP_AUTHORIZATION=auth)
assert resp.status_code == 200
# Should return both orgs with their consent status
expected_orgs = [
{
"org_id": org_with_consent.id,
"org_slug": org_with_consent.slug,
"org_name": org_with_consent.name,
"has_consent": True,
},
{
"org_id": org_without_consent.id,
"org_slug": org_without_consent.slug,
"org_name": org_without_consent.name,
"has_consent": False,
},
]
# Sort both lists by org_id to ensure consistent comparison
expected_orgs = sorted(expected_orgs, key=lambda x: x["org_id"])
actual_data = {
"organizations": sorted(resp.data["organizations"], key=lambda x: x["org_id"])
}
assert actual_data == {"organizations": expected_orgs}
with self.feature("organizations:gen-ai-features"):
resp = self.client.get(url, params, HTTP_AUTHORIZATION=auth)
assert resp.status_code == 200
# Should return both orgs with their consent status
expected_orgs = [
{
"org_id": org_with_consent.id,
"org_slug": org_with_consent.slug,
"org_name": org_with_consent.name,
"has_consent": True,
},
{
"org_id": org_without_consent.id,
"org_slug": org_without_consent.slug,
"org_name": org_without_consent.name,
"has_consent": False,
},
]
# Sort both lists by org_id to ensure consistent comparison
expected_orgs = sorted(expected_orgs, key=lambda x: x["org_id"])
actual_data = {
"organizations": sorted(resp.data["organizations"], key=lambda x: x["org_id"])
}
assert actual_data == {"organizations": expected_orgs}

@patch(
"sentry.overwatch.endpoints.overwatch_rpc.settings.OVERWATCH_RPC_SHARED_SECRET",
Expand Down Expand Up @@ -394,7 +395,8 @@ def test_filters_inactive_repositories(self):
params = {"repoId": repo_id}
auth = self._auth_header_for_get(url, params, "test-secret")

resp = self.client.get(url, params, HTTP_AUTHORIZATION=auth)
assert resp.status_code == 200
# Should return empty list as the repository is inactive
assert resp.data == {"organizations": []}
with self.feature("organizations:gen-ai-features"):
resp = self.client.get(url, params, HTTP_AUTHORIZATION=auth)
assert resp.status_code == 200
# Should return empty list as the repository is inactive
assert resp.data == {"organizations": []}
86 changes: 78 additions & 8 deletions tests/sentry/seer/endpoints/test_seer_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from sentry.models.options.organization_option import OrganizationOption
from sentry.models.repository import Repository
from sentry.seer.endpoints.seer_rpc import (
_can_use_prevent_ai_features,
check_repository_integrations_status,
generate_request_signature,
get_attributes_for_span,
Expand Down Expand Up @@ -118,6 +119,8 @@ def test_get_organization_seer_consent_by_org_name_with_default_pr_review_enable

def test_get_organization_seer_consent_by_org_name_multiple_orgs_one_with_consent(self) -> None:
"""Test when multiple organizations exist, one with consent"""
from sentry.testutils.helpers.features import with_feature

org_without_consent = self.create_organization(owner=self.user)
org_with_consent = self.create_organization(owner=self.user)

Expand All @@ -143,7 +146,8 @@ def test_get_organization_seer_consent_by_org_name_multiple_orgs_one_with_consen
org_with_consent, "sentry:enable_pr_review_test_generation", True
)

result = get_organization_seer_consent_by_org_name(org_name="test-org")
with with_feature("organizations:gen-ai-features"):
result = get_organization_seer_consent_by_org_name(org_name="test-org")

assert result == {"consent": True}

Expand Down Expand Up @@ -289,6 +293,63 @@ def test_get_organization_seer_consent_by_org_name_hide_ai_false_pr_review_false
"consent_url": self.organization.absolute_url("/settings/organization/"),
}

def test_can_use_prevent_ai_features_without_gen_ai_flag(self) -> None:
"""Test that _can_use_prevent_ai_features returns False when gen-ai-features flag is disabled"""
# Enable PR review and disable hide_ai_features (should normally pass)
OrganizationOption.objects.set_value(
self.organization, "sentry:enable_pr_review_test_generation", True
)
OrganizationOption.objects.set_value(self.organization, "sentry:hide_ai_features", False)

# Without the feature flag enabled, should return False
result = _can_use_prevent_ai_features(self.organization)
assert result is False

def test_can_use_prevent_ai_features_with_gen_ai_flag(self) -> None:
"""Test that _can_use_prevent_ai_features checks org-level flags when gen-ai-features is enabled"""
from sentry.testutils.helpers.features import with_feature

# Enable PR review and disable hide_ai_features
OrganizationOption.objects.set_value(
self.organization, "sentry:enable_pr_review_test_generation", True
)
OrganizationOption.objects.set_value(self.organization, "sentry:hide_ai_features", False)

# With the feature flag enabled and correct org settings, should return True
with with_feature("organizations:gen-ai-features"):
result = _can_use_prevent_ai_features(self.organization)
assert result is True

def test_can_use_prevent_ai_features_with_gen_ai_flag_but_hide_ai(self) -> None:
"""Test that _can_use_prevent_ai_features returns False when hide_ai_features is True"""
from sentry.testutils.helpers.features import with_feature

# Enable PR review but enable hide_ai_features
OrganizationOption.objects.set_value(
self.organization, "sentry:enable_pr_review_test_generation", True
)
OrganizationOption.objects.set_value(self.organization, "sentry:hide_ai_features", True)

# Even with feature flag enabled, should return False due to hide_ai_features
with with_feature("organizations:gen-ai-features"):
result = _can_use_prevent_ai_features(self.organization)
assert result is False

def test_can_use_prevent_ai_features_with_gen_ai_flag_but_no_pr_review(self) -> None:
"""Test that _can_use_prevent_ai_features returns False when PR review is disabled"""
from sentry.testutils.helpers.features import with_feature

# Disable PR review but disable hide_ai_features
OrganizationOption.objects.set_value(
self.organization, "sentry:enable_pr_review_test_generation", False
)
OrganizationOption.objects.set_value(self.organization, "sentry:hide_ai_features", False)

# Even with feature flag enabled, should return False due to PR review being disabled
with with_feature("organizations:gen-ai-features"):
result = _can_use_prevent_ai_features(self.organization)
assert result is False

def test_get_attributes_for_span(self) -> None:
project = self.create_project(organization=self.organization)

Expand Down Expand Up @@ -505,6 +566,7 @@ def test_get_github_enterprise_integration_config_invalid_encrypt_key(

def test_get_sentry_organization_ids_repository_found(self) -> None:
"""Test when repository exists and is active"""
from sentry.testutils.helpers.features import with_feature

# Create a project
project = self.create_project(organization=self.organization)
Expand Down Expand Up @@ -546,7 +608,8 @@ def test_get_sentry_organization_ids_repository_found(self) -> None:
OrganizationOption.objects.set_value(
self.organization, "sentry:enable_pr_review_test_generation", True
)
result = get_sentry_organization_ids(external_id="1234567890")
with with_feature("organizations:gen-ai-features"):
result = get_sentry_organization_ids(external_id="1234567890")
assert result == {
"org_ids": [self.organization.id],
"org_slugs": [self.organization.slug],
Expand Down Expand Up @@ -659,19 +722,23 @@ def test_get_sentry_organization_ids_multiple_repos_same_name_different_provider
)
OrganizationOption.objects.set_value(org2, "sentry:enable_pr_review_test_generation", True)

from sentry.testutils.helpers.features import with_feature

# Search for GitHub provider
result = get_sentry_organization_ids(external_id="1234567890")
with with_feature("organizations:gen-ai-features"):
result = get_sentry_organization_ids(external_id="1234567890")

assert result == {
"org_ids": [self.organization.id],
"org_slugs": [self.organization.slug],
}

# Search for GitLab provider
result = get_sentry_organization_ids(
provider="integrations:gitlab",
external_id="1234567890",
)
with with_feature("organizations:gen-ai-features"):
result = get_sentry_organization_ids(
provider="integrations:gitlab",
external_id="1234567890",
)

assert result == {"org_ids": [org2.id], "org_slugs": [org2.slug]}

Expand Down Expand Up @@ -775,7 +842,10 @@ def test_get_sentry_organization_ids_multiple_orgs_same_repo(self) -> None:
)

# Search for GitHub provider
result = get_sentry_organization_ids(external_id="1234567890")
from sentry.testutils.helpers.features import with_feature

with with_feature("organizations:gen-ai-features"):
result = get_sentry_organization_ids(external_id="1234567890")

assert set(result["org_ids"]) == {self.organization.id, org2.id}
assert set(result["org_slugs"]) == {self.organization.slug, org2.slug}
Expand Down
Loading