Skip to content

Commit 636110d

Browse files
committed
ref: run_pr_comment_workflow
1 parent 04ca5ca commit 636110d

File tree

3 files changed

+267
-259
lines changed

3 files changed

+267
-259
lines changed
+2-239
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,12 @@
11
from __future__ import annotations
22

3-
import itertools
43
import logging
5-
from typing import Any
64

7-
from sentry.constants import EXTENSION_LANGUAGE_MAP, ObjectStatus
8-
from sentry.integrations.services.integration import integration_service
9-
from sentry.integrations.source_code_management.commit_context import (
10-
OPEN_PR_METRICS_BASE,
11-
CommitContextIntegration,
12-
)
13-
from sentry.integrations.source_code_management.language_parsers import PATCH_PARSERS
14-
from sentry.models.organization import Organization
15-
from sentry.models.pullrequest import CommentType, PullRequest
16-
from sentry.models.repository import Repository
17-
from sentry.shared_integrations.exceptions import ApiError
5+
from sentry.integrations.source_code_management.commit_context import run_open_pr_comment_workflow
186
from sentry.silo.base import SiloMode
197
from sentry.tasks.base import instrumented_task
208
from sentry.taskworker.config import TaskworkerConfig
219
from sentry.taskworker.namespaces import integrations_tasks
22-
from sentry.utils import metrics
2310

2411
logger = logging.getLogger(__name__)
2512

