Add unified Gitea skill workflows
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
"""List, create, and comment on Gitea pull requests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
from common import (
|
||||
api_base,
|
||||
current_branch,
|
||||
load_token,
|
||||
remote_default_branch,
|
||||
request_json,
|
||||
resolve_repo,
|
||||
)
|
||||
from push_gitea import compute_push_plan, execute_push
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="List, create, and comment on Gitea pull requests."
|
||||
)
|
||||
parser.add_argument("--repo-url", help="Explicit target repo URL.")
|
||||
parser.add_argument("--repo", help="Shorthand owner/repo. Requires GITEA_BASE_URL.")
|
||||
parser.add_argument("--remote", default="origin", help="Git remote name. Default: origin")
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
list_parser = subparsers.add_parser("list", help="List pull requests.")
|
||||
list_parser.add_argument(
|
||||
"--state",
|
||||
default="open",
|
||||
choices=("open", "closed", "all"),
|
||||
help="Pull request state filter.",
|
||||
)
|
||||
list_parser.add_argument(
|
||||
"--limit",
|
||||
default=20,
|
||||
type=int,
|
||||
help="Maximum number of pull requests to return.",
|
||||
)
|
||||
|
||||
create_parser = subparsers.add_parser("create", help="Create a pull request.")
|
||||
create_parser.add_argument("--base", help="Base branch. Default: remote default branch.")
|
||||
create_parser.add_argument("--head", help="Head branch. Default: current branch.")
|
||||
create_parser.add_argument("--title", required=True, help="Pull request title.")
|
||||
create_parser.add_argument("--body", default="", help="Pull request body.")
|
||||
|
||||
comment_parser = subparsers.add_parser("comment", help="Comment on a pull request.")
|
||||
comment_parser.add_argument("pr", type=int, help="Pull request number.")
|
||||
comment_parser.add_argument("--body", required=True, help="Comment body.")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def summarize_pull_request(item: dict) -> dict:
|
||||
user = item.get("user") or {}
|
||||
head = item.get("head") or {}
|
||||
base = item.get("base") or {}
|
||||
return {
|
||||
"number": item.get("number"),
|
||||
"title": item.get("title"),
|
||||
"state": item.get("state"),
|
||||
"html_url": item.get("html_url"),
|
||||
"author": user.get("full_name") or user.get("login"),
|
||||
"head": head.get("ref"),
|
||||
"base": base.get("ref"),
|
||||
"created_at": item.get("created_at"),
|
||||
"updated_at": item.get("updated_at"),
|
||||
}
|
||||
|
||||
|
||||
def list_pull_requests(args: argparse.Namespace) -> dict:
|
||||
context = resolve_repo(repo_url=args.repo_url, repo=args.repo, remote=args.remote)
|
||||
token = load_token(required=True)
|
||||
url = f"{api_base(context)}/pulls?state={args.state}&page=1&limit={args.limit}"
|
||||
data = request_json(url, token)
|
||||
if not isinstance(data, list):
|
||||
raise SystemExit("Unexpected pull request list response.")
|
||||
return {
|
||||
"action": "list",
|
||||
"repo_url": context.repo_url,
|
||||
"state": args.state,
|
||||
"limit": args.limit,
|
||||
"count": len(data),
|
||||
"pull_requests": [summarize_pull_request(item) for item in data],
|
||||
}
|
||||
|
||||
|
||||
def create_pull_request(args: argparse.Namespace) -> dict:
|
||||
context = resolve_repo(repo_url=args.repo_url, repo=args.repo, remote=args.remote)
|
||||
token = load_token(required=True)
|
||||
head = args.head or current_branch()
|
||||
base = args.base or remote_default_branch(args.remote)
|
||||
|
||||
push_plan = compute_push_plan(
|
||||
repo_url=args.repo_url,
|
||||
repo=args.repo,
|
||||
remote=args.remote,
|
||||
branch=head,
|
||||
force=False,
|
||||
)
|
||||
push_result = None
|
||||
if push_plan["needs_push"]:
|
||||
push_result = execute_push(push_plan, force=False)
|
||||
elif push_plan["status"] == "blocked":
|
||||
raise SystemExit(
|
||||
"Cannot create PR because the current branch has diverged from the remote branch."
|
||||
)
|
||||
|
||||
payload = {"base": base, "head": head, "title": args.title, "body": args.body}
|
||||
created = request_json(f"{api_base(context)}/pulls", token, method="POST", payload=payload)
|
||||
if not isinstance(created, dict):
|
||||
raise SystemExit("Unexpected pull request creation response.")
|
||||
return {
|
||||
"action": "create",
|
||||
"repo_url": context.repo_url,
|
||||
"base": base,
|
||||
"head": head,
|
||||
"push": push_result,
|
||||
"pull_request": summarize_pull_request(created),
|
||||
}
|
||||
|
||||
|
||||
def comment_pull_request(args: argparse.Namespace) -> dict:
|
||||
context = resolve_repo(repo_url=args.repo_url, repo=args.repo, remote=args.remote)
|
||||
token = load_token(required=True)
|
||||
payload = {"body": args.body}
|
||||
created = request_json(
|
||||
f"{api_base(context)}/issues/{args.pr}/comments",
|
||||
token,
|
||||
method="POST",
|
||||
payload=payload,
|
||||
)
|
||||
if not isinstance(created, dict):
|
||||
raise SystemExit("Unexpected PR comment response.")
|
||||
user = created.get("user") or {}
|
||||
return {
|
||||
"action": "comment",
|
||||
"repo_url": context.repo_url,
|
||||
"pull_request": args.pr,
|
||||
"comment": {
|
||||
"id": created.get("id"),
|
||||
"html_url": created.get("html_url"),
|
||||
"author": user.get("full_name") or user.get("login"),
|
||||
"created_at": created.get("created_at"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
if args.command == "list":
|
||||
payload = list_pull_requests(args)
|
||||
elif args.command == "create":
|
||||
payload = create_pull_request(args)
|
||||
else:
|
||||
payload = comment_pull_request(args)
|
||||
print(json.dumps(payload, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user