|
| 1 | +from __future__ import annotations |
| 2 | +import os |
| 3 | +import sys |
| 4 | +import datetime |
| 5 | +import subprocess |
| 6 | +from pathlib import Path |
| 7 | +from typing import TYPE_CHECKING |
| 8 | + |
| 9 | +from github import Github |
| 10 | +from github import Auth |
| 11 | + |
| 12 | +if TYPE_CHECKING: |
| 13 | + from github.PullRequest import PullRequest |
| 14 | + |
| 15 | + |
| 16 | +def ident() -> None: |
| 17 | + subprocess.run(["/usr/bin/git", "config", "--global", "user.name", "github-actions[bot]"], check=True) |
| 18 | + subprocess.run( |
| 19 | + ["/usr/bin/git", "config", "--global", "user.email", "github-actions[bot]@users.noreply.github.com"], check=True |
| 20 | + ) |
| 21 | + |
| 22 | + |
| 23 | +def create_update_pr(commit_message: str, branch_prefix: str, title: str, body: str, path: str | Path) -> None: |
| 24 | + """ |
| 25 | + Creates or updates a pull request with the given title and body. |
| 26 | +
|
| 27 | + Parameters |
| 28 | + ---------- |
| 29 | + commit_message (str): The commit message to use. |
| 30 | + branch_prefix (str): The prefix for the branch name. |
| 31 | + title (str): The title of the pull request. |
| 32 | + body (str): The body of the pull request. |
| 33 | + path (str | Path): The path or glob to the file to commit. |
| 34 | + """ |
| 35 | + github = Github(os.environ["GITHUB_TOKEN"]) |
| 36 | + repo = github.get_repo(os.environ["GITHUB_REPOSITORY"]) |
| 37 | + base_branch = subprocess.run( |
| 38 | + ["/usr/bin/git", "rev-parse", "--abbrev-ref", "HEAD"], |
| 39 | + check=True, |
| 40 | + capture_output=True, |
| 41 | + text=True, |
| 42 | + ).stdout.strip() |
| 43 | + ident() |
| 44 | + print(f"Creating/updating PR in {repo.full_name} on branch {base_branch} with prefix {branch_prefix}") |
| 45 | + |
| 46 | + prs = repo.get_pulls(state="open", sort="created", base=base_branch) |
| 47 | + pull_request: None | PullRequest = None |
| 48 | + for pr in prs: |
| 49 | + if pr.head.ref.startswith(branch_prefix): |
| 50 | + branch_name: str = pr.head.ref |
| 51 | + subprocess.run( |
| 52 | + ["/usr/bin/git", "fetch", "origin", branch_name], |
| 53 | + check=False, |
| 54 | + ) |
| 55 | + subprocess.run( |
| 56 | + ["/usr/bin/git", "checkout", branch_name], |
| 57 | + check=False, |
| 58 | + ) |
| 59 | + pull_request = pr |
| 60 | + break |
| 61 | + else: |
| 62 | + branch_name = f"{branch_prefix}-{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}" |
| 63 | + subprocess.run( |
| 64 | + ["/usr/bin/git", "checkout", "-b", branch_name], |
| 65 | + check=False, |
| 66 | + ) |
| 67 | + |
| 68 | + if not subprocess.run(["/usr/bin/git", "status", "--porcelain"], check=False, capture_output=True).stdout: |
| 69 | + print("No changes to commit.") |
| 70 | + return |
| 71 | + |
| 72 | + subprocess.run( |
| 73 | + ["/usr/bin/git", "add", str(path)], |
| 74 | + check=False, |
| 75 | + ) |
| 76 | + subprocess.run( |
| 77 | + ["/usr/bin/git", "commit", "-m", title], |
| 78 | + check=False, |
| 79 | + ) |
| 80 | + subprocess.run( |
| 81 | + ["/usr/bin/git", "push", "-u", "origin", branch_name], |
| 82 | + check=False, |
| 83 | + ) |
| 84 | + |
| 85 | + if not pull_request: |
| 86 | + pull_request = repo.create_pull( |
| 87 | + title=title, |
| 88 | + body=body, |
| 89 | + head=branch_name, |
| 90 | + base=base_branch, |
| 91 | + ) |
| 92 | + print(f"Created new PR #{pull_request.number}: {pull_request.title}") |
| 93 | + |
| 94 | + |
| 95 | +__all__ = ("create_update_pr",) |
0 commit comments