Просмотр исходного кода

fix(codeowners): Allow files with size over 1MB (#62762)

Add the header "Accept: application/vnd.github.raw" when making the call
to get-repository-content
Jodi Jang 1 год назад
Родитель
Сommit
2fea524b54

+ 14 - 5
src/sentry/integrations/github/client.py

@@ -168,8 +168,10 @@ class GithubProxyClient(IntegrationProxyClient):
             )
             return prepared_request
 
-        prepared_request.headers["Accept"] = "application/vnd.github+json"
         prepared_request.headers["Authorization"] = f"Bearer {token}"
+        prepared_request.headers["Accept"] = "application/vnd.github+json"
+        if prepared_request.headers.get("Content-Type") == "application/raw; charset=utf-8":
+            prepared_request.headers["Accept"] = "application/vnd.github.raw"
 
         return prepared_request
 
@@ -615,16 +617,23 @@ class GitHubClientMixin(GithubProxyClient):
     def check_file(self, repo: Repository, path: str, version: str) -> BaseApiResponseX:
         return self.head_cached(path=f"/repos/{repo.name}/contents/{path}", params={"ref": version})
 
-    def get_file(self, repo: Repository, path: str, ref: str) -> str:
+    def get_file(self, repo: Repository, path: str, ref: str, codeowners: bool = False) -> str:
         """Get the contents of a file
 
         See https://docs.github.com/en/rest/reference/repos#get-repository-content
         """
         from base64 import b64decode
 