@@ -32,228 +19,4 @@
3219
),
3320
)
3421
def open_pr_comment_workflow(pr_id: int) -> None:
35-
logger.info("github.open_pr_comment.start_workflow")
36-
37-
# CHECKS
38-
# check PR exists to get PR key
39-
try:
40-
pr = PullRequest.objects.get(id=pr_id)
41-
assert isinstance(pr, PullRequest)
42-
except PullRequest.DoesNotExist:
43-
logger.info("github.open_pr_comment.pr_missing")
44-
metrics.incr(
45-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
46-
tags={"type": "missing_pr"},
47-
)
48-
return
49-
50-
# check org option
51-
try:
52-
organization = Organization.objects.get_from_cache(id=pr.organization_id)
53-
assert isinstance(organization, Organization)
54-
except Organization.DoesNotExist:
55-
logger.exception("github.open_pr_comment.org_missing")
56-
metrics.incr(
57-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
58-
tags={"type": "missing_org"},
59-
)
60-
return
61-
62-
# check PR repo exists to get repo name
63-
try:
64-
repo = Repository.objects.get(id=pr.repository_id)
65-
assert isinstance(repo, Repository)
66-
except Repository.DoesNotExist:
67-
logger.info(
68-
"github.open_pr_comment.repo_missing", extra={"organization_id": organization.id}
69-
)
70-
metrics.incr(
71-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
72-
tags={"type": "missing_repo"},
73-
)
74-
return
75-
76-
# check integration exists to hit Github API with client
77-
integration = integration_service.get_integration(
78-
integration_id=repo.integration_id, status=ObjectStatus.ACTIVE
79-
)
80-
if not integration:
81-
logger.info(
82-
"github.open_pr_comment.integration_missing", extra={"organization_id": organization.id}
83-
)
84-
metrics.incr(
85-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
86-
tags={"type": "missing_integration"},
87-
)
88-
return
89-
90-
installation = integration.get_installation(organization_id=organization.id)
91-
assert isinstance(installation, CommitContextIntegration)
92-
93-
# CREATING THE COMMENT
94-
95-
# fetch the files in the PR and determine if it is safe to comment
96-
pr_files = installation.get_pr_files_safe_for_comment(repo=repo, pr=pr)
97-
98-
if len(pr_files) == 0:
99-
logger.info(
100-
"github.open_pr_comment.not_safe_for_comment", extra={"file_count": len(pr_files)}
101-
)
102-
metrics.incr(
103-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
104-
tags={"type": "unsafe_for_comment"},
105-
)
106-
return
107-
108-
pullrequest_files = installation.get_pr_files(pr_files)
109-
110-
issue_table_contents = {}
111-
top_issues_per_file = []
112-
113-
patch_parsers = PATCH_PARSERS
114-
# NOTE: if we are testing beta patch parsers, add check here
115-
116-
file_extensions = set()
117-
# fetch issues related to the files
118-
for file in pullrequest_files:
119-
projects, sentry_filenames = installation.get_projects_and_filenames_from_source_file(
120-
organization=organization, repo=repo, pr_filename=file.filename
121-
)
122-
if not len(projects) or not len(sentry_filenames):
123-
continue
124-
125-
file_extension = file.filename.split(".")[-1]
126-
logger.info(
127-
"github.open_pr_comment.file_extension",
128-
extra={
129-
"organization_id": organization.id,
130-
"repository_id": repo.id,
131-
"extension": file_extension,
132-
},
133-
)
134-
135-
language_parser = patch_parsers.get(file.filename.split(".")[-1], None)
136-
if not language_parser:
137-
logger.info(
138-
"github.open_pr_comment.missing_parser", extra={"extension": file_extension}
139-
)
140-
metrics.incr(
141-
OPEN_PR_METRICS_BASE.format(integration="github", key="missing_parser"),
142-
tags={"extension": file_extension},
143-
)
144-
continue
145-
146-
function_names = language_parser.extract_functions_from_patch(file.patch)
147-
148-
if file_extension in ["js", "jsx"]:
149-
logger.info(
150-
"github.open_pr_comment.javascript",
151-
extra={
152-
"organization_id": organization.id,
153-
"repository_id": repo.id,
154-
"extension": file_extension,
155-
"has_function_names": bool(function_names),
156-
},
157-
)
158-
159-
if file_extension == ["php"]:
160-
logger.info(
161-
"github.open_pr_comment.php",
162-
extra={
163-
"organization_id": organization.id,
164-
"repository_id": repo.id,
165-
"extension": file_extension,
166-
"has_function_names": bool(function_names),
167-
},
168-
)
169-
170-
if file_extension == ["rb"]:
171-
logger.info(
172-
"github.open_pr_comment.ruby",
173-
extra={
174-
"organization_id": organization.id,
175-
"repository_id": repo.id,
176-
"extension": file_extension,
177-
"has_function_names": bool(function_names),
178-
},
179-
)
180-
181-
if not len(function_names):
182-
continue
183-
184-
top_issues = installation.get_top_5_issues_by_count_for_file(
185-
list(projects), list(sentry_filenames), list(function_names)
186-
)
187-
if not len(top_issues):
188-
continue
189-
190-
top_issues_per_file.append(top_issues)
191-
file_extensions.add(file_extension)
192-
193-
issue_table_contents[file.filename] = installation.get_issue_table_contents(top_issues)
194-
195-
if not len(issue_table_contents):
196-
logger.info("github.open_pr_comment.no_issues")
197-
# don't leave a comment if no issues for files in PR
198-
metrics.incr(OPEN_PR_METRICS_BASE.format(integration="github", key="no_issues"))
199-
return
200-
201-
# format issues per file into comment
202-
issue_tables = []
203-
first_table = True
204-
for file in pullrequest_files:
205-
pr_filename = file.filename
206-
issue_table_content = issue_table_contents.get(pr_filename, None)
207-
208-
if issue_table_content is None:
209-
continue
210-
211-
if first_table:
212-
issue_table = installation.format_issue_table(
213-
pr_filename, issue_table_content, patch_parsers, toggle=False
214-
)
215-
first_table = False
216-
else:
217-
# toggle all tables but the first one
218-
issue_table = installation.format_issue_table(
219-
pr_filename, issue_table_content, patch_parsers, toggle=True
220-
)
221-
222-
issue_tables.append(issue_table)
223-
224-
comment_body = installation.format_open_pr_comment(issue_tables)
225-
226-
# list all issues in the comment
227-
issue_list: list[dict[str, Any]] = list(itertools.chain.from_iterable(top_issues_per_file))
228-
issue_id_list: list[int] = [issue["group_id"] for issue in issue_list]
229-
230-
# pick one language from the list of languages in the PR for analytics
231-
languages = [
232-
EXTENSION_LANGUAGE_MAP[extension]
233-
for extension in file_extensions
234-
if extension in EXTENSION_LANGUAGE_MAP
235-
]
236-
language = languages[0] if len(languages) else "not found"
237-
238-
try:
239-
installation.create_or_update_comment(
240-
repo=repo,
241-
pr_key=pr.key,
242-
comment_data={"body": comment_body},
243-
pullrequest_id=pr.id,
244-
issue_ids=issue_id_list,
245-
comment_type=CommentType.OPEN_PR,
246-
metrics_base=OPEN_PR_METRICS_BASE,
247-
language=language,
248-
)
249-
except ApiError as e:
250-
if installation.on_create_or_update_comment_error(
251-
api_error=e, metrics_base=OPEN_PR_METRICS_BASE
252-
):
253-
return
254-
255-
metrics.incr(
256-
OPEN_PR_METRICS_BASE.format(integration="github", key="error"),
257-
tags={"type": "api_error"},
258-
)
259-
raise
22+
run_open_pr_comment_workflow(integration_name="github", pullrequest_id=pr_id)

0 commit comments

Comments
 (0)