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