-        contents = self.get(path=f"/repos/{repo.name}/contents/{path}", params={"ref": ref})
-        encoded_content = contents["content"]
-        return b64decode(encoded_content).decode("utf-8")
+        headers = {"Content-Type": "application/raw; charset=utf-8"} if codeowners else {}
+        contents = self.get(
+            path=f"/repos/{repo.name}/contents/{path}",
+            params={"ref": ref},
+            raw_response=True if codeowners else False,
+            headers=headers,
+        )
+
+        result = contents.content if codeowners else b64decode(contents["content"]).decode("utf-8")
+        return result
 
     def get_blame_for_file(
         self, repo: Repository, path: str, ref: str, lineno: int

+ 12 - 4
src/sentry/integrations/gitlab/client.py

@@ -326,7 +326,7 @@ class GitLabProxyApiClient(IntegrationProxyClient):
                 raise
             return None
 
-    def get_file(self, repo: Repository, path: str, ref: str) -> str:
+    def get_file(self, repo: Repository, path: str, ref: str, codeowners: bool = False) -> str:
         """Get the contents of a file
 
         See https://docs.gitlab.com/ee/api/repository_files.html#get-file-from-repository
@@ -338,10 +338,18 @@ class GitLabProxyApiClient(IntegrationProxyClient):
         project_id = repo.config["project_id"]
         encoded_path = quote(path, safe="")
         request_path = GitLabApiClientPath.file.format(project=project_id, path=encoded_path)
-        contents = self.get(request_path, params={"ref": ref})
+        headers = (
+            {
+                "Accept": "application/vnd.github.raw",
+                "Content-Type": "application/raw; charset=utf-8",
+            }
+            if codeowners
+            else {}
+        )
+        contents = self.get(request_path, params={"ref": ref}, raw_response=True, headers=headers)
 
-        encoded_content = contents["content"]
-        return b64decode(encoded_content).decode("utf-8")
+        result = contents.content if codeowners else b64decode(contents["content"]).decode("utf-8")
+        return result
 
     def get_blame_for_file(
         self, repo: Repository, path: str, ref: str, lineno: int

+ 1 - 1
src/sentry/integrations/mixins/repositories.py

@@ -155,7 +155,7 @@ class RepositoryMixin:
             html_url = self.check_file(repo, filepath, ref)
             if html_url:
                 try:
-                    contents = self.get_client().get_file(repo, filepath, ref)
+                    contents = self.get_client().get_file(repo, filepath, ref, codeowners=True)
                 except ApiError:
                     continue
                 return {"filepath": filepath, "html_url": html_url, "raw": contents}

+ 6 - 4
tests/sentry/integrations/github/test_client.py

@@ -1,4 +1,3 @@
-import base64
 import re
 from dataclasses import asdict
 from datetime import datetime, timedelta, timezone
@@ -33,7 +32,7 @@ from tests.sentry.integrations.test_helpers import add_control_silo_proxy_respon
 GITHUB_CODEOWNERS = {
     "filepath": "CODEOWNERS",
     "html_url": "https://github.com/org/reponame/CODEOWNERS",
-    "raw": "docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
+    "raw": b"docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
 }
 
 
@@ -218,12 +217,15 @@ class GitHubAppsClientTest(TestCase):
         responses.add(
             method=responses.GET,
             url=f"https://api.github.com/repos/{self.repo.name}/contents/CODEOWNERS?ref=master",
-            json={"content": base64.b64encode(GITHUB_CODEOWNERS["raw"].encode()).decode("ascii")},
+            body=b"docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
         )
         result = self.install.get_codeowner_file(
             self.config.repository, ref=self.config.default_branch
         )
-
+        assert (
+            responses.calls[1].request.headers["Content-Type"] == "application/raw; charset=utf-8"
+        )
+        assert responses.calls[1].request.headers["Accept"] == "application/vnd.github.raw"
         assert result == GITHUB_CODEOWNERS
 
     @mock.patch("sentry.integrations.github.client.get_jwt", return_value=b"jwt_token_1")

+ 6 - 3
tests/sentry/integrations/github_enterprise/test_client.py

@@ -1,4 +1,3 @@
-import base64
 from unittest import mock
 
 import pytest
@@ -12,7 +11,7 @@ from sentry.testutils.cases import TestCase
 GITHUB_CODEOWNERS = {
     "filepath": "CODEOWNERS",
     "html_url": "https://github.example.org/Test-Organization/foo/blob/master/CODEOWNERS",
-    "raw": "docs/*    @jianyuan   @getsentry/ecosystem\n* @jianyuan\n",
+    "raw": b"docs/*    @jianyuan   @getsentry/ecosystem\n* @jianyuan\n",
 }
 
 
@@ -143,10 +142,14 @@ class GitHubAppsClientTest(TestCase):
         responses.add(
             method=responses.GET,
             url=url,
-            json={"content": base64.b64encode(GITHUB_CODEOWNERS["raw"].encode()).decode("ascii")},
+            body=b"docs/*    @jianyuan   @getsentry/ecosystem\n* @jianyuan\n",
         )
         result = self.install.get_codeowner_file(
             self.config.repository, ref=self.config.default_branch
         )
 
+        assert (
+            responses.calls[3].request.headers["Content-Type"] == "application/raw; charset=utf-8"
+        )
+        assert responses.calls[3].request.headers["Accept"] == "application/vnd.github.raw"
         assert result == GITHUB_CODEOWNERS

+ 6 - 3
tests/sentry/integrations/gitlab/test_client.py

@@ -1,6 +1,5 @@
 from __future__ import annotations
 
-import base64
 from dataclasses import asdict
 from datetime import datetime, timezone
 from unittest import mock
@@ -23,7 +22,7 @@ from sentry.utils.cache import cache
 GITLAB_CODEOWNERS = {
     "filepath": "CODEOWNERS",
     "html_url": "https://gitlab.com/org/reponame/CODEOWNERS",
-    "raw": "docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
+    "raw": b"docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
 }
 
 
@@ -207,12 +206,16 @@ class GitlabRefreshAuthTest(GitLabClientTest):
         responses.add(
             method=responses.GET,
             url=f"https://example.gitlab.com/api/v4/projects/{self.gitlab_id}/repository/files/CODEOWNERS?ref=master",
-            json={"content": base64.b64encode(GITLAB_CODEOWNERS["raw"].encode()).decode("ascii")},
+            body=b"docs/*    @NisanthanNanthakumar   @getsentry/ecosystem\n* @NisanthanNanthakumar\n",
         )
         result = self.installation.get_codeowner_file(
             self.config.repository, ref=self.config.default_branch
         )
 
+        assert (
+            responses.calls[0].request.headers["Content-Type"] == "application/raw; charset=utf-8"
+        )
+        assert responses.calls[0].request.headers["Accept"] == "application/vnd.github.raw"
         assert result == GITLAB_CODEOWNERS
 
     @responses.activate