Skip to content
Open
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
1 change: 0 additions & 1 deletion src/sentry/features/temporary.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ def register_temporary_features(manager: FeatureManager) -> None:
manager.add("organizations:indexed-spans-extraction", OrganizationFeature, FeatureHandlerStrategy.INTERNAL, api_expose=False)
# These flags follow the pattern expected by IntegrationProvider.requires_feature_flag's usage on the config endpoint
manager.add("organizations:integrations-claude-code", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
manager.add("organizations:integrations-github-copilot-agent", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
manager.add("organizations:integrations-github-platform-detection", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
manager.add("organizations:github-repo-auto-sync-webhook", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
manager.add("organizations:integrations-slack-staging", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
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.base import cell_silo_endpoint
Expand Down Expand Up @@ -94,9 +93,7 @@ def get(self, request: Request, organization: Organization) -> Response:
]

github_copilot_installed = any(i.provider == "github_copilot" for i in integrations)
if github_copilot_installed and features.has(
"organizations:integrations-github-copilot-agent", organization
):
if github_copilot_installed:
has_identity = False
if request.user and request.user.id:
try:
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/integrations/github_copilot/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class GithubCopilotIntegrationProvider(CodingAgentIntegrationProvider):
name = "GitHub Copilot"
metadata = metadata
integration_cls = GithubCopilotIntegration
feature_flag_name = "organizations:integrations-github-copilot-agent"
requires_feature_flag = False

def get_agent_name(self) -> str:
return "GitHub Copilot"
Expand Down
3 changes: 0 additions & 3 deletions src/sentry/seer/agent/coding_agent_handoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from requests import HTTPError
from rest_framework.exceptions import PermissionDenied, ValidationError

from sentry import features
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Tests not updated after removing features import

High Severity

The from sentry import features import was removed from coding_agent_handoff.py, but the corresponding test file tests/sentry/seer/agent/test_coding_agent_handoff.py was not updated. Five tests still patch sentry.seer.agent.coding_agent_handoff.features.has, which will raise AttributeError since features is no longer an attribute of the module. Additionally, test_raises_permission_denied_when_copilot_not_enabled asserts behavior (raising PermissionDenied when the feature flag is off) that was intentionally removed in this commit and will never pass.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 14155ba. Configure here.

from sentry.integrations.coding_agent.client import CodingAgentClient
from sentry.integrations.coding_agent.integration import CodingAgentIntegration
from sentry.integrations.coding_agent.models import CodingAgentLaunchRequest
Expand Down Expand Up @@ -50,8 +49,6 @@ def _resolve_client(
Tuple of (client, installation). Exactly one will be non-None.
"""
if provider == "github_copilot":
if not features.has("organizations:integrations-github-copilot-agent", organization):
raise PermissionDenied("GitHub Copilot is not enabled for this organization")
user_access_token: str | None = None
if user_id is not None:
user_access_token = github_copilot_identity_service.get_access_token_for_user(
Expand Down
4 changes: 1 addition & 3 deletions src/sentry/seer/autofix/coding_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from requests import HTTPError
from rest_framework.exceptions import APIException, NotFound, PermissionDenied, ValidationError

from sentry import analytics, features
from sentry import analytics
from sentry.models.project import Project


Expand Down Expand Up @@ -476,8 +476,6 @@ def launch_coding_agents_for_run(
is_github_copilot = provider == "github_copilot"

if is_github_copilot:
if not features.has("organizations:integrations-github-copilot-agent", organization):
raise PermissionDenied("GitHub Copilot is not enabled for this organization")
user_access_token: str | None = None
if user_id is not None:
user_access_token = github_copilot_identity_service.get_access_token_for_user(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,8 @@ export function GithubCopilotIntegrationCta() {
integration => integration.provider === 'github_copilot'
);

const hasGithubCopilotFeatureFlag = organization.features.includes(
'integrations-github-copilot-agent'
);
const hasGithubCopilotIntegration = Boolean(githubCopilotIntegration);

if (!hasGithubCopilotFeatureFlag) {
return null;
}

if (isLoadingIntegrations) {
return (
<Container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,10 @@ def _mock_github_copilot_integration(self):
mock.provider = "github_copilot"
return mock

def test_github_copilot_shown_when_installed_and_feature_flag_enabled(self):
"""Test GET endpoint shows GitHub Copilot when installed and feature flag is enabled."""
def test_github_copilot_shown_when_installed(self):
"""Test GET endpoint shows GitHub Copilot when installed."""
copilot = self._mock_github_copilot_integration()
with (
self.feature("organizations:integrations-github-copilot-agent"),
self.mock_integration_service_calls(integrations=[copilot]),
):
with self.mock_integration_service_calls(integrations=[copilot]):
response = self.get_success_response(self.organization.slug)

integrations = response.data["integrations"]
Expand All @@ -357,11 +354,8 @@ def test_github_copilot_shown_when_installed_and_feature_flag_enabled(self):
assert integrations[0]["has_identity"] is False

def test_github_copilot_not_shown_when_not_installed(self):
"""Test GET endpoint does not show GitHub Copilot when feature flag is on but integration is not installed."""
with (
self.feature("organizations:integrations-github-copilot-agent"),
self.mock_integration_service_calls(integrations=[]),
):
"""Test GET endpoint does not show GitHub Copilot when integration is not installed."""
with self.mock_integration_service_calls(integrations=[]):
response = self.get_success_response(self.organization.slug)
assert response.data["integrations"] == []

Expand All @@ -373,10 +367,7 @@ def test_github_copilot_has_identity_true_when_authenticated(self, mock_identity
mock_identity_service.get_access_token_for_user.return_value = "mock-access-token"
copilot = self._mock_github_copilot_integration()

with (
self.feature("organizations:integrations-github-copilot-agent"),
self.mock_integration_service_calls(integrations=[copilot]),
):
with self.mock_integration_service_calls(integrations=[copilot]):
response = self.get_success_response(self.organization.slug)

integrations = response.data["integrations"]
Expand All @@ -395,10 +386,7 @@ def test_github_copilot_has_identity_false_when_not_authenticated(self, mock_ide
mock_identity_service.get_access_token_for_user.return_value = None
copilot = self._mock_github_copilot_integration()

with (
self.feature("organizations:integrations-github-copilot-agent"),
self.mock_integration_service_calls(integrations=[copilot]),
):
with self.mock_integration_service_calls(integrations=[copilot]):
response = self.get_success_response(self.organization.slug)

integrations = response.data["integrations"]
Expand All @@ -421,10 +409,7 @@ def test_github_copilot_handles_rpc_exception_gracefully(self, mock_identity_ser
)
copilot = self._mock_github_copilot_integration()

with (
self.feature("organizations:integrations-github-copilot-agent"),
self.mock_integration_service_calls(integrations=[copilot]),
):
with self.mock_integration_service_calls(integrations=[copilot]):
response = self.get_success_response(self.organization.slug)

integrations = response.data["integrations"]
Expand All @@ -435,17 +420,6 @@ def test_github_copilot_handles_rpc_exception_gracefully(self, mock_identity_ser
user_id=self.user.id
)

def test_github_copilot_not_shown_without_feature_flag(self) -> None:
"""Test GET endpoint does not show GitHub Copilot without feature flag."""
with (
self.feature({"organizations:integrations-github-copilot-agent": False}),
self.mock_integration_service_calls(integrations=[]),
):
response = self.get_success_response(self.organization.slug)

integrations = response.data["integrations"]
assert len(integrations) == 0


class OrganizationCodingAgentsPostCodingDisabledTest(BaseOrganizationCodingAgentsTest):
"""Test that the endpoint returns 403 when code generation is disabled.
Expand Down Expand Up @@ -1118,10 +1092,7 @@ def test_copilot_403_returns_github_app_permissions_failure_type(

data = {"provider": "github_copilot", "run_id": 123}

with (
self.feature("organizations:integrations-github-copilot-agent"),
patch("sentry.seer.autofix.coding_agent.store_coding_agent_states_to_seer"),
):
with patch("sentry.seer.autofix.coding_agent.store_coding_agent_states_to_seer"):
response = self.get_success_response(self.organization.slug, method="post", **data)
assert response.data["success"] is False
assert response.data["failed_count"] >= 1
Expand Down Expand Up @@ -1161,10 +1132,7 @@ def test_copilot_not_licensed_403_returns_github_copilot_not_licensed_failure_ty

data = {"provider": "github_copilot", "run_id": 123}

with (
self.feature("organizations:integrations-github-copilot-agent"),
patch("sentry.seer.autofix.coding_agent.store_coding_agent_states_to_seer"),
):
with patch("sentry.seer.autofix.coding_agent.store_coding_agent_states_to_seer"):
response = self.get_success_response(self.organization.slug, method="post", **data)
assert response.data["success"] is False
assert response.data["failed_count"] >= 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ def setUp(self):
self.login_as(self.user)

def test_enables_github_copilot(self):
with self.feature("organizations:integrations-github-copilot-agent"):
response = self.get_success_response(self.organization.slug, "github_copilot")
response = self.get_success_response(self.organization.slug, "github_copilot")

integration = Integration.objects.get(provider="github_copilot")
assert OrganizationIntegration.objects.filter(
Expand All @@ -34,15 +33,11 @@ def test_returns_400_for_provider_without_direct_enable(self):
self.get_error_response(self.organization.slug, "cursor", status_code=400)

def test_prevents_duplicate_installation(self):
with self.feature("organizations:integrations-github-copilot-agent"):
self.get_success_response(self.organization.slug, "github_copilot")
self.get_error_response(self.organization.slug, "github_copilot", status_code=400)
self.get_success_response(self.organization.slug, "github_copilot")
self.get_error_response(self.organization.slug, "github_copilot", status_code=400)

assert Integration.objects.filter(provider="github_copilot").count() == 1

def test_returns_404_when_feature_flag_disabled(self):
self.get_error_response(self.organization.slug, "github_copilot", status_code=404)

def test_requires_org_write_permission(self):
member = self.create_user()
self.create_member(organization=self.organization, user=member, role="member")
Expand Down
7 changes: 2 additions & 5 deletions tests/sentry/integrations/github_copilot/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ def setUp(self):
def test_key(self):
assert self.provider.key == "github_copilot"

def test_requires_feature_flag_true(self):
assert self.provider.requires_feature_flag is True

def test_feature_flag_name(self):
assert self.provider.feature_flag_name == "organizations:integrations-github-copilot-agent"
def test_requires_feature_flag_false(self):
assert self.provider.requires_feature_flag is False

def test_no_pipeline_views(self):
assert self.provider.get_pipeline_views() == []
Expand Down
Loading