mirror of
https://github.com/saymrwulf/pytorch.git
synced 2026-05-14 20:57:59 +00:00
For https://github.com/pytorch/pytorch/issues/82033 Only update the pinned hash if the new hash is strictly newer than the old hash. This should allow us to use commits on PRs as the pinned hash, which helps with fixes in XLA. General hash update behavior (looking at hash on branch, trying to update + pushing, creating pr) should be unchanged. If the currently pinned hash is newer than the hash we are trying to update to, the existing pr will be closed if it exists. Also changes the hash update time to 12:37am PST (7:37am UTC). Pull Request resolved: https://github.com/pytorch/pytorch/pull/82173 Approved by: https://github.com/ZainRizvi, https://github.com/huydhn
168 lines
5.2 KiB
Python
168 lines
5.2 KiB
Python
import json
|
|
import os
|
|
import subprocess
|
|
import requests
|
|
from typing import Any, Dict
|
|
from argparse import ArgumentParser
|
|
|
|
MERGEBOT_TOKEN = os.environ["MERGEBOT_TOKEN"]
|
|
PYTORCHBOT_TOKEN = os.environ["PYTORCHBOT_TOKEN"]
|
|
OWNER, REPO = "pytorch", "pytorch"
|
|
|
|
|
|
def git_api(
|
|
url: str, params: Dict[str, str], type: str = "get", token: str = MERGEBOT_TOKEN
|
|
) -> Any:
|
|
headers = {
|
|
"Accept": "application/vnd.github.v3+json",
|
|
"Authorization": f"token {token}",
|
|
}
|
|
if type == "post":
|
|
return requests.post(
|
|
f"https://api.github.com{url}",
|
|
data=json.dumps(params),
|
|
headers=headers,
|
|
).json()
|
|
elif type == "patch":
|
|
return requests.patch(
|
|
f"https://api.github.com{url}",
|
|
data=json.dumps(params),
|
|
headers=headers,
|
|
).json()
|
|
else:
|
|
return requests.get(
|
|
f"https://api.github.com{url}",
|
|
params=params,
|
|
headers=headers,
|
|
).json()
|
|
|
|
|
|
def parse_args() -> Any:
|
|
parser = ArgumentParser("Rebase PR into branch")
|
|
parser.add_argument("--repo-name", type=str)
|
|
parser.add_argument("--branch", type=str)
|
|
return parser.parse_args()
|
|
|
|
|
|
def make_pr(repo_name: str, branch_name: str) -> Any:
|
|
params = {
|
|
"title": f"[{repo_name} hash update] update the pinned {repo_name} hash",
|
|
"head": branch_name,
|
|
"base": "master",
|
|
"body": "This PR is auto-generated nightly by [this action](https://github.com/pytorch/pytorch/blob/master/"
|
|
+ f".github/workflows/_update-commit-hash.yml).\nUpdate the pinned {repo_name} hash.",
|
|
}
|
|
response = git_api(f"/repos/{OWNER}/{REPO}/pulls", params, type="post")
|
|
print(f"made pr {response['html_url']}")
|
|
return response["number"]
|
|
|
|
|
|
def approve_pr(pr_number: str) -> None:
|
|
params = {"event": "APPROVE"}
|
|
# use pytorchbot to approve the pr
|
|
git_api(
|
|
f"/repos/{OWNER}/{REPO}/pulls/{pr_number}/reviews",
|
|
params,
|
|
type="post",
|
|
token=PYTORCHBOT_TOKEN,
|
|
)
|
|
|
|
|
|
def make_comment(pr_number: str, msg: str) -> None:
|
|
params = {"body": msg}
|
|
# comment with pytorchbot because pytorchmergebot gets ignored
|
|
git_api(
|
|
f"/repos/{OWNER}/{REPO}/issues/{pr_number}/comments",
|
|
params,
|
|
type="post",
|
|
token=PYTORCHBOT_TOKEN,
|
|
)
|
|
|
|
|
|
def close_pr(pr_number: str) -> None:
|
|
params = {"state": "closed"}
|
|
git_api(
|
|
f"/repos/{OWNER}/{REPO}/pulls/{pr_number}",
|
|
params,
|
|
type="patch",
|
|
)
|
|
|
|
|
|
def is_newer_hash(new_hash: str, old_hash: str, repo_name: str) -> bool:
|
|
def _get_date(hash: str) -> int:
|
|
# this git command prints the unix timestamp of the hash
|
|
return int(
|
|
subprocess.run(
|
|
f"git show --no-patch --no-notes --pretty=%ct {hash}".split(),
|
|
capture_output=True,
|
|
cwd=f"{repo_name}",
|
|
)
|
|
.stdout.decode("utf-8")
|
|
.strip()
|
|
)
|
|
|
|
return _get_date(new_hash) > _get_date(old_hash)
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
|
|
branch_name = os.environ["NEW_BRANCH_NAME"]
|
|
pr_num = None
|
|
|
|
# query to see if a pr already exists
|
|
params = {
|
|
"q": f"is:pr is:open in:title author:pytorchmergebot repo:{OWNER}/{REPO} {args.repo_name} hash update"
|
|
}
|
|
response = git_api("/search/issues", params)
|
|
if response["total_count"] != 0:
|
|
# pr does exist
|
|
pr_num = response["items"][0]["number"]
|
|
link = response["items"][0]["html_url"]
|
|
response = git_api(f"/repos/{OWNER}/{REPO}/pulls/{pr_num}", {})
|
|
branch_name = response["head"]["ref"]
|
|
print(
|
|
f"pr does exist, number is {pr_num}, branch name is {branch_name}, link is {link}"
|
|
)
|
|
|
|
hash = (
|
|
subprocess.run(
|
|
f"git rev-parse {args.branch}".split(),
|
|
capture_output=True,
|
|
cwd=f"{args.repo_name}",
|
|
)
|
|
.stdout.decode("utf-8")
|
|
.strip()
|
|
)
|
|
with open(f".github/ci_commit_pins/{args.repo_name}.txt", "r+") as f:
|
|
old_hash = f.read().strip()
|
|
f.seek(0)
|
|
f.truncate()
|
|
f.write(f"{hash}\n")
|
|
if is_newer_hash(hash, old_hash, args.repo_name):
|
|
# if there was an update, push to branch
|
|
subprocess.run(f"git checkout -b {branch_name}".split())
|
|
subprocess.run(f"git add .github/ci_commit_pins/{args.repo_name}.txt".split())
|
|
subprocess.run(
|
|
"git commit -m".split() + [f"update {args.repo_name} commit hash"]
|
|
)
|
|
subprocess.run(f"git push --set-upstream origin {branch_name} -f".split())
|
|
print(f"changes pushed to branch {branch_name}")
|
|
if pr_num is None:
|
|
# no existing pr, so make a new one and approve it
|
|
pr_num = make_pr(args.repo_name, branch_name)
|
|
approve_pr(pr_num)
|
|
# comment to merge if all checks are green
|
|
make_comment(pr_num, "@pytorchbot merge -g")
|
|
else:
|
|
print(
|
|
f"tried to update from old hash: {old_hash} to new hash: {hash} but the old hash seems to be newer, not creating pr"
|
|
)
|
|
if pr_num is not None:
|
|
make_comment(pr_num, "closing pr as the current hash seems up to date")
|
|
close_pr(pr_num)
|
|
print(f"closing PR {pr_num}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|