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",
     )
Ejemplo n.º 4
0
 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")
Ejemplo n.º 5
0
 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")
Ejemplo n.º 6
0
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)