From 1ff0afabaedca81eede69ebb60b00c168eb4b7d1 Mon Sep 17 00:00:00 2001 From: Ori Kotek Date: Thu, 7 Mar 2024 00:48:33 +0200 Subject: [PATCH] Refactor update changelog --- pr_agent/git_providers/bitbucket_provider.py | 35 ++++++++++++ pr_agent/git_providers/github_provider.py | 27 +++++++++- pr_agent/git_providers/gitlab_provider.py | 8 ++- pr_agent/tools/pr_update_changelog.py | 57 ++++++++++---------- 4 files changed, 93 insertions(+), 34 deletions(-) diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index 103ea5cd..c4873f88 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -342,6 +342,41 @@ class BitbucketProvider(GitProvider): def _get_pr(self): return self._get_repo().pullrequests.get(self.pr_num) + def get_pr_file_content(self, file_path: str, branch: str) -> str: + try: + if branch == self.pr.source_branch: + branch = self.pr.data["source"]["commit"]["hash"] + elif branch == self.pr.destination_branch: + branch = self.pr.data["destination"]["commit"]["hash"] + url = (f"https://api.bitbucket.org/2.0/repositories/{self.workspace_slug}/{self.repo_slug}/src/" + f"{branch}/{file_path}") + response = requests.request("GET", url, headers=self.headers) + if response.status_code == 404: # not found + return "" + contents = response.text + return contents + except Exception: + return "" + + + def create_or_update_pr_file(self, file_path: str, branch: str, contents="", message="") -> None: + url = (f"https://api.bitbucket.org/2.0/repositories/{self.workspace_slug}/{self.repo_slug}/src/") + if not message: + if contents: + message = f"Update {file_path}" + else: + message = f"Create {file_path}" + files={file_path: contents} + data={ + "message": message, + "branch": branch + } + headers = {'Authorization':self.headers['Authorization']} if 'Authorization' in self.headers else {} + try: + requests.request("POST", url, headers=headers, data=data, files=files) + except Exception: + get_logger().exception(f"Failed to create empty file {file_path} in branch {branch}") + def _get_pr_file_content(self, remote_link: str): return "" diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 22117af6..fab4fd5b 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -603,13 +603,36 @@ class GithubProvider(GitProvider): def _get_pr(self): return self._get_repo().get_pull(self.pr_num) - def _get_pr_file_content(self, file: FilePatchInfo, sha: str) -> str: + def get_pr_file_content(self, file_path: str, branch: str) -> str: try: - file_content_str = str(self._get_repo().get_contents(file.filename, ref=sha).decoded_content.decode()) + file_content_str = str( + self._get_repo() + .get_contents(file_path, ref=branch) + .decoded_content.decode() + ) except Exception: file_content_str = "" return file_content_str + def create_or_update_pr_file( + self, file_path: str, branch: str, contents="", message="" + ) -> None: + try: + file_obj = self._get_repo().get_contents(file_path, ref=branch) + sha1=file_obj.sha + except Exception: + sha1="" + self.repo_obj.update_file( + path=file_path, + message=message, + content=contents, + sha=sha1, + branch=branch, + ) + + def _get_pr_file_content(self, file: FilePatchInfo, sha: str) -> str: + return self.get_pr_file_content(file.filename, sha) + def publish_labels(self, pr_types): try: label_color_map = {"Bug fix": "1d76db", "Tests": "e99695", "Bug fix with tests": "c5def5", diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index 8d2e97c8..5021896d 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -63,7 +63,7 @@ class GitLabProvider(GitProvider): raise DiffNotFoundError(f"Could not get diff for merge request {self.id_mr}") from e - def _get_pr_file_content(self, file_path: str, branch: str) -> str: + def get_pr_file_content(self, file_path: str, branch: str) -> str: try: return self.gl.projects.get(self.id_project).files.get(file_path, branch).decode() except GitlabGetError: @@ -88,10 +88,8 @@ class GitLabProvider(GitProvider): diff_files = [] for diff in diffs: if is_valid_file(diff['new_path']): - # original_file_content_str = self._get_pr_file_content(diff['old_path'], self.mr.target_branch) - # new_file_content_str = self._get_pr_file_content(diff['new_path'], self.mr.source_branch) - original_file_content_str = self._get_pr_file_content(diff['old_path'], self.mr.diff_refs['base_sha']) - new_file_content_str = self._get_pr_file_content(diff['new_path'], self.mr.diff_refs['head_sha']) + original_file_content_str = self.get_pr_file_content(diff['old_path'], self.mr.diff_refs['base_sha']) + new_file_content_str = self.get_pr_file_content(diff['new_path'], self.mr.diff_refs['head_sha']) try: if isinstance(original_file_content_str, bytes): diff --git a/pr_agent/tools/pr_update_changelog.py b/pr_agent/tools/pr_update_changelog.py index 102d8a69..4e168d5d 100644 --- a/pr_agent/tools/pr_update_changelog.py +++ b/pr_agent/tools/pr_update_changelog.py @@ -53,11 +53,16 @@ class PRUpdateChangelog: get_logger().debug("Relevant configs", artifacts=relevant_configs) # currently only GitHub is supported for pushing changelog changes - if get_settings().pr_update_changelog.push_changelog_changes and type(self.git_provider) != GithubProvider: - get_logger().error("Pushing changelog changes is not currently supported for this code platform") + if get_settings().pr_update_changelog.push_changelog_changes and not hasattr( + self.git_provider, "create_or_update_pr_file" + ): + get_logger().error( + "Pushing changelog changes is not currently supported for this code platform" + ) if get_settings().config.publish_output: self.git_provider.publish_comment( - "Pushing changelog changes is not currently supported for this code platform") + "Pushing changelog changes is not currently supported for this code platform" + ) return if get_settings().config.publish_output: @@ -98,11 +103,11 @@ class PRUpdateChangelog: def _prepare_changelog_update(self) -> Tuple[str, str]: answer = self.prediction.strip().strip("```").strip() # noqa B005 if hasattr(self, "changelog_file"): - existing_content = self.changelog_file.decoded_content.decode() + existing_content = self.changelog_file else: existing_content = "" if existing_content: - new_file_content = answer + "\n\n" + self.changelog_file.decoded_content.decode() + new_file_content = answer + "\n\n" + self.changelog_file else: new_file_content = answer @@ -113,25 +118,28 @@ class PRUpdateChangelog: return new_file_content, answer def _push_changelog_update(self, new_file_content, answer): - self.git_provider.repo_obj.update_file(path=self.changelog_file.path, - message="Update CHANGELOG.md", - content=new_file_content, - sha=self.changelog_file.sha, - branch=self.git_provider.get_pr_branch()) - d = dict(body="CHANGELOG.md update", - path=self.changelog_file.path, - line=max(2, len(answer.splitlines())), - start_line=1) + self.git_provider.create_or_update_pr_file( + file_path="CHANGELOG.md", + branch=self.git_provider.get_pr_branch(), + contents=new_file_content, + message="Update CHANGELOG.md", + ) sleep(5) # wait for the file to be updated - last_commit_id = list(self.git_provider.pr.get_commits())[-1] try: - self.git_provider.pr.create_review(commit=last_commit_id, comments=[d]) + if get_settings().config.git_provider == "github": + last_commit_id = list(self.git_provider.pr.get_commits())[-1] + d = dict( + body="CHANGELOG.md update", + path="CHANGELOG.md", + line=max(2, len(answer.splitlines())), + start_line=1, + ) + self.git_provider.pr.create_review(commit=last_commit_id, comments=[d]) except Exception: # we can't create a review for some reason, let's just publish a comment self.git_provider.publish_comment(f"**Changelog updates:**\n\n{answer}") - def _get_default_changelog(self): example_changelog = \ """ @@ -149,20 +157,15 @@ Example: def _get_changlog_file(self): try: - self.changelog_file = self.git_provider.repo_obj.get_contents("CHANGELOG.md", - ref=self.git_provider.get_pr_branch()) - changelog_file_lines = self.changelog_file.decoded_content.decode().splitlines() + self.changelog_file = self.git_provider.get_pr_file_content( + "CHANGELOG.md", self.git_provider.get_pr_branch() + ) + changelog_file_lines = self.changelog_file.splitlines() changelog_file_lines = changelog_file_lines[:CHANGELOG_LINES] self.changelog_file_str = "\n".join(changelog_file_lines) except Exception: self.changelog_file_str = "" - if self.commit_changelog: - get_logger().info("No CHANGELOG.md file found in the repository. Creating one...") - changelog_file = self.git_provider.repo_obj.create_file(path="CHANGELOG.md", - message='add CHANGELOG.md', - content="", - branch=self.git_provider.get_pr_branch()) - self.changelog_file = changelog_file['content'] + self.changelog_file = "" if not self.changelog_file_str: self.changelog_file_str = self._get_default_changelog()