From 46177115b8cf1838dd02283ef5196e3b0e032488 Mon Sep 17 00:00:00 2001 From: Dan Fuller Date: Mon, 1 Jun 2026 16:02:40 -0700 Subject: [PATCH] ref(flags): Graduate organizations:integrations-github_enterprise-project-management GA flag rolled out to 100%. Remove the flag and make the gated behavior unconditional. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/sentry/features/temporary.py | 1 - .../github_enterprise/integration.py | 194 +++++++++--------- src/sentry/integrations/utils/sync.py | 4 +- .../github_enterprise/test_integration.py | 1 - 4 files changed, 95 insertions(+), 105 deletions(-) diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py index 79f9b5b8b87b67..17b68caf36ba56 100644 --- a/src/sentry/features/temporary.py +++ b/src/sentry/features/temporary.py @@ -137,7 +137,6 @@ def register_temporary_features(manager: FeatureManager) -> None: # API-driven integration setup pipeline (per-provider rollout) # ... # Project Management Integrations Feature Parity Flags - manager.add("organizations:integrations-github_enterprise-project-management", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) manager.add("organizations:integrations-gitlab-project-management", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True) # Temporary: log full Jira Cloud `issue.updated` webhook payloads so we can design project-change link rewriting. manager.add("organizations:jira-issue-updated-payload-logging", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False) diff --git a/src/sentry/integrations/github_enterprise/integration.py b/src/sentry/integrations/github_enterprise/integration.py index 35eb55121109e9..90c026bc763991 100644 --- a/src/sentry/integrations/github_enterprise/integration.py +++ b/src/sentry/integrations/github_enterprise/integration.py @@ -366,61 +366,58 @@ def _get_organization_config_default_values(self) -> list[dict[str, Any]]: """ config: list[dict[str, Any]] = [] - if features.has( - "organizations:integrations-github_enterprise-project-management", self.organization - ): - config.extend( - [ - { - "name": self.inbound_status_key, - "type": "boolean", - "label": _("Sync GitHub Status to Sentry"), - "help": _( - "When a GitHub issue is marked closed, resolve its linked issue in Sentry. " - "When a GitHub issue is reopened, unresolve its linked Sentry issue." - ), - "default": False, - }, - { - "name": self.inbound_assignee_key, - "type": "boolean", - "label": _("Sync Github Assignment to Sentry"), - "help": _( - "When an issue is assigned in GitHub, assign its linked Sentry issue to the same user." - ), - "default": False, - }, - { - "name": self.outbound_assignee_key, - "type": "boolean", - "label": _("Sync Sentry Assignment to GitHub"), - "help": _( - "When an issue is assigned in Sentry, assign its linked GitHub issue to the same user." - ), - "default": False, - }, - { - "name": self.resolution_strategy_key, - "label": "Resolve", - "type": "select", - "placeholder": "Resolve", - "choices": [ - ("resolve", "Resolve"), - ("resolve_current_release", "Resolve in Current Release"), - ("resolve_next_release", "Resolve in Next Release"), - ], - "help": _( - "Select what action to take on Sentry Issue when GitHub ticket is marked Closed." - ), - }, - { - "name": self.comment_key, - "type": "boolean", - "label": _("Sync Sentry Comments to GitHub"), - "help": _("Post comments from Sentry issues to linked GitHub issues"), - }, - ] - ) + config.extend( + [ + { + "name": self.inbound_status_key, + "type": "boolean", + "label": _("Sync GitHub Status to Sentry"), + "help": _( + "When a GitHub issue is marked closed, resolve its linked issue in Sentry. " + "When a GitHub issue is reopened, unresolve its linked Sentry issue." + ), + "default": False, + }, + { + "name": self.inbound_assignee_key, + "type": "boolean", + "label": _("Sync Github Assignment to Sentry"), + "help": _( + "When an issue is assigned in GitHub, assign its linked Sentry issue to the same user." + ), + "default": False, + }, + { + "name": self.outbound_assignee_key, + "type": "boolean", + "label": _("Sync Sentry Assignment to GitHub"), + "help": _( + "When an issue is assigned in Sentry, assign its linked GitHub issue to the same user." + ), + "default": False, + }, + { + "name": self.resolution_strategy_key, + "label": "Resolve", + "type": "select", + "placeholder": "Resolve", + "choices": [ + ("resolve", "Resolve"), + ("resolve_current_release", "Resolve in Current Release"), + ("resolve_next_release", "Resolve in Next Release"), + ], + "help": _( + "Select what action to take on Sentry Issue when GitHub ticket is marked Closed." + ), + }, + { + "name": self.comment_key, + "type": "boolean", + "label": _("Sync Sentry Comments to GitHub"), + "help": _("Post comments from Sentry issues to linked GitHub issues"), + }, + ] + ) return config @@ -430,55 +427,52 @@ def get_organization_config(self) -> list[dict[str, Any]]: """ config = self._get_organization_config_default_values() - if features.has( - "organizations:integrations-github_enterprise-project-management", self.organization - ): - # Async lookup for integration external projects in the frontend - # Get currently configured external projects to display their labels - current_repo_items = [] - external_projects = IntegrationExternalProject.objects.filter( - organization_integration_id=self.org_integration.id - ) + # Async lookup for integration external projects in the frontend + # Get currently configured external projects to display their labels + current_repo_items = [] + external_projects = IntegrationExternalProject.objects.filter( + organization_integration_id=self.org_integration.id + ) - if external_projects.exists(): - # Use the stored external_id from IntegrationExternalProject - current_repo_items = [ - {"value": project.external_id, "label": project.external_id} - for project in external_projects - ] + if external_projects.exists(): + # Use the stored external_id from IntegrationExternalProject + current_repo_items = [ + {"value": project.external_id, "label": project.external_id} + for project in external_projects + ] - config.insert( - 0, - { - "name": self.outbound_status_key, - "type": "choice_mapper", - "label": _("Sync Sentry Status to Github"), - "help": _( - "When a Sentry issue changes status, change the status of the linked ticket in Github." + config.insert( + 0, + { + "name": self.outbound_status_key, + "type": "choice_mapper", + "label": _("Sync Sentry Status to Github"), + "help": _( + "When a Sentry issue changes status, change the status of the linked ticket in Github." + ), + "addButtonText": _("Add Github Project"), + "addDropdown": { + "emptyMessage": _("All projects configured"), + "noResultsMessage": _("Could not find Github project"), + "items": current_repo_items, + "url": reverse( + "sentry-integration-github-search", + args=[self.organization.slug, self.model.id], ), - "addButtonText": _("Add Github Project"), - "addDropdown": { - "emptyMessage": _("All projects configured"), - "noResultsMessage": _("Could not find Github project"), - "items": current_repo_items, - "url": reverse( - "sentry-integration-github-search", - args=[self.organization.slug, self.model.id], - ), - "searchField": "repo", - }, - "mappedSelectors": { - "on_resolve": {"choices": GitHubIssueStatus.get_choices()}, - "on_unresolve": {"choices": GitHubIssueStatus.get_choices()}, - }, - "columnLabels": { - "on_resolve": _("When resolved"), - "on_unresolve": _("When unresolved"), - }, - "mappedColumnLabel": _("Github Project"), - "formatMessageValue": False, + "searchField": "repo", }, - ) + "mappedSelectors": { + "on_resolve": {"choices": GitHubIssueStatus.get_choices()}, + "on_unresolve": {"choices": GitHubIssueStatus.get_choices()}, + }, + "columnLabels": { + "on_resolve": _("When resolved"), + "on_unresolve": _("When unresolved"), + }, + "mappedColumnLabel": _("Github Project"), + "formatMessageValue": False, + }, + ) context = organization_service.get_organization_by_id( id=self.organization_id, include_projects=False, include_teams=False diff --git a/src/sentry/integrations/utils/sync.py b/src/sentry/integrations/utils/sync.py index 5bd44383026f62..7a79214937d53f 100644 --- a/src/sentry/integrations/utils/sync.py +++ b/src/sentry/integrations/utils/sync.py @@ -43,9 +43,7 @@ def should_sync_assignee_inbound( if provider == "github": return True elif provider == "github_enterprise": - return features.has( - "organizations:integrations-github_enterprise-project-management", organization - ) + return True elif provider == "gitlab": return features.has("organizations:integrations-gitlab-project-management", organization) return True diff --git a/tests/sentry/integrations/github_enterprise/test_integration.py b/tests/sentry/integrations/github_enterprise/test_integration.py index 94b4197a1d687a..6733160d905eae 100644 --- a/tests/sentry/integrations/github_enterprise/test_integration.py +++ b/tests/sentry/integrations/github_enterprise/test_integration.py @@ -460,7 +460,6 @@ def test_extract_source_path_from_source_url(self) -> None: ) @responses.activate - @with_feature("organizations:integrations-github_enterprise-project-management") def test_get_organization_config(self) -> None: # Mock the repositories endpoint responses.add(