From 011b9c26b012a905953cfa0413c169fb6ac8f149 Mon Sep 17 00:00:00 2001 From: Min Zhengjie Date: Wed, 18 Jun 2025 14:22:55 +0800 Subject: [PATCH] feat: generate repos using templates (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feature allows choosing templates when creating repos for individuals and groups. Reviewed-on: https://focs.ji.sjtu.edu.cn/git/JOJ/Joint-Teapot/pulls/1 Reviewed-by: 张泊明518370910136 Co-authored-by: Min Zhengjie Co-committed-by: Min Zhengjie --- joint_teapot/app.py | 12 ++++-- joint_teapot/teapot.py | 7 ++-- joint_teapot/workers/gitea.py | 77 +++++++++++++++++++++++++---------- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/joint_teapot/app.py b/joint_teapot/app.py index 2cca38e..ed8e83c 100644 --- a/joint_teapot/app.py +++ b/joint_teapot/app.py @@ -50,13 +50,17 @@ def add_all_canvas_students_to_teams(team_names: List[str]) -> None: "create-personal-repos", help="create personal repos on gitea for all canvas students", ) -def create_personal_repos_for_all_canvas_students(suffix: str = Option("")) -> None: - tea.pot.create_personal_repos_for_all_canvas_students(suffix) +def create_personal_repos_for_all_canvas_students( + suffix: str = Option(""), template: str = Option("", help="generate from template") +) -> None: + tea.pot.create_personal_repos_for_all_canvas_students(suffix, template) @app.command("create-teams", help="create teams on gitea by canvas groups") -def create_teams_and_repos_by_canvas_groups(group_prefix: str) -> None: - tea.pot.create_teams_and_repos_by_canvas_groups(group_prefix) +def create_teams_and_repos_by_canvas_groups( + group_prefix: str, template: str = Option("", help="generate from template") +) -> None: + tea.pot.create_teams_and_repos_by_canvas_groups(group_prefix, template) @app.command("get-public-keys", help="list all public keys on gitea") diff --git a/joint_teapot/teapot.py b/joint_teapot/teapot.py index 8c6b4e9..6ac888e 100644 --- a/joint_teapot/teapot.py +++ b/joint_teapot/teapot.py @@ -96,15 +96,16 @@ class Teapot: return self.gitea.add_canvas_students_to_teams(self.canvas.students, team_names) def create_personal_repos_for_all_canvas_students( - self, suffix: str = "" + self, suffix: str = "", template: str = "" ) -> List[str]: return self.gitea.create_personal_repos_for_canvas_students( self.canvas.students, lambda user: default_repo_name_convertor(user) + suffix, + template, ) def create_teams_and_repos_by_canvas_groups( - self, group_prefix: str = "" + self, group_prefix: str = "", template: str = "" ) -> List[str]: def convertor(name: str) -> Optional[str]: if group_prefix and not name.startswith(group_prefix): @@ -114,7 +115,7 @@ class Teapot: return f"{team_name}{number:02}" return self.gitea.create_teams_and_repos_by_canvas_groups( - self.canvas.students, self.canvas.groups, convertor, convertor + self.canvas.students, self.canvas.groups, convertor, convertor, template ) def get_public_key_of_all_canvas_students(self) -> Dict[str, List[str]]: diff --git a/joint_teapot/workers/gitea.py b/joint_teapot/workers/gitea.py index eced7d5..d3422e7 100644 --- a/joint_teapot/workers/gitea.py +++ b/joint_teapot/workers/gitea.py @@ -116,6 +116,7 @@ class Gitea: repo_name_convertor: Callable[ [User], Optional[str] ] = default_repo_name_convertor, + template: str = "", ) -> List[str]: repo_names = [] for student in students: @@ -123,17 +124,32 @@ class Gitea: if repo_name is None: continue repo_names.append(repo_name) - body = { - "auto_init": False, - "default_branch": settings.default_branch, - "name": repo_name, - "private": True, - "template": False, - "trust_model": "default", - } try: try: - self.organization_api.create_org_repo(self.org_name, body=body) + if template == "": + body = { + "auto_init": False, + "default_branch": settings.default_branch, + "name": repo_name, + "private": True, + "template": False, + "trust_model": "default", + } + self.organization_api.create_org_repo(self.org_name, body=body) + else: + body = { + "default_branch": settings.default_branch, + "git_content": True, + "git_hooks": True, + "labels": True, + "name": repo_name, + "owner": self.org_name, + "private": True, + "protected_branch": True, + } + self.repository_api.generate_repo( + self.org_name, template, body=body + ) logger.info( f"Personal repo {self.org_name}/{repo_name} for {student} created" ) @@ -158,6 +174,7 @@ class Gitea: groups: PaginatedList, team_name_convertor: Callable[[str], Optional[str]] = lambda name: name, repo_name_convertor: Callable[[str], Optional[str]] = lambda name: name, + template: str = "", permission: PermissionEnum = PermissionEnum.write, ) -> List[str]: repo_names = [] @@ -190,21 +207,37 @@ class Gitea: ], }, ) - logger.info(f"{self.org_name}/{team_name} created") + logger.info(f"Team {team_name} created") if first(repos, lambda repo: repo.name == repo_name) is None: repo_names.append(repo_name) - self.organization_api.create_org_repo( - self.org_name, - body={ - "auto_init": False, - "default_branch": settings.default_branch, - "name": repo_name, - "private": True, - "template": False, - "trust_model": "default", - }, - ) - logger.info(f"Team {team_name} created") + if template == "": + self.organization_api.create_org_repo( + self.org_name, + body={ + "auto_init": False, + "default_branch": settings.default_branch, + "name": repo_name, + "private": True, + "template": False, + "trust_model": "default", + }, + ) + else: + self.repository_api.generate_repo( + self.org_name, + template, + body={ + "default_branch": settings.default_branch, + "git_content": True, + "git_hooks": True, + "labels": True, + "name": repo_name, + "owner": self.org_name, + "private": True, + "protected_branch": True, + }, + ) + logger.info(f"{self.org_name}/{team_name} created") try: self.organization_api.org_add_team_repository( team.id, self.org_name, repo_name