Coverage for tools / gitlab_projects.py: 76%
97 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-21 08:53 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-21 08:53 +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 # pylint: disable=too-many-locals
109 parser = ArgumentParserFactory.default_parser(__doc__).parser
110 subparsers = parser.add_subparsers(title="actions", dest="actions", help="sub-command help", required=True)
112 # Common arguments
113 factory = ArgumentParserFactory.parent_parser()
114 factory.add_student_repo_info_file()
115 factory.add_gitlab_token()
117 # Create issues parser
118 create_issue_factory = factory.copy()
119 create_issue_factory.add_issue_md_slide()
120 create_issue_factory.add_homework_number()
121 create_issue_factory.add_due_date()
122 parser_issues = subparsers.add_parser(
123 "create_issues",
124 parents=[create_issue_factory.parser],
125 formatter_class=ArgumentDefaultsHelpFormatter,
126 description="Create Gitlab issues from homework slides",
127 help="Create Gitlab issues from homework slides",
128 )
129 parser_issues.set_defaults(func=edit_create_issues)
131 # Comment issues parser
132 comment_issue_factory = factory.copy()
133 comment_issue_factory.add_issue_number()
134 comment_issue_factory.add_message("Message as string or path to an `.md` file with the message")
135 comment_issue_factory.add_state_event()
136 parser_comment = subparsers.add_parser(
137 "comment_issue",
138 parents=[comment_issue_factory.parser],
139 formatter_class=ArgumentDefaultsHelpFormatter,
140 description="Comment to Gitlab issues via message or markdown slides",
141 help="Comment to Gitlab issues via message or markdown slides",
142 )
143 parser_comment.set_defaults(func=edit_comment_issue)
145 # Fetch code parser
146 fetch_code_factory = factory.copy()
147 fetch_code_factory.add_workspace()
148 parser_fetch = subparsers.add_parser(
149 "fetch_code",
150 parents=[fetch_code_factory.parser],
151 formatter_class=ArgumentDefaultsHelpFormatter,
152 description="Fetch (clone or pull) Gitlab repositories",
153 help="Fetch (clone or pull) Gitlab repositories",
154 )
155 parser_fetch.set_defaults(func=edit_fetch_code)
157 # Evaluate code parser
158 evaluate_code_factory = factory.copy()
159 evaluate_code_factory.add_homework_number()
160 evaluate_code_factory.add_job_factory_path()
161 evaluate_code_factory.add_workspace()
162 evaluate_code_factory.add_date_sine_last_homework()
163 evaluate_code_factory.add_evaluation_date()
164 parser_evaluate = subparsers.add_parser(
165 "evaluate_code",
166 parents=[evaluate_code_factory.parser],
167 formatter_class=ArgumentDefaultsHelpFormatter,
168 description="Fetch (clone or pull) Gitlab repositories and evaluate code",
169 help="Fetch (clone or pull) Gitlab repositories and evaluate code",
170 )
171 parser_evaluate.set_defaults(func=edit_evaluate_code)
173 # Upload files parser
174 upload_files_factory = factory.copy()
175 upload_files_factory.add_source_folder(None)
176 parser_upload_files = subparsers.add_parser(
177 "upload_files",
178 parents=[upload_files_factory.parser],
179 formatter_class=ArgumentDefaultsHelpFormatter,
180 description="Upload files via commit to Gitlab from source folder",
181 help="Upload files via commit to Gitlab from source folder",
182 )
183 parser_upload_files.set_defaults(func=edit_upload_files)
185 # Commit changes parser
186 commit_changes_factory = factory.copy()
187 commit_changes_factory.add_source_folder(None)
188 commit_changes_factory.add_message("Commit message used for all repos")
189 commit_changes_factory.add_workspace()
190 commit_changes_factory.add_keep_solutions()
191 parser_commit_changes = subparsers.add_parser(
192 "commit_changes",
193 parents=[commit_changes_factory.parser],
194 formatter_class=ArgumentDefaultsHelpFormatter,
195 description="Copy source folder to workspace and commit the changes",
196 help="Copy source folder to workspace and commit the changes",
197 )
198 parser_commit_changes.set_defaults(func=edit_commit_changes)
200 # Add users parser
201 add_users_factory = factory.copy()
202 add_users_factory.add_student_group_info_file()
203 parser_add_users = subparsers.add_parser(
204 "add_users",
205 parents=[add_users_factory.parser],
206 formatter_class=ArgumentDefaultsHelpFormatter,
207 description="Add all users to their respective repositories",
208 help="Add all users to their respective repositories",
209 )
210 parser_add_users.set_defaults(func=edit_add_users)
212 return parser.parse_args(arguments[1:])
215def main() -> None:
216 """Main."""
217 args = parse_arguments(sys.argv)
218 args.func(args)
221if __name__ == "__main__":
222 main()