From 23204ef168d055708d7d4def28a5a52167652fa0 Mon Sep 17 00:00:00 2001 From: mQzLjP <91550006+mQzLjP@users.noreply.github.com> Date: Wed, 21 May 2025 02:49:01 +0800 Subject: [PATCH] feat: create issue with milestone (#55) --- joint_teapot/app.py | 24 ++++++++++++---- joint_teapot/teapot.py | 10 ++----- joint_teapot/workers/gitea.py | 54 ++++++++++++++++++++++++++++++++--- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/joint_teapot/app.py b/joint_teapot/app.py index ab70c74..230f79f 100644 --- a/joint_teapot/app.py +++ b/joint_teapot/app.py @@ -90,8 +90,16 @@ def create_issue_for_repos( use_regex: bool = Option( False, "--regex", help="repo_names takes list of regexes if set" ), + milesetone: str = Option("", "--milestone", help="milestone title"), + labels: List[str] = Option( + [], + "--label", + help="labels to add to the issue (use --label A --label B to add multiple)", + ), ) -> None: - tea.pot.create_issue_for_repos(repo_names, title, body, from_file, use_regex) + tea.pot.create_issue_for_repos( + repo_names, title, body, from_file, use_regex, milesetone, labels + ) @app.command("create-comment", help="create a comment for an issue on gitea") @@ -103,11 +111,17 @@ def create_comment( tea.pot.create_comment(repo_name, index, body) -@app.command("create-milestones", help="create milestones on gitea") -def create_milestone_for_repos( - repo_names: List[str], title: str, description: str, due_on: datetime +@app.command( + "create-milestones", + help="create milestones on gitea", +) +def create_milestones( + title: str, + regex: str = Argument(".+"), + due_on: str = Argument("", help="milestone due-on date [%YYYY-%MM-%DD]"), + description: str = Argument(""), ) -> None: - tea.pot.create_milestone_for_repos(repo_names, title, description, due_on) + tea.pot.gitea.create_milestones(title, regex, due_on, description) @app.command("check-issues", help="check the existence of issue by title on gitea") diff --git a/joint_teapot/teapot.py b/joint_teapot/teapot.py index 129b08c..5efad94 100644 --- a/joint_teapot/teapot.py +++ b/joint_teapot/teapot.py @@ -146,6 +146,8 @@ class Teapot: body: str, from_file: bool = False, use_regex: bool = False, + milestone: str = "", + labels: List[str] = [], ) -> None: if from_file: try: @@ -173,7 +175,7 @@ class Teapot: affected_repos = repo_names for repo_name in affected_repos: - self.gitea.create_issue(repo_name, title, content) + self.gitea.create_issue(repo_name, title, content, True, milestone, labels) def create_comment( self, @@ -183,12 +185,6 @@ class Teapot: ) -> None: self.gitea.create_comment(repo_name, index, body) - def create_milestone_for_repos( - self, repo_names: List[str], title: str, description: str, due_on: datetime - ) -> None: - for repo_name in repo_names: - self.gitea.create_milestone(repo_name, title, description, due_on) - def check_exist_issue_by_title( self, repo_names: List[str], title: str ) -> List[str]: diff --git a/joint_teapot/workers/gitea.py b/joint_teapot/workers/gitea.py index 0667ca8..2732662 100644 --- a/joint_teapot/workers/gitea.py +++ b/joint_teapot/workers/gitea.py @@ -1,5 +1,4 @@ import re -from datetime import datetime from enum import Enum from functools import lru_cache from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, TypeVar @@ -345,6 +344,8 @@ class Gitea: title: str, body: str, assign_every_collaborators: bool = True, + milestone: str = "", + labels: list[str] = [], ) -> None: assignees = [] if assign_every_collaborators: @@ -356,10 +357,33 @@ class Gitea: repo_name, ) ] + milestone_id = None + if milestone: + milestone_list = self.issue_api.issue_get_milestones_list( + self.org_name, repo_name + ) + if milestone not in [m.title for m in milestone_list]: + logger.warning(f"Milestone {milestone} does not exist in {repo_name}") + else: + milestone_id = first( + [m.id for m in milestone_list if m.title == milestone] + ) + labels_id = [] + if labels: + labels_list = self.issue_api.issue_list_labels(self.org_name, repo_name) + labels_id = [l.id for l in labels_list if l.name in labels] + if not labels_id: + logger.warning(f"no label matches {labels}") self.issue_api.issue_create_issue( self.org_name, repo_name, - body={"title": title, "body": body, "assignees": assignees}, + body={ + "title": title, + "body": body, + "assignees": assignees, + "milestone": milestone_id, + "labels": labels_id, + }, ) logger.info(f'Created issue "{title}" in {repo_name}') @@ -382,15 +406,22 @@ class Gitea: repo_name: str, title: str, description: str, - due_on: datetime, + due_on: str, ) -> None: + if due_on == "": + self.issue_api.issue_create_milestone( + self.org_name, + repo_name, + body={"title": title, "description": description}, + ) + return self.issue_api.issue_create_milestone( self.org_name, repo_name, body={ "title": title, "description": description, - "due_on": due_on.strftime("%Y-%m-%dT%H:%M:%S.%fZ"), + "due_on": due_on + "T23:59:59.999Z", }, ) @@ -469,6 +500,21 @@ class Gitea: ) logger.info(f"Unsubscribed from {sub.name}") + def create_milestones( + self, milestone: str, regex: str, due_date: str, description: str + ) -> None: + for repo_name in self.get_all_repo_names(): + if not re.match(regex, repo_name): + continue + milestone_list = self.issue_api.issue_get_milestones_list( + self.org_name, repo_name + ) + if milestone in [m.title for m in milestone_list]: + logger.warning(f"Milestone {milestone} already exists in {repo_name}") + continue + self.create_milestone(repo_name, milestone, description, due_date) + logger.info(f"Created milestone {milestone} in {repo_name}") + if __name__ == "__main__": gitea = Gitea()