def open_pr(subject, body, branch): log.info("Opening pull request for branch %s", branch) github_token = os.environ['GITHUB_TOKEN'] g = Github(github_token) user = g.get_user() origin_url = subprocess.check_output(( "git", "remote", "get-url", "origin", )).decode("utf-8").strip() origin_repo = g.get_repo(parse_github_url(origin_url)) if origin_repo.permissions.push: log.debug("origin repo is writable") remote = "origin" repo = origin_repo fork = None else: log.debug("origin repo not writable; creating fork") fork = user.create_fork(origin_repo) remote = user.login repo = fork remote_url = f"https://{github_token}:[email protected]/{repo.full_name}" if fork: check_call(("git", "remote", "add", remote, remote_url)) else: check_call(("git", "remote", "set-url", remote, remote_url)) base = "master" head = "{}:{}".format(repo.owner.login, branch) pr_message = ((body or "") + "\n\n" + DISCLAIMER).strip() # Include closed PRs – if the maintainer has closed our last PR, we don't want to # open another one. for pr in origin_repo.get_pulls(state="all", base=base, head=head): log.info( "Found existing %s PR: %s", "merged" if pr.is_merged() else pr.state, pr.html_url, ) return check_call(("git", "push", "-u", remote, branch)) pr = origin_repo.create_pull( subject, pr_message, base, head, maintainer_can_modify=True, ) log.info("Opened pull request %s", pr.html_url)
def test_https(self): self.assertEqual( parse_github_url("https://github.com/flathub/com.dropbox.Client"), "flathub/com.dropbox.Client", )
def test_ssh(self): self.assertEqual( parse_github_url( "[email protected]:endlessm/flatpak-external-data-checker.git"), "endlessm/flatpak-external-data-checker", )
def test_https_with_auth(self): url = "https://*****:*****@github.com/endlessm/eos-google-chrome-app" self.assertEqual(parse_github_url(url), "endlessm/eos-google-chrome-app")
def test_ssh_no_dotgit(self): url = "[email protected]:flathub/flatpak-external-data-checker" self.assertEqual(parse_github_url(url), "flathub/flatpak-external-data-checker")
def open_pr(subject, body, branch, manifest_checker=None): try: github_token = os.environ["GITHUB_TOKEN"] except KeyError: log.error("GITHUB_TOKEN environment variable is not set") sys.exit(1) log.info("Opening pull request for branch %s", branch) g = Github(github_token) user = g.get_user() origin_url = (subprocess.check_output(( "git", "remote", "get-url", "origin", )).decode("utf-8").strip()) origin_repo = g.get_repo(parse_github_url(origin_url)) if origin_repo.permissions.push: log.debug("origin repo is writable") repo = origin_repo else: log.debug("origin repo not writable; creating fork") repo = user.create_fork(origin_repo) remote_url = f"https://{github_token}:[email protected]/{repo.full_name}" base = origin_repo.default_branch head = "{}:{}".format(repo.owner.login, branch) pr_message = ((body or "") + "\n\n" + DISCLAIMER).strip() try: with open("flathub.json") as f: repocfg = json.load(f) except FileNotFoundError: repocfg = {} automerge = repocfg.get("automerge-flathubbot-prs") # Enable automatic merge if external data is broken unless explicitly disabled if automerge is not False and manifest_checker: for data in manifest_checker.get_outdated_external_data(): if data.new_version and data.state == ExternalData.State.BROKEN: automerge = True break prs = origin_repo.get_pulls(state="all", base=base, head=head) # If the maintainer has closed our last PR or it was merged, # we don't want to open another one. closed_prs = [pr for pr in prs if pr.state == "closed"] for pr in closed_prs: log.info( "Found existing %s PR: %s", "merged" if pr.is_merged() else pr.state, pr.html_url, ) return open_prs = [pr for pr in prs if pr.state == "open"] for pr in open_prs: log.info("Found open PR: %s", pr.html_url) if origin_repo.permissions.push and automerge: pr_commit = pr.head.repo.get_commit(pr.head.sha) if pr_commit.get_combined_status( ).state == "success" and pr.mergeable: log.info("PR passed CI and is mergeable, merging", pr.html_url) pr.create_issue_comment(MERGE_COMMENT) pr.merge(merge_method="rebase") origin_repo.get_git_ref(f"heads/{pr.head.ref}").delete() return else: return check_call(("git", "push", "-u", remote_url, branch)) pr = origin_repo.create_pull( subject, pr_message, base, head, maintainer_can_modify=True, ) log.info("Opened pull request %s", pr.html_url)