Example #1
0
def rebase_onto(pr: GitHubPR,
                repo: GitRepo,
                onto_branch: str,
                dry_run: bool = False) -> None:
    branch = f"pull/{pr.pr_num}/head"
    onto_branch = f"refs/remotes/origin/{onto_branch}"
    remote_url = f"https://github.com/{pr.info['headRepository']['nameWithOwner']}.git"
    refspec = f"{branch}:{pr.head_ref()}"

    repo.fetch(branch, branch)
    repo._run_git("rebase", onto_branch, branch)
    if dry_run:
        push_result = repo._run_git("push", "--dry-run", "-f", remote_url,
                                    refspec)
    else:
        push_result = repo._run_git("push", "-f", remote_url, refspec)
    if "Everything up-to-date" in push_result:
        gh_post_comment(
            pr.org,
            pr.project,
            pr.pr_num,
            f"Tried to rebase and push PR #{pr.pr_num}, but it was already up to date",
            dry_run=dry_run)
    else:
        gh_post_comment(
            pr.org,
            pr.project,
            pr.pr_num,
            f"Successfully rebased `{pr.head_ref()}` onto `{onto_branch}`, please pull locally "
            +
            f"before adding more changes (for example, via `git checkout {pr.head_ref()} && "
            + "git pull --rebase`)",
            dry_run=dry_run)
Example #2
0
    def merge_into(self,
                   repo: GitRepo,
                   *,
                   force: bool = False,
                   dry_run: bool = False,
                   comment_id: Optional[int] = None) -> None:
        # Raises exception if matching rule is not found
        find_matching_merge_rule(self,
                                 repo,
                                 force=force,
                                 skip_internal_checks=can_skip_internal_checks(
                                     self, comment_id))
        if repo.current_branch() != self.default_branch():
            repo.checkout(self.default_branch())
        if not self.is_ghstack_pr():
            # Adding the url here makes it clickable within the Github UI
            approved_by_urls = ', '.join(
                prefix_with_github_url(login)
                for login in self.get_approved_by())
            msg = self.get_title() + f" (#{self.pr_num})\n\n" + self.get_body()
            msg += f"\nPull Request resolved: {self.get_pr_url()}\n"
            msg += f"Approved by: {approved_by_urls}\n"
            pr_branch_name = f"__pull-request-{self.pr_num}__init__"
            repo.fetch(f"pull/{self.pr_num}/head", pr_branch_name)
            repo._run_git("merge", "--squash", pr_branch_name)
            repo._run_git("commit", f"--author=\"{self.get_author()}\"", "-m",
                          msg)
        else:
            self.merge_ghstack_into(repo, force, comment_id=comment_id)

        repo.push(self.default_branch(), dry_run)
        if not dry_run:
            gh_add_labels(self.org, self.project, self.pr_num, ["merged"])
Example #3
0
 def merge_changes(self,
                   repo: GitRepo,
                   force: bool = False,
                   comment_id: Optional[int] = None,
                   branch: Optional[str] = None) -> None:
     branch_to_merge_into = self.default_branch() if branch is None else branch
     if repo.current_branch() != branch_to_merge_into:
         repo.checkout(branch_to_merge_into)
     if not self.is_ghstack_pr():
         msg = self.gen_commit_message()
         pr_branch_name = f"__pull-request-{self.pr_num}__init__"
         repo.fetch(f"pull/{self.pr_num}/head", pr_branch_name)
         repo._run_git("merge", "--squash", pr_branch_name)
         repo._run_git("commit", f"--author=\"{self.get_author()}\"", "-m", msg)
     else:
         self.merge_ghstack_into(repo, force, comment_id=comment_id)
