We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update GitHub integration to support generic issue types (ticketing feature)
Update the GitHub integration so that it displays the `IssueEvidence` for a generic issue type. See https://github.com/getsentry/sentry/pull/41041 for how it was done for performance issues as it'll be similar.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/sentry/integrations/github/issues.py`
Content:
```
1 from __future__ import annotations
2 
3 from typing import Any, Mapping, Sequence
4 
5 from django.urls import reverse
6 
7 from sentry.eventstore.models import Event
8 from sentry.integrations.mixins.issues import MAX_CHAR, IssueBasicMixin
9 from sentry.models import ExternalIssue, Group, User
10 from sentry.shared_integrations.exceptions import ApiError, IntegrationError
11 from sentry.types.issues import GroupCategory
12 from sentry.utils.http import absolute_uri
13 from sentry.utils.strings import truncatechars
14 
15 
16 class GitHubIssueBasic(IssueBasicMixin):  # type: ignore
17     def make_external_key(self, data: Mapping[str, Any]) -> str:
18         return "{}#{}".format(data["repo"], data["key"])
19 
20     def get_issue_url(self, key: str) -> str:
21         domain_name, user = self.model.metadata["domain_name"].split("/")
22         repo, issue_id = key.split("#")
23         return f"https://{domain_name}/{repo}/issues/{issue_id}"
24 
25     def get_performance_issue_body(self, event: Event) -> str:
26         (
27             transaction_name,
28             parent_span,
29             num_repeating_spans,
30             repeating_spans,
31         ) = self.get_performance_issue_description_data(event)
32 
33         body = "|  |  |\n"
34         body += "| ------------- | --------------- |\n"
35         body += f"| **Transaction Name** | {truncatechars(transaction_name, MAX_CHAR)} |\n"
36         body += f"| **Parent Span** | {truncatechars(parent_span, MAX_CHAR)} |\n"
37         body += f"| **Repeating Spans ({num_repeating_spans})** | {truncatechars(repeating_spans, MAX_CHAR)} |"
38         return body
39 
40     def get_group_description(self, group: Group, event: Event, **kwargs: Any) -> str:
41         output = self.get_group_link(group, **kwargs)
42 
43         if group.issue_category == GroupCategory.PERFORMANCE:
44             body = self.get_performance_issue_body(event)
45             output.extend([body])
46 
47         else:
48             body = self.get_group_body(group, event)
49             if body:
50                 output.extend(["", "```", body, "```"])
51         return "\n".join(output)
52 
53     def after_link_issue(self, external_issue: ExternalIssue, **kwargs: Any) -> None:
54         data = kwargs["data"]
55         client = self.get_client()
56 
57         repo, issue_num = external_issue.key.split("#")
58         if not repo:
59             raise IntegrationError("repo must be provided")
60 
61         if not issue_num:
62             raise IntegrationError("issue number must be provided")
63 
64         comment = data.get("comment")
65         if comment:
66             try:
67                 client.create_comment(repo=repo, issue_id=issue_num, data={"body": comment})
68             except ApiError as e:
69                 raise IntegrationError(self.message_from_error(e))
70 
71     def get_persisted_default_config_fields(self) -> Sequence[str]:
72         return ["repo"]
73 
74     def create_default_repo_choice(self, default_repo: str) -> tuple[str, str]:
75         return default_repo, default_repo.split("/")[1]
76 
77     def get_create_issue_config(
78         self, group: Group, user: User, **kwargs: Any
79     ) -> Sequence[Mapping[str, Any]]:
80         kwargs["link_referrer"] = "github_integration"
81         fields = super().get_create_issue_config(group, user, **kwargs)
82         default_repo, repo_choices = self.get_repository_choices(group, **kwargs)
83 
84         assignees = self.get_allowed_assignees(default_repo) if default_repo else []
85 
86         org = group.organization
87         autocomplete_url = reverse(
88             "sentry-extensions-github-search", args=[org.slug, self.model.id]
89         )
90 
91         return [
92             {
93                 "name": "repo",
94                 "label": "GitHub Repository",
95                 "type": "select",
96                 "default": default_repo,
97                 "choices": repo_choices,
98                 "url": autocomplete_url,
99                 "updatesForm": True,
100                 "required": True,
101             },
102             *fields,
103             {
104                 "name": "assignee",
105                 "label": "Assignee",
106                 "default": "",
107                 "type": "select",
108                 "required": False,
109                 "choices": assignees,
110             },
111         ]
112 
113     def create_issue(self, data: Mapping[str, Any], **kwargs: Any) -> Mapping[str, Any]:
114         client = self.get_client()
115 
116         repo = data.get("repo")
117 
118         if not repo:
119             raise IntegrationError("repo kwarg must be provided")
120 
121         try:
122             issue = client.create_issue(
123                 repo=repo,
124                 data={
125                     "title": data["title"],
126                     "body": data["description"],
127                     "assignee": data.get("assignee"),
128                 },
129             )
130         except ApiError as e:
131             raise IntegrationError(self.message_from_error(e))
132 
133         return {
134             "key": issue["number"],
135             "title": issue["title"],
136             "description": issue["body"],
137             "url": issue["html_url"],
138             "repo": repo,
139         }
140 
141     def get_link_issue_config(self, group: Group, **kwargs: Any) -> Sequence[Mapping[str, Any]]:
142         default_repo, repo_choices = self.get_repository_choices(group, **kwargs)
143 
144         org = group.organization
145         autocomplete_url = reverse(
146             "sentry-extensions-github-search", args=[org.slug, self.model.id]
147         )
148 
149         return [
150             {
151                 "name": "repo",
152                 "label": "GitHub Repository",
153                 "type": "select",
154                 "default": default_repo,
155                 "choices": repo_choices,
156                 "url": autocomplete_url,
157                 "required": True,
158                 "updatesForm": True,
159             },
160             {
161                 "name": "externalIssue",
162                 "label": "Issue",
163                 "default": "",
164                 "choices": [],
165                 "type": "select",
166                 "url": autocomplete_url,
167                 "required": True,
168             },
169             {
170                 "name": "comment",
171                 "label": "Comment",
172                 "default": "Sentry issue: [{issue_id}]({url})".format(
173                     url=absolute_uri(
174                         group.get_absolute_url(params={"referrer": "github_integration"})
175                     ),
176                     issue_id=group.qualified_short_id,
177                 ),
178                 "type": "textarea",
179                 "required": False,
180                 "autosize": True,
181                 "help": "Leave blank if you don't want to add a comment to the GitHub issue.",
182             },
183         ]
184 
185     def get_issue(self, issue_id: str, **kwargs: Any) -> Mapping[str, Any]:
186         data = kwargs["data"]
187         repo = data.get("repo")
188         issue_num = data.get("externalIssue")
189         client = self.get_client()
190 
191         if not repo:
192             raise IntegrationError("repo must be provided")
193 
194         if not issue_num:
195             raise IntegrationError("issue must be provided")
196 
197         try:
198             issue = client.get_issue(repo, issue_num)
199         except ApiError as e:
200             raise IntegrationError(self.message_from_error(e))
201 
202         return {
203             "key": issue["number"],
204             "title": issue["title"],
205             "description": issue["body"],
206             "url": issue["html_url"],
207             "repo": repo,
208         }
209 
210     def get_allowed_assignees(self, repo: str) -> Sequence[tuple[str, str]]:
211         client = self.get_client()
212         try:
213             response = client.get_assignees(repo)
214         except Exception as e:
215             raise self.raise_error(e)
216 
217         users = tuple((u["login"], u["login"]) for u in response)
218 
219         return (("", "Unassigned"),) + users
220 
221     def get_repo_issues(self, repo: str) -> Sequence[tuple[str, str]]:
222         client = self.get_client()
223         try:
224             response = client.get_issues(repo)
225         except Exception as e:
226             raise self.raise_error(e)
227 
228         issues = tuple((i["number"], "#{} {}".format(i["number"], i["title"])) for i in response)
229 
230         return issues
231
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/sentry/integrations/github/issues.py b/src/sentry/integrations/github/issues.py
--- a/src/sentry/integrations/github/issues.py
+++ b/src/sentry/integrations/github/issues.py
@@ -1,10 +1,11 @@
 from __future__ import annotations
 
+from operator import attrgetter
 from typing import Any, Mapping, Sequence
 
 from django.urls import reverse
 
-from sentry.eventstore.models import Event
+from sentry.eventstore.models import Event, GroupEvent
 from sentry.integrations.mixins.issues import MAX_CHAR, IssueBasicMixin
 from sentry.models import ExternalIssue, Group, User
 from sentry.shared_integrations.exceptions import ApiError, IntegrationError
@@ -37,13 +38,25 @@
         body += f"| **Repeating Spans ({num_repeating_spans})** | {truncatechars(repeating_spans, MAX_CHAR)} |"
         return body
 
-    def get_group_description(self, group: Group, event: Event, **kwargs: Any) -> str:
+    def get_generic_issue_body(self, event: GroupEvent) -> str:
+        body = "|  |  |\n"
+        body += "| ------------- | --------------- |\n"
+        for evidence in sorted(
+            event.occurrence.evidence_display, key=attrgetter("important"), reverse=True
+        ):
+            body += f"| **{evidence.name}** | {truncatechars(evidence.value, MAX_CHAR)} |\n"
+
+        return body[:-2]
+
+    def get_group_description(self, group: Group, event: Event | GroupEvent, **kwargs: Any) -> str:
         output = self.get_group_link(group, **kwargs)
 
         if group.issue_category == GroupCategory.PERFORMANCE:
             body = self.get_performance_issue_body(event)
             output.extend([body])
-
+        elif isinstance(event, GroupEvent) and event.occurrence is not None:
+            body = self.get_generic_issue_body(event)
+            output.extend([body])
         else:
             body = self.get_group_body(group, event)
             if body:

{"golden_diff": "diff --git a/src/sentry/integrations/github/issues.py b/src/sentry/integrations/github/issues.py\n--- a/src/sentry/integrations/github/issues.py\n+++ b/src/sentry/integrations/github/issues.py\n@@ -1,10 +1,11 @@\n from __future__ import annotations\n \n+from operator import attrgetter\n from typing import Any, Mapping, Sequence\n \n from django.urls import reverse\n \n-from sentry.eventstore.models import Event\n+from sentry.eventstore.models import Event, GroupEvent\n from sentry.integrations.mixins.issues import MAX_CHAR, IssueBasicMixin\n from sentry.models import ExternalIssue, Group, User\n from sentry.shared_integrations.exceptions import ApiError, IntegrationError\n@@ -37,13 +38,25 @@\n         body += f\"| **Repeating Spans ({num_repeating_spans})** | {truncatechars(repeating_spans, MAX_CHAR)} |\"\n         return body\n \n-    def get_group_description(self, group: Group, event: Event, **kwargs: Any) -> str:\n+    def get_generic_issue_body(self, event: GroupEvent) -> str:\n+        body = \"|  |  |\\n\"\n+        body += \"| ------------- | --------------- |\\n\"\n+        for evidence in sorted(\n+            event.occurrence.evidence_display, key=attrgetter(\"important\"), reverse=True\n+        ):\n+            body += f\"| **{evidence.name}** | {truncatechars(evidence.value, MAX_CHAR)} |\\n\"\n+\n+        return body[:-2]\n+\n+    def get_group_description(self, group: Group, event: Event | GroupEvent, **kwargs: Any) -> str:\n         output = self.get_group_link(group, **kwargs)\n \n         if group.issue_category == GroupCategory.PERFORMANCE:\n             body = self.get_performance_issue_body(event)\n             output.extend([body])\n-\n+        elif isinstance(event, GroupEvent) and event.occurrence is not None:\n+            body = self.get_generic_issue_body(event)\n+            output.extend([body])\n         else:\n             body = self.get_group_body(group, event)\n             if body:\n", "issue": "Update GitHub integration to support generic issue types (ticketing feature)\nUpdate the GitHub integration so that it displays the `IssueEvidence` for a generic issue type. See https://github.com/getsentry/sentry/pull/41041 for how it was done for performance issues as it'll be similar.\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom typing import Any, Mapping, Sequence\n\nfrom django.urls import reverse\n\nfrom sentry.eventstore.models import Event\nfrom sentry.integrations.mixins.issues import MAX_CHAR, IssueBasicMixin\nfrom sentry.models import ExternalIssue, Group, User\nfrom sentry.shared_integrations.exceptions import ApiError, IntegrationError\nfrom sentry.types.issues import GroupCategory\nfrom sentry.utils.http import absolute_uri\nfrom sentry.utils.strings import truncatechars\n\n\nclass GitHubIssueBasic(IssueBasicMixin):  # type: ignore\n    def make_external_key(self, data: Mapping[str, Any]) -> str:\n        return \"{}#{}\".format(data[\"repo\"], data[\"key\"])\n\n    def get_issue_url(self, key: str) -> str:\n        domain_name, user = self.model.metadata[\"domain_name\"].split(\"/\")\n        repo, issue_id = key.split(\"#\")\n        return f\"https://{domain_name}/{repo}/issues/{issue_id}\"\n\n    def get_performance_issue_body(self, event: Event) -> str:\n        (\n            transaction_name,\n            parent_span,\n            num_repeating_spans,\n            repeating_spans,\n        ) = self.get_performance_issue_description_data(event)\n\n        body = \"|  |  |\\n\"\n        body += \"| ------------- | --------------- |\\n\"\n        body += f\"| **Transaction Name** | {truncatechars(transaction_name, MAX_CHAR)} |\\n\"\n        body += f\"| **Parent Span** | {truncatechars(parent_span, MAX_CHAR)} |\\n\"\n        body += f\"| **Repeating Spans ({num_repeating_spans})** | {truncatechars(repeating_spans, MAX_CHAR)} |\"\n        return body\n\n    def get_group_description(self, group: Group, event: Event, **kwargs: Any) -> str:\n        output = self.get_group_link(group, **kwargs)\n\n        if group.issue_category == GroupCategory.PERFORMANCE:\n            body = self.get_performance_issue_body(event)\n            output.extend([body])\n\n        else:\n            body = self.get_group_body(group, event)\n            if body:\n                output.extend([\"\", \"```\", body, \"```\"])\n        return \"\\n\".join(output)\n\n    def after_link_issue(self, external_issue: ExternalIssue, **kwargs: Any) -> None:\n        data = kwargs[\"data\"]\n        client = self.get_client()\n\n        repo, issue_num = external_issue.key.split(\"#\")\n        if not repo:\n            raise IntegrationError(\"repo must be provided\")\n\n        if not issue_num:\n            raise IntegrationError(\"issue number must be provided\")\n\n        comment = data.get(\"comment\")\n        if comment:\n            try:\n                client.create_comment(repo=repo, issue_id=issue_num, data={\"body\": comment})\n            except ApiError as e:\n                raise IntegrationError(self.message_from_error(e))\n\n    def get_persisted_default_config_fields(self) -> Sequence[str]:\n        return [\"repo\"]\n\n    def create_default_repo_choice(self, default_repo: str) -> tuple[str, str]:\n        return default_repo, default_repo.split(\"/\")[1]\n\n    def get_create_issue_config(\n        self, group: Group, user: User, **kwargs: Any\n    ) -> Sequence[Mapping[str, Any]]:\n        kwargs[\"link_referrer\"] = \"github_integration\"\n        fields = super().get_create_issue_config(group, user, **kwargs)\n        default_repo, repo_choices = self.get_repository_choices(group, **kwargs)\n\n        assignees = self.get_allowed_assignees(default_repo) if default_repo else []\n\n        org = group.organization\n        autocomplete_url = reverse(\n            \"sentry-extensions-github-search\", args=[org.slug, self.model.id]\n        )\n\n        return [\n            {\n                \"name\": \"repo\",\n                \"label\": \"GitHub Repository\",\n                \"type\": \"select\",\n                \"default\": default_repo,\n                \"choices\": repo_choices,\n                \"url\": autocomplete_url,\n                \"updatesForm\": True,\n                \"required\": True,\n            },\n            *fields,\n            {\n                \"name\": \"assignee\",\n                \"label\": \"Assignee\",\n                \"default\": \"\",\n                \"type\": \"select\",\n                \"required\": False,\n                \"choices\": assignees,\n            },\n        ]\n\n    def create_issue(self, data: Mapping[str, Any], **kwargs: Any) -> Mapping[str, Any]:\n        client = self.get_client()\n\n        repo = data.get(\"repo\")\n\n        if not repo:\n            raise IntegrationError(\"repo kwarg must be provided\")\n\n        try:\n            issue = client.create_issue(\n                repo=repo,\n                data={\n                    \"title\": data[\"title\"],\n                    \"body\": data[\"description\"],\n                    \"assignee\": data.get(\"assignee\"),\n                },\n            )\n        except ApiError as e:\n            raise IntegrationError(self.message_from_error(e))\n\n        return {\n            \"key\": issue[\"number\"],\n            \"title\": issue[\"title\"],\n            \"description\": issue[\"body\"],\n            \"url\": issue[\"html_url\"],\n            \"repo\": repo,\n        }\n\n    def get_link_issue_config(self, group: Group, **kwargs: Any) -> Sequence[Mapping[str, Any]]:\n        default_repo, repo_choices = self.get_repository_choices(group, **kwargs)\n\n        org = group.organization\n        autocomplete_url = reverse(\n            \"sentry-extensions-github-search\", args=[org.slug, self.model.id]\n        )\n\n        return [\n            {\n                \"name\": \"repo\",\n                \"label\": \"GitHub Repository\",\n                \"type\": \"select\",\n                \"default\": default_repo,\n                \"choices\": repo_choices,\n                \"url\": autocomplete_url,\n                \"required\": True,\n                \"updatesForm\": True,\n            },\n            {\n                \"name\": \"externalIssue\",\n                \"label\": \"Issue\",\n                \"default\": \"\",\n                \"choices\": [],\n                \"type\": \"select\",\n                \"url\": autocomplete_url,\n                \"required\": True,\n            },\n            {\n                \"name\": \"comment\",\n                \"label\": \"Comment\",\n                \"default\": \"Sentry issue: [{issue_id}]({url})\".format(\n                    url=absolute_uri(\n                        group.get_absolute_url(params={\"referrer\": \"github_integration\"})\n                    ),\n                    issue_id=group.qualified_short_id,\n                ),\n                \"type\": \"textarea\",\n                \"required\": False,\n                \"autosize\": True,\n                \"help\": \"Leave blank if you don't want to add a comment to the GitHub issue.\",\n            },\n        ]\n\n    def get_issue(self, issue_id: str, **kwargs: Any) -> Mapping[str, Any]:\n        data = kwargs[\"data\"]\n        repo = data.get(\"repo\")\n        issue_num = data.get(\"externalIssue\")\n        client = self.get_client()\n\n        if not repo:\n            raise IntegrationError(\"repo must be provided\")\n\n        if not issue_num:\n            raise IntegrationError(\"issue must be provided\")\n\n        try:\n            issue = client.get_issue(repo, issue_num)\n        except ApiError as e:\n            raise IntegrationError(self.message_from_error(e))\n\n        return {\n            \"key\": issue[\"number\"],\n            \"title\": issue[\"title\"],\n            \"description\": issue[\"body\"],\n            \"url\": issue[\"html_url\"],\n            \"repo\": repo,\n        }\n\n    def get_allowed_assignees(self, repo: str) -> Sequence[tuple[str, str]]:\n        client = self.get_client()\n        try:\n            response = client.get_assignees(repo)\n        except Exception as e:\n            raise self.raise_error(e)\n\n        users = tuple((u[\"login\"], u[\"login\"]) for u in response)\n\n        return ((\"\", \"Unassigned\"),) + users\n\n    def get_repo_issues(self, repo: str) -> Sequence[tuple[str, str]]:\n        client = self.get_client()\n        try:\n            response = client.get_issues(repo)\n        except Exception as e:\n            raise self.raise_error(e)\n\n        issues = tuple((i[\"number\"], \"#{} {}\".format(i[\"number\"], i[\"title\"])) for i in response)\n\n        return issues\n", "path": "src/sentry/integrations/github/issues.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom operator import attrgetter\nfrom typing import Any, Mapping, Sequence\n\nfrom django.urls import reverse\n\nfrom sentry.eventstore.models import Event, GroupEvent\nfrom sentry.integrations.mixins.issues import MAX_CHAR, IssueBasicMixin\nfrom sentry.models import ExternalIssue, Group, User\nfrom sentry.shared_integrations.exceptions import ApiError, IntegrationError\nfrom sentry.types.issues import GroupCategory\nfrom sentry.utils.http import absolute_uri\nfrom sentry.utils.strings import truncatechars\n\n\nclass GitHubIssueBasic(IssueBasicMixin):  # type: ignore\n    def make_external_key(self, data: Mapping[str, Any]) -> str:\n        return \"{}#{}\".format(data[\"repo\"], data[\"key\"])\n\n    def get_issue_url(self, key: str) -> str:\n        domain_name, user = self.model.metadata[\"domain_name\"].split(\"/\")\n        repo, issue_id = key.split(\"#\")\n        return f\"https://{domain_name}/{repo}/issues/{issue_id}\"\n\n    def get_performance_issue_body(self, event: Event) -> str:\n        (\n            transaction_name,\n            parent_span,\n            num_repeating_spans,\n            repeating_spans,\n        ) = self.get_performance_issue_description_data(event)\n\n        body = \"|  |  |\\n\"\n        body += \"| ------------- | --------------- |\\n\"\n        body += f\"| **Transaction Name** | {truncatechars(transaction_name, MAX_CHAR)} |\\n\"\n        body += f\"| **Parent Span** | {truncatechars(parent_span, MAX_CHAR)} |\\n\"\n        body += f\"| **Repeating Spans ({num_repeating_spans})** | {truncatechars(repeating_spans, MAX_CHAR)} |\"\n        return body\n\n    def get_generic_issue_body(self, event: GroupEvent) -> str:\n        body = \"|  |  |\\n\"\n        body += \"| ------------- | --------------- |\\n\"\n        for evidence in sorted(\n            event.occurrence.evidence_display, key=attrgetter(\"important\"), reverse=True\n        ):\n            body += f\"| **{evidence.name}** | {truncatechars(evidence.value, MAX_CHAR)} |\\n\"\n\n        return body[:-2]\n\n    def get_group_description(self, group: Group, event: Event | GroupEvent, **kwargs: Any) -> str:\n        output = self.get_group_link(group, **kwargs)\n\n        if group.issue_category == GroupCategory.PERFORMANCE:\n            body = self.get_performance_issue_body(event)\n            output.extend([body])\n        elif isinstance(event, GroupEvent) and event.occurrence is not None:\n            body = self.get_generic_issue_body(event)\n            output.extend([body])\n        else:\n            body = self.get_group_body(group, event)\n            if body:\n                output.extend([\"\", \"```\", body, \"```\"])\n        return \"\\n\".join(output)\n\n    def after_link_issue(self, external_issue: ExternalIssue, **kwargs: Any) -> None:\n        data = kwargs[\"data\"]\n        client = self.get_client()\n\n        repo, issue_num = external_issue.key.split(\"#\")\n        if not repo:\n            raise IntegrationError(\"repo must be provided\")\n\n        if not issue_num:\n            raise IntegrationError(\"issue number must be provided\")\n\n        comment = data.get(\"comment\")\n        if comment:\n            try:\n                client.create_comment(repo=repo, issue_id=issue_num, data={\"body\": comment})\n            except ApiError as e:\n                raise IntegrationError(self.message_from_error(e))\n\n    def get_persisted_default_config_fields(self) -> Sequence[str]:\n        return [\"repo\"]\n\n    def create_default_repo_choice(self, default_repo: str) -> tuple[str, str]:\n        return default_repo, default_repo.split(\"/\")[1]\n\n    def get_create_issue_config(\n        self, group: Group, user: User, **kwargs: Any\n    ) -> Sequence[Mapping[str, Any]]:\n        kwargs[\"link_referrer\"] = \"github_integration\"\n        fields = super().get_create_issue_config(group, user, **kwargs)\n        default_repo, repo_choices = self.get_repository_choices(group, **kwargs)\n\n        assignees = self.get_allowed_assignees(default_repo) if default_repo else []\n\n        org = group.organization\n        autocomplete_url = reverse(\n            \"sentry-extensions-github-search\", args=[org.slug, self.model.id]\n        )\n\n        return [\n            {\n                \"name\": \"repo\",\n                \"label\": \"GitHub Repository\",\n                \"type\": \"select\",\n                \"default\": default_repo,\n                \"choices\": repo_choices,\n                \"url\": autocomplete_url,\n                \"updatesForm\": True,\n                \"required\": True,\n            },\n            *fields,\n            {\n                \"name\": \"assignee\",\n                \"label\": \"Assignee\",\n                \"default\": \"\",\n                \"type\": \"select\",\n                \"required\": False,\n                \"choices\": assignees,\n            },\n        ]\n\n    def create_issue(self, data: Mapping[str, Any], **kwargs: Any) -> Mapping[str, Any]:\n        client = self.get_client()\n\n        repo = data.get(\"repo\")\n\n        if not repo:\n            raise IntegrationError(\"repo kwarg must be provided\")\n\n        try:\n            issue = client.create_issue(\n                repo=repo,\n                data={\n                    \"title\": data[\"title\"],\n                    \"body\": data[\"description\"],\n                    \"assignee\": data.get(\"assignee\"),\n                },\n            )\n        except ApiError as e:\n            raise IntegrationError(self.message_from_error(e))\n\n        return {\n            \"key\": issue[\"number\"],\n            \"title\": issue[\"title\"],\n            \"description\": issue[\"body\"],\n            \"url\": issue[\"html_url\"],\n            \"repo\": repo,\n        }\n\n    def get_link_issue_config(self, group: Group, **kwargs: Any) -> Sequence[Mapping[str, Any]]:\n        default_repo, repo_choices = self.get_repository_choices(group, **kwargs)\n\n        org = group.organization\n        autocomplete_url = reverse(\n            \"sentry-extensions-github-search\", args=[org.slug, self.model.id]\n        )\n\n        return [\n            {\n                \"name\": \"repo\",\n                \"label\": \"GitHub Repository\",\n                \"type\": \"select\",\n                \"default\": default_repo,\n                \"choices\": repo_choices,\n                \"url\": autocomplete_url,\n                \"required\": True,\n                \"updatesForm\": True,\n            },\n            {\n                \"name\": \"externalIssue\",\n                \"label\": \"Issue\",\n                \"default\": \"\",\n                \"choices\": [],\n                \"type\": \"select\",\n                \"url\": autocomplete_url,\n                \"required\": True,\n            },\n            {\n                \"name\": \"comment\",\n                \"label\": \"Comment\",\n                \"default\": \"Sentry issue: [{issue_id}]({url})\".format(\n                    url=absolute_uri(\n                        group.get_absolute_url(params={\"referrer\": \"github_integration\"})\n                    ),\n                    issue_id=group.qualified_short_id,\n                ),\n                \"type\": \"textarea\",\n                \"required\": False,\n                \"autosize\": True,\n                \"help\": \"Leave blank if you don't want to add a comment to the GitHub issue.\",\n            },\n        ]\n\n    def get_issue(self, issue_id: str, **kwargs: Any) -> Mapping[str, Any]:\n        data = kwargs[\"data\"]\n        repo = data.get(\"repo\")\n        issue_num = data.get(\"externalIssue\")\n        client = self.get_client()\n\n        if not repo:\n            raise IntegrationError(\"repo must be provided\")\n\n        if not issue_num:\n            raise IntegrationError(\"issue must be provided\")\n\n        try:\n            issue = client.get_issue(repo, issue_num)\n        except ApiError as e:\n            raise IntegrationError(self.message_from_error(e))\n\n        return {\n            \"key\": issue[\"number\"],\n            \"title\": issue[\"title\"],\n            \"description\": issue[\"body\"],\n            \"url\": issue[\"html_url\"],\n            \"repo\": repo,\n        }\n\n    def get_allowed_assignees(self, repo: str) -> Sequence[tuple[str, str]]:\n        client = self.get_client()\n        try:\n            response = client.get_assignees(repo)\n        except Exception as e:\n            raise self.raise_error(e)\n\n        users = tuple((u[\"login\"], u[\"login\"]) for u in response)\n\n        return ((\"\", \"Unassigned\"),) + users\n\n    def get_repo_issues(self, repo: str) -> Sequence[tuple[str, str]]:\n        client = self.get_client()\n        try:\n            response = client.get_issues(repo)\n        except Exception as e:\n            raise self.raise_error(e)\n\n        issues = tuple((i[\"number\"], \"#{} {}\".format(i[\"number\"], i[\"title\"])) for i in response)\n\n        return issues\n", "path": "src/sentry/integrations/github/issues.py"}]}