Skip to content

Commit

Permalink
chore: amend track-pr for new backport label
Browse files Browse the repository at this point in the history
  • Loading branch information
carolinaecalderon committed Oct 31, 2024
1 parent 227eab8 commit 37b70a7
Showing 1 changed file with 21 additions and 88 deletions.
109 changes: 21 additions & 88 deletions tools/scripts/track-pr
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ ORG = "determined-ai"
CLONED_REMOTE = "origin"
ISSUES_REPO = "release-party-issues-test" if TEST else "release-party-issues"

CHERRY_PICK_LABEL = "to-cherry-pick"

NEEDS_TESTING_STATUS = "Needs testing"
FIX_OPEN_STATUS = "Fix (open)"
FIX_CONFLICT_STATUS = "Fix (conflict)"
Expand Down Expand Up @@ -118,6 +116,14 @@ def add_tracking_issue_to_project(project_id: str, pr_id: str, status: str) -> N
add_item_to_project(project_id, issue_id, status)


def parse_release_string(release_string):
match = re.search(r"\((\d+\.\d+\.\d+)\)", release_string)
if match:
version = match.group(1)
return f"release-{version}"
return None


def find_project(owner: str, query: str, filt: Callable[[dict], bool]) -> dict:
all_projects = gql.search_projects(owner=owner, q=query)["organization"]["projectsV2"]["nodes"]
return next(p for p in all_projects if filt(p))
Expand All @@ -139,6 +145,15 @@ def current_project_id() -> str:
)["id"]


def current_backport_label() -> str:
res = find_project(
ORG,
"Current release",
lambda p: p["title"].startswith("TEST Current release" if TEST else "Current release"),
)
return "backport " + parse_release_string(res["name"])


def project_item_id_for_pr(project_id: str, pr_id: str):
after_cursor = None
while True:
Expand All @@ -152,111 +167,35 @@ def project_item_id_for_pr(project_id: str, pr_id: str):
return None


def cherry_pick_skipping_empty(commit):
out = run_capture("git", "cherry-pick", "-x", commit, check=False)
try:
out.check_returncode()
except subprocess.CalledProcessError:
if "The previous cherry-pick is now empty" in out.stderr:
run("git", "cherry-pick", "--skip")
else:
print(out.stdout)
print(out.stderr)
raise


def cherry_pick_pr(pr_id: str) -> None:
pr = gql.get_pr_merge_commit_and_url(id=pr_id)["node"]
pr_commit = pr["mergeCommit"]["oid"]
print(f"Cherry-picking {pr_commit}")

try:
# Find and fetch the PR commit and both release branches.
branch_pat = re.compile(r"/release-(\d+)\.(\d+)\.(\d+)$")
release_branch = max(
(
line.split()[1]
for line in run_capture(
"git", "ls-remote", CLONED_REMOTE, "refs/heads/release-*"
).stdout.splitlines()
),
key=lambda branch: [int(part) for part in branch_pat.search(branch).groups()],
)[len("refs/heads/") :]
print(f"Found release branch {release_branch}")

run(
"git",
"fetch",
"--depth=2",
CLONED_REMOTE,
pr_commit,
f"{release_branch}:{release_branch}",
)

# Perform the cherry-pick and push.
run("git", "config", "user.email", "[email protected]")
run("git", "config", "user.name", "Determined CI")
run("git", "checkout", release_branch)
cherry_pick_skipping_empty(pr_commit)
run("git", "push", CLONED_REMOTE, f"{release_branch}:{release_branch}")

print("Cherry-pick succeeded, updating item status")
set_project_pr_status(current_project_id(), pr_id, FIX_UNRELEASED_STATUS)
except subprocess.CalledProcessError:
import traceback

traceback.print_exc()
print("Cherry-pick failed, adding PR as conflicted")
set_project_pr_status(current_project_id(), pr_id, FIX_CONFLICT_STATUS)
requests.post(
"https://casper.internal.infra.determined.ai/hubot/conflict",
headers={"X-Casper-Token": CASPER_TOKEN},
json={"url": pr["url"], "logs_url": os.environ.get("LOGS_URL")},
)


class Actions:
@staticmethod
def pr_merged(pr_id: str):
pr_labels = gql.get_pr_labels(id=pr_id)["node"]["labels"]["nodes"]
print("Labels of merged PR:", [label["name"] for label in pr_labels])
if any(label["name"] == CHERRY_PICK_LABEL for label in pr_labels):
if any(label["name"] == current_backport_label() for label in pr_labels):
print("Cherry-picking labeled merged PR")
cherry_pick_pr(pr_id)
else:
title = gql.get_pr_title(id=pr_id)["node"]["title"]
if re.match(r"(feat|fix)\S*:", title, re.IGNORECASE) is not None:
print("Adding feat/fix PR")
elif re.match(r"\S+:", title, re.IGNORECASE) is not None:
print("Skipping non-feat/fix PR")
return
else:
print("Adding PR of unknown type")

print("Adding merged PR to next release project")
add_tracking_issue_to_project(next_project_id(), pr_id, NEEDS_TESTING_STATUS)

@staticmethod
def pr_labeled(pr_id: str, label: str):
if label != CHERRY_PICK_LABEL:
if label != current_backport_label():
return

state = gql.get_pr_state(id=pr_id)["node"]["state"]
if state == "OPEN":
print("Adding labeled open PR to current release project")
add_item_to_project(current_project_id(), pr_id, FIX_OPEN_STATUS)
elif state == "MERGED":
# TODO Maybe delete the tracking issue in the next release that was
# TODO CAROLINA Maybe delete the tracking issue in the next release that was
# created when this merged without a label.
print("Cherry-picking labeled merged PR")
add_item_to_project(current_project_id(), pr_id, FIX_OPEN_STATUS)
cherry_pick_pr(pr_id)
elif state == "CLOSED":
print("Ignoring label addition to closed PR")

@staticmethod
def pr_unlabeled(pr_id: str, label: str):
if label != CHERRY_PICK_LABEL:
if label != current_backport_label():
return

state = gql.get_pr_state(id=pr_id)["node"]["state"]
Expand All @@ -266,12 +205,6 @@ class Actions:
else:
print(f"Ignoring label removal from {state.lower()} PR")

@staticmethod
def cherry_pick_conflict_resolved(pr_id: str):
# TODO Use Git to confirm the cherry-pick was done.
project_id = current_project_id()
set_project_pr_status(project_id, pr_id, FIX_UNRELEASED_STATUS)

@staticmethod
def release_unreleased_prs():
after_cursor = None
Expand Down

0 comments on commit 37b70a7

Please sign in to comment.