| """Subcommand to mark preparation task as complete.""" | |
| import re | |
| from dev.release.gh import GitHub | |
| from dev.release.release_issue import ( | |
| parse_checklist_state, | |
| update_task_in_body, | |
| ) | |
| from dev.release.utils import set_github_output | |
| class CompletePrepare: | |
| """Class to mark preparation task as complete.""" | |
| def __init__(self, args, gh: GitHub): | |
| self.args = args | |
| self.gh = gh | |
| def run(self) -> int: | |
| """Executes the complete-prepare subcommand (Phase 2 PR merged).""" | |
| args = self.args | |
| pr_number = args.pr | |
| issue_number = args.issue | |
| if not pr_number and not issue_number: | |
| print("Error: Either --pr or --issue must be provided.") | |
| return 1 | |
| if not pr_number and issue_number: | |
| issue_body = self.gh.get_issue_body(issue_number) | |
| state = parse_checklist_state(issue_body) | |
| prep_task = state.get("prepare_release") | |
| if not prep_task or not prep_task.pr: | |
| print( | |
| f"Error: Could not find PR reference for 'Prepare Release'" | |
| f" in issue #{issue_number}." | |
| ) | |
| return 1 | |
| pr_number = int(prep_task.pr.lstrip("#")) | |
| print(f"Completing preparation for PR #{pr_number}...") | |
| pr_info = self.gh.get_pr_info(pr_number) | |
| if not pr_info or pr_info.get("state") != "MERGED": | |
| state = pr_info.get("state", "UNKNOWN") if pr_info else "NOT_FOUND" | |
| print(f"Error: PR #{pr_number} is not merged yet (state: {state}).") | |
| return 1 | |
| if not issue_number: | |
| # Resolve issue number from PR body | |
| pr_body = pr_info.get("body") or "" | |
| match = re.search(r"Work towards #(\d+)", pr_body) | |
| if not match: | |
| match = re.search(r"#(\d+)", pr_body) | |
| if not match: | |
| print( | |
| f"Error: Could not determine tracking issue number from PR" | |
| f" #{pr_number} body: {pr_body}" | |
| ) | |
| return 1 | |
| issue_number = int(match.group(1)) | |
| print(f"Resolved tracking issue #{issue_number} from PR #{pr_number} body.") | |
| commit_sha = pr_info["mergeCommit"]["oid"] | |
| short_commit = commit_sha[:8] | |
| print( | |
| f"PR #{pr_number} merged at commit {commit_sha}. Updating tracking issue..." | |
| ) | |
| # Update checklist: mark Prepare Release as done (checked) and set SUCCESS | |
| body = self.gh.get_issue_body(issue_number) | |
| metadata = { | |
| "status": "done", | |
| "pr": f"#{pr_number}", | |
| "commit": short_commit, | |
| } | |
| updated_body = update_task_in_body( | |
| body, "Prepare Release", checked=True, metadata=metadata | |
| ) | |
| self.gh.update_issue_body(issue_number, updated_body) | |
| print("Prepare Release task marked complete successfully!") | |
| set_github_output("issue", str(issue_number)) | |
| return 0 | |
| @classmethod | |
| def add_parser(cls, subparsers): | |
| """Adds parser for complete-prepare subcommand.""" | |
| parser = subparsers.add_parser( | |
| "complete-prepare", | |
| help="Mark the Prepare Release task as complete in the tracking issue.", | |
| ) | |
| parser.add_argument( | |
| "--pr", | |
| type=int, | |
| required=False, | |
| help="The merged preparation PR number.", | |
| ) | |
| parser.add_argument( | |
| "--issue", | |
| type=int, | |
| required=False, | |
| help="The release tracking issue number.", | |
| ) | |
| parser.set_defaults(command=cls.run_from_args) | |
| @classmethod | |
| def run_from_args(cls, args): | |
| """Instantiates and runs the command from parsed args.""" | |
| gh = GitHub() | |
| return cls(args, gh).run() |