Example #4
0
    def merge_into(self, repo: GitRepo, dry_run: bool = False) -> None:
        # Raises exception if matching rule is not found
        find_matching_merge_rule(self, repo)
        if repo.current_branch() != self.default_branch():
            repo.checkout(self.default_branch())
        if not self.is_ghstack_pr():
            msg = self.get_title() + "\n\n" + self.get_body()
            msg += f"\nPull Request resolved: {self.get_pr_url()}\n"
            pr_branch_name = f"__pull-request-{self.pr_num}__init__"
            repo.fetch(f"pull/{self.pr_num}/head", pr_branch_name)
            repo._run_git("merge", "--squash", pr_branch_name)
            repo._run_git("commit", f"--author=\"{self.get_author()}\"", "-m",
                          msg)
        else:
            self.merge_ghstack_into(repo)

        repo.push(self.default_branch(), dry_run)
Example #5
0
    def merge_into(self, repo: GitRepo, *, force: bool = False, dry_run: bool = False) -> None:
        # Raises exception if matching rule is not found
        find_matching_merge_rule(self, repo, force=force)
        if self.has_internal_changes():
            raise RuntimeError("This PR must be landed via phabricator")
        if repo.current_branch() != self.default_branch():
            repo.checkout(self.default_branch())
        if not self.is_ghstack_pr():
            # Adding the url here makes it clickable within the Github UI
            approved_by_urls = ', '.join(prefix_with_github_url(login) for login in self.get_approved_by())
            msg = self.get_title() + "\n\n" + self.get_body()
            msg += f"\nPull Request resolved: {self.get_pr_url()}\n"
            msg += f"Approved by: {approved_by_urls}\n"
            pr_branch_name = f"__pull-request-{self.pr_num}__init__"
            repo.fetch(f"pull/{self.pr_num}/head", pr_branch_name)
            repo._run_git("merge", "--squash", pr_branch_name)
            repo._run_git("commit", f"--author=\"{self.get_author()}\"", "-m", msg)
        else:
            self.merge_ghstack_into(repo, force)

        repo.push(self.default_branch(), dry_run)
Example #6
0
def rebase_ghstack_onto(pr: GitHubPR,
                        repo: GitRepo,
                        onto_branch: str,
                        dry_run: bool = False) -> None:
    if subprocess.run([sys.executable, "-m", "ghstack", "--help"],
                      capture_output=True).returncode != 0:
        subprocess.run([sys.executable, "-m", "pip", "install", "ghstack"])
    orig_ref = f"{re.sub(r'/head$', '/orig', pr.head_ref())}"
    onto_branch = f"refs/remotes/origin/{onto_branch}"

    repo.fetch(orig_ref, orig_ref)
    repo._run_git("rebase", onto_branch, orig_ref)

    # steal the identity of the committer of the commit on the orig branch
    email = repo._run_git("log", orig_ref, "--pretty=format:%ae", "-1")
    name = repo._run_git("log", orig_ref, "--pretty=format:%an", "-1")
    repo._run_git("config", "--global", "user.name", name)
    repo._run_git("config", "--global", "user.email", email)

    os.environ["OAUTH_TOKEN"] = os.environ["GITHUB_TOKEN"]
    with open('.ghstackrc', 'w+') as f:
        f.write('[ghstack]\n' + "github_url=github.com\n" +
                "github_username=pytorchmergebot\n" + "remote_name=origin")

    if dry_run:
        print("Don't know how to dry-run ghstack")
    else:
        ghstack_result = subprocess.run(["ghstack"], capture_output=True)
        push_result = ghstack_result.stdout.decode("utf-8")
        print(push_result)
        if ghstack_result.returncode != 0:
            raise Exception(f"\n```{push_result}```")
        # The contents of a successful push result should look like:
        # Summary of changes (ghstack 0.6.0)

        #  - Updated https://github.com/clee2000/random-testing/pull/2
        #  - Updated https://github.com/clee2000/random-testing/pull/1

        # Facebook employees can import your changes by running
        # (on a Facebook machine):

        #     ghimport -s https://github.com/clee2000/random-testing/pull/2

        # If you want to work on this diff stack on another machine:

        #     ghstack checkout https://github.com/clee2000/random-testing/pull/2
        org, project = repo.gh_owner_and_name()
        for line in push_result.splitlines():
            if "Updated" in line:
                pr_num = int(line.split("/")[-1])
                if pr_num != pr.pr_num:
                    gh_post_comment(
                        pr.org,
                        pr.project,
                        pr_num,
                        f"Rebased `{orig_ref}` onto `{onto_branch}` because #{pr.pr_num} was rebased, "
                        "please pull locally before adding more changes (for example, via `ghstack "
                        +
                        f"checkout https://github.com/{org}/{project}/pull/{pr_num}`)",
                        dry_run=dry_run)
                else:
                    gh_post_comment(
                        pr.org,
                        pr.project,
                        pr_num,
                        f"Successfully rebased `{orig_ref}` onto `{onto_branch}`, please pull locally "
                        +
                        "before adding more changes (for example, via `ghstack "
                        +
                        f"checkout https://github.com/{org}/{project}/pull/{pr.pr_num}`)",
                        dry_run=dry_run)

        if f"Skipped https://github.com/{org}/{project}/pull/{pr.pr_num}" in push_result:
            gh_post_comment(
                pr.org,
                pr.project,
                pr.pr_num,
                f"Tried to rebase and push PR #{pr.pr_num}, but it was already up to date",
                dry_run=dry_run)
