Skip to content

Commit

Permalink
Merge pull request #7260 from freedomofpress/backport-many-but-not-al…
Browse files Browse the repository at this point in the history
…l-the-things

feat: make `backport.py` more flexible for complex pull requests
  • Loading branch information
legoktm authored Nov 21, 2024
2 parents f006815 + 0574c47 commit 6a875bc
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions utils/backport.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,36 @@
parser.add_argument("pr", type=int, help="the # of the PR to backport")
parser.add_argument("version", help="the release version to target with the backport")
parser.add_argument("remote", default="origin", help="the git remote to use (defaults to origin)")
parser.add_argument("--skip", default=[], action="append", help="don't cherry-pick these commits")
args = parser.parse_args()

title = json.loads(
subprocess.check_output(["gh", "pr", "view", str(args.pr), "--json", "title"], text=True)
)["title"]
commits = json.loads(
subprocess.check_output(
["gh", "api", f"repos/{{owner}}/{{repo}}/pulls/{args.pr}/commits"], text=True
["gh", "api", "--paginate", f"repos/{{owner}}/{{repo}}/pulls/{args.pr}/commits"], text=True
)
)
print(f'Backporting {len(commits)} commits from "{title}"')

# NB. It's tempting to do something like `set(commit_hashes) -= set(args.skip)`
# here, but we must preserve the order of commits, and it's not worth pulling
# in an ordered-set implementation just for this.
commit_hashes = [commit["sha"] for commit in commits if commit["sha"] not in args.skip]

print(f'Backporting {len(commit_hashes)}/{len(commits)} commits from "{title}"')
branch = f"backport-{args.pr}"
base = f"release/{args.version}"
remote = args.remote
subprocess.check_call(["git", "fetch", remote])
subprocess.check_call(["git", "checkout", "-b", branch, f"{remote}/{base}"])
subprocess.check_call(["git", "cherry-pick", "-x"] + [commit["sha"] for commit in commits])
subprocess.check_call(["git", "cherry-pick", "-x"] + commit_hashes)
if input("OK to push and create PR? [y/N]").lower() != "y":
sys.exit()
subprocess.check_call(["git", "push", "-u", remote, branch])

skip_list = ", ".join(args.skip)
skip_message = f", excluding {skip_list}" if len(args.skip) > 0 else ""
body = f"""\
## Status
Expand All @@ -49,7 +59,7 @@
* [ ] CI is passing
* [ ] base is `{base}`
* [ ] Only contains changes from #{args.pr}.
* [ ] Only contains changes from #{args.pr} #{skip_message}
"""
print(body)

Expand Down

0 comments on commit 6a875bc

Please sign in to comment.