File indexing completed on 2026-07-25 08:29:59
0001 import sys
0002
0003 import click
0004 from github import Auth, Github, GithubException
0005
0006 from ..github import download_artifact
0007
0008
0009 @click.command()
0010 @click.option('--artifact-name', default="rec_dis_18x275_minQ2=1000_craterlake_18x275.edm4eic.root")
0011 @click.option('--token', envvar="GITHUB_TOKEN", required=True, help="GitHub access token (defaults to GITHUB_TOKEN environment variable)")
0012 @click.option('--owner', default="eic", help="Owner of the target repository")
0013 @click.option('--repo', default="EICrecon", help="Name of the target repository")
0014 @click.argument('pr_number', type=int)
0015 @click.pass_context
0016 def pr(ctx: click.Context, artifact_name: str, owner: str, pr_number: int, repo: str, token: str):
0017 gh = Github(auth=Auth.Token(token))
0018 repo = gh.get_user(owner).get_repo(repo)
0019
0020 click.secho(f'Fetching metadata for #{pr_number}...', fg='green', err=True)
0021 try:
0022 pr = repo.get_pull(pr_number)
0023 except GithubException as e:
0024 click.secho("Pull Request is not accessible", fg="red", err=True)
0025 click.secho(e)
0026 ctx.exit(1)
0027 click.echo(f"Title: {pr.title}", err=True)
0028 other_repo_message = ""
0029 if pr.head.repo != repo:
0030 other_repo_message = click.style(f"{pr.head.repo.owner.login}/{pr.head.repo.name}", italic=True) + "/"
0031 click.echo(f"PR head: {other_repo_message}{click.style(pr.head.ref, bold=True)}@{pr.head.sha}, targets {click.style(pr.base.ref, bold=True)}@{pr.base.sha}", err=True)
0032
0033 workflow_head = None
0034 workflow_base = None
0035 messages = []
0036
0037 def item_show_func(workflow):
0038 workflow_id = str(workflow.id) if hasattr(workflow, "id") else "?"
0039 head_found = "no" if workflow_head is None else "yes"
0040 base_found = "no" if workflow_base is None else "yes"
0041 return f"{workflow_id} head:{head_found} base:{base_found}"
0042
0043 with click.progressbar(
0044 repo.get_workflow_runs(),
0045 label="Loading workflows",
0046 item_show_func=item_show_func,
0047 file=sys.stderr,
0048 ) as workflows_bar:
0049 for workflow in workflows_bar:
0050
0051
0052 if workflow.head_repository == pr.head.repo and workflow.head_branch == pr.head.ref and workflow_head is None:
0053 if workflow.get_artifacts().totalCount == 0:
0054 messages.append(dict(message=f"Skipping workflow {workflow.html_url} on {workflow.head_branch} with no artifacts", fg="red", err=True))
0055 continue
0056 workflow_head = workflow
0057 if workflow.head_repository == repo and workflow.head_branch == pr.base.ref and workflow_base is None:
0058 if workflow.get_artifacts().totalCount == 0:
0059 messages.append(dict(message=f"Skipping workflow {workflow.html_url} on {workflow.head_branch} with no artifacts", fg="red", err=True))
0060 continue
0061 workflow_base = workflow
0062 if workflow_head is not None and workflow_base is not None:
0063 break
0064
0065 if workflow_head is None:
0066 click.secho("No completed workflow found for head branch", fg="red")
0067 ctx.exit(1)
0068 if workflow_base is None:
0069 click.secho("No completed workflow found for base branch", fg="red")
0070 ctx.exit(1)
0071
0072 for message in messages:
0073 click.secho(**message)
0074
0075 click.echo(f"PR base workflow: {workflow_base.html_url}", err=True)
0076 click.echo(f"PR head workflow: {workflow_head.html_url}", err=True)
0077
0078 click.echo(download_artifact(workflow_base, artifact_name, token=token, click=click))
0079 click.echo(download_artifact(workflow_head, artifact_name, token=token, click=click))
0080
0081
0082 @click.command()
0083 @click.option('--artifact-name', default="rec_dis_18x275_minQ2=1000_craterlake_18x275.edm4eic.root")
0084 @click.option('--token', envvar="GITHUB_TOKEN", required=True, help="GitHub access token (defaults to GITHUB_TOKEN environment variable)")
0085 @click.option('--owner', default="eic", help="Owner of the target repository")
0086 @click.option('--repo', default="EICrecon", help="Name of the target repository")
0087 @click.argument('ref', type=str)
0088 @click.pass_context
0089 def rev(ctx: click.Context, artifact_name: str, owner: str, ref: str, repo: str, token: str):
0090 gh = Github(auth=Auth.Token(token))
0091 repo = gh.get_user(owner).get_repo(repo)
0092
0093 rev = repo.get_commit(ref)
0094
0095 def item_show_func(workflow):
0096 workflow_id = str(workflow.id) if hasattr(workflow, "id") else "?"
0097 head_found = "no" if workflow_head is None else "yes"
0098 return f"{workflow_id} head:{head_found}"
0099
0100 workflow_head = None
0101 messages = []
0102
0103 with click.progressbar(
0104 repo.get_workflow_runs(),
0105 label="Loading workflows",
0106 item_show_func=item_show_func,
0107 file=sys.stderr,
0108 ) as workflows_bar:
0109 for workflow in workflows_bar:
0110
0111
0112 if workflow.head_repository == repo and workflow.head_sha == rev.sha and workflow_head is None:
0113 if workflow.get_artifacts().totalCount == 0:
0114 messages.append(dict(message=f"Skipping workflow {workflow.html_url} on {workflow.head_branch} with no artifacts", fg="red", err=True))
0115 continue
0116 workflow_head = workflow
0117 if workflow_head is not None:
0118 break
0119
0120 if workflow_head is None:
0121 click.secho("No completed workflow found for head branch", fg="red")
0122 ctx.exit(1)
0123
0124 for message in messages:
0125 click.secho(**message)
0126
0127 click.echo(f"PR head workflow: {workflow_head.html_url}", err=True)
0128
0129 click.echo(download_artifact(workflow_head, artifact_name, token=token, click=click))
0130
0131
0132 class ForwardGroup(click.Group):
0133 def resolve_command(self, ctx, args):
0134 try:
0135 cmd_name, cmd, args = super().resolve_command(ctx, args)
0136 except click.exceptions.UsageError as e:
0137 click.secho(f"Invoking `capy' without subcommand is deprecated. Use `capy pr'.", fg="yellow", err=True)
0138 args = ["pr"] + args
0139 cmd_name, cmd, args = super().resolve_command(ctx, args)
0140 return cmd_name, cmd, args
0141
0142 @click.group(cls=ForwardGroup, context_settings={'help_option_names': ['-h', '--help']})
0143 @click.option('--artifact-name', default="rec_dis_18x275_minQ2=1000_craterlake_18x275.edm4eic.root")
0144 @click.option('--token', envvar="GITHUB_TOKEN", required=True, help="GitHub access token (defaults to GITHUB_TOKEN environment variable)")
0145 @click.option('--owner', default="eic", help="Owner of the target repository")
0146 @click.option('--repo', default="EICrecon", help="Name of the target repository")
0147 def capy(**kwargs):
0148 pass
0149
0150
0151 capy.add_command(pr)
0152 capy.add_command(rev)