Coverage for tools/gitlab_projects.py: 77%
95 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-02 05:55 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-02 05:55 +0000
1"""Perform actions on gitlab projects."""
3import sys
4from argparse import ArgumentDefaultsHelpFormatter, Namespace
5from pathlib import Path
7from sel_tools.code_evaluation.evaluate_code import evaluate_code
8from sel_tools.code_evaluation.jobs.factory import EvaluationJobFactory
9from sel_tools.code_evaluation.report import write_evaluation_reports
10from sel_tools.diff_creation.create_diff import create_diff
11from sel_tools.diff_creation.report import write_diff_reports, write_report_for_inactive_student_repos
12from sel_tools.file_export.export_item import export_items
13from sel_tools.file_parsing.slide_parser import get_tasks_from_slides
14from sel_tools.gitlab_api.add_user import add_users
15from sel_tools.gitlab_api.comment_issue import comment_issues
16from sel_tools.gitlab_api.create_commit import commit_changes, upload_files
17from sel_tools.gitlab_api.create_issue import create_issues
18from sel_tools.gitlab_api.fetch_repo import fetch_repos
19from sel_tools.utils.args import ArgumentParserFactory
20from sel_tools.utils.comment import Comment
21from sel_tools.utils.task import configure_tasks
24def edit_create_issues(args: Namespace) -> None:
25 """Default action for create_issues subcommand."""
26 tasks = get_tasks_from_slides(Path(args.issue_md_slides.name))
27 tasks = configure_tasks(tasks, args.due_date, args.homework_number)
28 create_issues(tasks, Path(args.student_repo_info_file.name), args.gitlab_token)
31def edit_comment_issue(args: Namespace) -> None:
32 """Default action for comment_issue subcommand."""
33 comment = Comment.create(args.issue_number, args.message, args.state_event)
34 comment_issues(comment, Path(args.student_repo_info_file.name), args.gitlab_token)
37def edit_fetch_code(args: Namespace) -> None:
38 """Default action for fetch_code subcommand."""
39 fetch_repos(args.workspace, Path(args.student_repo_info_file.name), args.gitlab_token)
42def edit_evaluate_code(args: Namespace) -> None:
43 """Default action for evaluate_code subcommand."""
44 gitlab_projects = fetch_repos(args.workspace, Path(args.student_repo_info_file.name), args.gitlab_token)
45 factory = EvaluationJobFactory.load_factory_from_file(args.job_factory)
46 evaluation_reports = evaluate_code(factory, gitlab_projects, args.homework_number, args.evaluation_date)
47 write_evaluation_reports(evaluation_reports, f"homework-{args.homework_number}-report")
48 diff_reports = create_diff(
49 [project.local_path for project in gitlab_projects],
50 args.date_last_homework,
51 args.evaluation_date,
52 )
53 write_diff_reports(diff_reports, f"homework-{args.homework_number}-diff")
54 write_report_for_inactive_student_repos(diff_reports, args.workspace)
57def edit_upload_files(args: Namespace) -> None:
58 """Default action for upload_files subcommand."""
59 upload_files(args.source_path, Path(args.student_repo_info_file.name), args.gitlab_token)
62def edit_commit_changes(args: Namespace) -> None:
63 """Default action for commit_changes subcommand."""
64 gitlab_projects = fetch_repos(args.workspace, Path(args.student_repo_info_file.name), args.gitlab_token)
65 student_repos = [project.local_path for project in gitlab_projects]
66 export_items(args.source_path, student_repos, args.keep_solutions)
67 commit_changes(student_repos, args.message)
70def edit_add_users(args: Namespace) -> None:
71 """Default action for add_users subcommand."""
72 add_users(
73 Path(args.student_repo_info_file.name),
74 Path(args.student_group_info_file.name),
75 args.gitlab_token,
76 )
79def parse_arguments(arguments: list[str]) -> Namespace:
80 """Parse CLI arguments."""
81 # pylint: disable=too-many-locals
83 parser = ArgumentParserFactory.default_parser(__doc__).parser
84 subparsers = parser.add_subparsers(title="actions", dest="actions", help="sub-command help", required=True)
86 # Common arguments
87 factory = ArgumentParserFactory.parent_parser()
88 factory.add_student_repo_info_file()
89 factory.add_gitlab_token()
91 # Create issues parser
92 create_issue_factory = factory.copy()
93 create_issue_factory.add_issue_md_slide()
94 create_issue_factory.add_homework_number()
95 create_issue_factory.add_due_date()
96 parser_issues = subparsers.add_parser(
97 "create_issues",
98 parents=[create_issue_factory.parser],
99 formatter_class=ArgumentDefaultsHelpFormatter,
100 description="Create Gitlab issues from homework slides",
101 help="Create Gitlab issues from homework slides",
102 )
103 parser_issues.set_defaults(func=edit_create_issues)
105 # Comment issues parser
106 comment_issue_factory = factory.copy()
107 comment_issue_factory.add_issue_number()
108 comment_issue_factory.add_message("Message or path to a .md file")
109 comment_issue_factory.add_state_event()
110 parser_comment = subparsers.add_parser(
111 "comment_issue",
112 parents=[comment_issue_factory.parser],
113 formatter_class=ArgumentDefaultsHelpFormatter,
114 description="Comment to Gitlab issues via message or markdown slides",
115 help="Comment to Gitlab issues via message or markdown slides",
116 )
117 parser_comment.set_defaults(func=edit_comment_issue)
119 # Fetch code parser
120 fetch_code_factory = factory.copy()
121 fetch_code_factory.add_workspace()
122 parser_fetch = subparsers.add_parser(
123 "fetch_code",
124 parents=[fetch_code_factory.parser],
125 formatter_class=ArgumentDefaultsHelpFormatter,
126 description="Fetch (clone or pull) Gitlab repositories",
127 help="Fetch (clone or pull) Gitlab repositories",
128 )
129 parser_fetch.set_defaults(func=edit_fetch_code)
131 # Evaluate code parser
132 evaluate_code_factory = factory.copy()
133 evaluate_code_factory.add_homework_number()
134 evaluate_code_factory.add_job_factory_path()
135 evaluate_code_factory.add_workspace()
136 evaluate_code_factory.add_date_sine_last_homework()
137 evaluate_code_factory.add_evaluation_date()
138 parser_evaluate = subparsers.add_parser(
139 "evaluate_code",
140 parents=[evaluate_code_factory.parser],
141 formatter_class=ArgumentDefaultsHelpFormatter,
142 description="Fetch (clone or pull) Gitlab repositories and evaluate code",
143 help="Fetch (clone or pull) Gitlab repositories and evaluate code",
144 )
145 parser_evaluate.set_defaults(func=edit_evaluate_code)
147 # Upload files parser
148 upload_files_factory = factory.copy()
149 upload_files_factory.add_source_folder(None)
150 parser_upload_files = subparsers.add_parser(
151 "upload_files",
152 parents=[upload_files_factory.parser],
153 formatter_class=ArgumentDefaultsHelpFormatter,
154 description="Upload files via commit to Gitlab from source folder",
155 help="Upload files via commit to Gitlab from source folder",
156 )
157 parser_upload_files.set_defaults(func=edit_upload_files)
159 # Commit changes parser
160 commit_changes_factory = factory.copy()
161 commit_changes_factory.add_source_folder(None)
162 commit_changes_factory.add_message("Commit message used for all repos")
163 commit_changes_factory.add_workspace()
164 commit_changes_factory.add_keep_solutions()
165 parser_commit_changes = subparsers.add_parser(
166 "commit_changes",
167 parents=[commit_changes_factory.parser],
168 formatter_class=ArgumentDefaultsHelpFormatter,
169 description="Copy source folder to workspace and commit the changes",
170 help="Copy source folder to workspace and commit the changes",
171 )
172 parser_commit_changes.set_defaults(func=edit_commit_changes)
174 # Add users parser
175 add_users_factory = factory.copy()
176 add_users_factory.add_student_group_info_file()
177 parser_add_users = subparsers.add_parser(
178 "add_users",
179 parents=[add_users_factory.parser],
180 formatter_class=ArgumentDefaultsHelpFormatter,
181 description="Add all users to their respective repositories",
182 help="Add all users to their respective repositories",
183 )
184 parser_add_users.set_defaults(func=edit_add_users)
186 return parser.parse_args(arguments[1:])
189def main() -> None:
190 """Main."""
191 args = parse_arguments(sys.argv)
192 args.func(args)
195if __name__ == "__main__":
196 main()