Example #7
0
def rebase_ghstack_onto(pr: GitHubPR,
                        repo: GitRepo,
                        dry_run: bool = False,
                        stable: bool = False) -> None:
    if subprocess.run([sys.executable, "-m", "ghstack", "--help"],
                      capture_output=True).returncode != 0:
        subprocess.run([sys.executable, "-m", "pip", "install", "ghstack"])
    orig_ref = f"{re.sub(r'/head$', '/orig', pr.head_ref())}"
    onto_branch = "refs/remotes/origin/viable/strict" if stable else pr.default_branch(
    )

    repo.fetch(orig_ref, orig_ref)
    repo._run_git("rebase", onto_branch, orig_ref)
    if dry_run:
        print("Don't know how to dry-run ghstack")
    else:
        ghstack_result = subprocess.run(["ghstack"], capture_output=True)
        push_result = ghstack_result.stdout.decode("utf-8")
        print(push_result)
        if ghstack_result.returncode != 0:
            raise Exception(f"\n```{push_result}```")
        # The contents of a successful push result should look like:
        # Summary of changes (ghstack 0.6.0)

        #  - Updated https://github.com/clee2000/random-testing/pull/2
        #  - Updated https://github.com/clee2000/random-testing/pull/1

        # Facebook employees can import your changes by running
        # (on a Facebook machine):

        #     ghimport -s https://github.com/clee2000/random-testing/pull/2

        # If you want to work on this diff stack on another machine:

        #     ghstack checkout https://github.com/clee2000/random-testing/pull/2
        org, project = repo.gh_owner_and_name()
        for line in push_result.splitlines():
            if "Updated" in line:
                pr_num = int(line.split("/")[-1])
                if pr_num != pr.pr_num:
                    gh_post_comment(
                        pr.org,
                        pr.project,
                        pr_num,
                        f"Rebased `{orig_ref}` onto `{onto_branch}` because #{pr.pr_num} was rebased, "
                        "please pull locally before adding more changes (for example, via `git checkout "
                        f"{orig_ref} && git pull --rebase`)",
                        dry_run=dry_run)
                else:
                    gh_post_comment(
                        pr.org,
                        pr.project,
                        pr_num,
                        f"Successfully rebased `{orig_ref}` onto `{onto_branch}`, please pull locally "
                        +
                        f"before adding more changes (for example, via `git checkout {orig_ref} && "
                        + "git pull --rebase`)",
                        dry_run=dry_run)

        if f"Skipped https://github.com/{org}/{project}/pull/{pr.pr_num}" in push_result:
            gh_post_comment(
                pr.org,
                pr.project,
                pr.pr_num,
                f"Tried to rebase and push PR #{pr.pr_num}, but it was already up to date",
                dry_run=dry_run)