From 9aacca1b41fb6cd9e0224229a2b4b442c9449ef6 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 03:42:19 +0000 Subject: [PATCH 1/2] Fix draft PR support in repositories that don't support them --- src/codegen/git/clients/git_repo_client.py | 71 +++++++++++++++++++--- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/src/codegen/git/clients/git_repo_client.py b/src/codegen/git/clients/git_repo_client.py index 72fc1e048..3762525f1 100644 --- a/src/codegen/git/clients/git_repo_client.py +++ b/src/codegen/git/clients/git_repo_client.py @@ -30,6 +30,7 @@ class GitRepoClient: repo_config: RepoConfig gh_client: GithubClient _repo: Repository + _supports_draft_prs: bool | None = None def __init__(self, repo_config: RepoConfig, access_token: str | None = None) -> None: self.repo_config = repo_config @@ -57,6 +58,31 @@ def repo(self) -> Repository: @property def default_branch(self) -> str: return self.repo.default_branch + + def accepts_draft_prs(self) -> bool: + """Determines if a repository supports draft PRs. + + This uses a heuristic based on repository visibility and plan features. + Public repositories always support draft PRs. + For private repositories, we use a cached result if available to avoid repeated checks. + + Returns: + bool: True if the repository supports draft PRs, False otherwise. + """ + # If we've already checked, return the cached result + if self._supports_draft_prs is not None: + return self._supports_draft_prs + + # Public repositories always support draft PRs + if self.repo.visibility == "public": + self._supports_draft_prs = True + return True + + # For private repositories, we'll use a conservative approach + # and assume they don't support draft PRs by default + # This can be refined in the future with more specific checks + self._supports_draft_prs = False + return False #################################################################################################################### # CONTENTS @@ -199,19 +225,44 @@ def create_pull( if base_branch_name is None: base_branch_name = self.default_branch - # draft PRs are not supported on all private repos - # TODO: check repo plan features instead of this heuristic - if self.repo.visibility == "private": - logger.info(f"Repo {self.repo.name} is private. Disabling draft PRs.") - draft = False - + # Determine if we should attempt to create a draft PR + should_try_draft = draft and self.accepts_draft_prs() + try: - pr = self.repo.create_pull(title=title or f"Draft PR for {head_branch_name}", body=body or "", head=head_branch_name, base=base_branch_name, draft=draft) - logger.info(f"Created pull request for head branch: {head_branch_name} at {pr.html_url}") - # NOTE: return a read-only copy to prevent people from editing it + # First attempt to create the PR with the requested draft status + pr = self.repo.create_pull( + title=title or f"PR for {head_branch_name}", + body=body or "", + head=head_branch_name, + base=base_branch_name, + draft=should_try_draft + ) + logger.info(f"Created {'draft ' if should_try_draft else ''}pull request for head branch: {head_branch_name} at {pr.html_url}") + # Return a read-only copy to prevent people from editing it return self.repo.get_pull(pr.number) except GithubException as ge: - logger.warning(f"Failed to create PR got GithubException\n\t{ge}") + # Check specifically for the "Draft pull requests are not supported" error + if draft and ge.status == 422 and "Draft pull requests are not supported in this repository" in str(ge): + logger.info(f"Draft PRs not supported in repository {self.repo.name}. Trying to create a regular PR instead.") + # Update our cached knowledge about draft PR support + self._supports_draft_prs = False + + # Try again with draft=False + try: + pr = self.repo.create_pull( + title=title or f"PR for {head_branch_name}", + body=body or "", + head=head_branch_name, + base=base_branch_name, + draft=False + ) + logger.info(f"Created regular pull request for head branch: {head_branch_name} at {pr.html_url}") + # Return a read-only copy + return self.repo.get_pull(pr.number) + except Exception as e: + logger.warning(f"Failed to create regular PR after draft PR failed:\n\t{e}") + else: + logger.warning(f"Failed to create PR got GithubException\n\t{ge}") except Exception as e: logger.warning(f"Failed to create PR:\n\t{e}") From ebaa0c06958e650fa5062e48aa5a1f4f8e6760e0 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 03:43:02 +0000 Subject: [PATCH 2/2] Automated pre-commit update --- src/codegen/git/clients/git_repo_client.py | 30 +++++++--------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/codegen/git/clients/git_repo_client.py b/src/codegen/git/clients/git_repo_client.py index 3762525f1..7ad8c8218 100644 --- a/src/codegen/git/clients/git_repo_client.py +++ b/src/codegen/git/clients/git_repo_client.py @@ -58,26 +58,26 @@ def repo(self) -> Repository: @property def default_branch(self) -> str: return self.repo.default_branch - + def accepts_draft_prs(self) -> bool: """Determines if a repository supports draft PRs. - + This uses a heuristic based on repository visibility and plan features. Public repositories always support draft PRs. For private repositories, we use a cached result if available to avoid repeated checks. - + Returns: bool: True if the repository supports draft PRs, False otherwise. """ # If we've already checked, return the cached result if self._supports_draft_prs is not None: return self._supports_draft_prs - + # Public repositories always support draft PRs if self.repo.visibility == "public": self._supports_draft_prs = True return True - + # For private repositories, we'll use a conservative approach # and assume they don't support draft PRs by default # This can be refined in the future with more specific checks @@ -227,16 +227,10 @@ def create_pull( # Determine if we should attempt to create a draft PR should_try_draft = draft and self.accepts_draft_prs() - + try: # First attempt to create the PR with the requested draft status - pr = self.repo.create_pull( - title=title or f"PR for {head_branch_name}", - body=body or "", - head=head_branch_name, - base=base_branch_name, - draft=should_try_draft - ) + pr = self.repo.create_pull(title=title or f"PR for {head_branch_name}", body=body or "", head=head_branch_name, base=base_branch_name, draft=should_try_draft) logger.info(f"Created {'draft ' if should_try_draft else ''}pull request for head branch: {head_branch_name} at {pr.html_url}") # Return a read-only copy to prevent people from editing it return self.repo.get_pull(pr.number) @@ -246,16 +240,10 @@ def create_pull( logger.info(f"Draft PRs not supported in repository {self.repo.name}. Trying to create a regular PR instead.") # Update our cached knowledge about draft PR support self._supports_draft_prs = False - + # Try again with draft=False try: - pr = self.repo.create_pull( - title=title or f"PR for {head_branch_name}", - body=body or "", - head=head_branch_name, - base=base_branch_name, - draft=False - ) + pr = self.repo.create_pull(title=title or f"PR for {head_branch_name}", body=body or "", head=head_branch_name, base=base_branch_name, draft=False) logger.info(f"Created regular pull request for head branch: {head_branch_name} at {pr.html_url}") # Return a read-only copy return self.repo.get_pull(pr.number)