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

1"""Perform actions on gitlab projects.""" 

2 

3import sys 

4from argparse import ArgumentDefaultsHelpFormatter, Namespace 

5from pathlib import Path 

6 

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 

22 

23 

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) 

29 

30 

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) 

35 

36 

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) 

40 

41 

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) 

55 

56 

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) 

60 

61 

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) 

68 

69 

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 ) 

77 

78 

79def parse_arguments(arguments: list[str]) -> Namespace: 

80 """Parse CLI arguments.""" 

81 # pylint: disable=too-many-locals 

82 

83 parser = ArgumentParserFactory.default_parser(__doc__).parser 

84 subparsers = parser.add_subparsers(title="actions", dest="actions", help="sub-command help", required=True) 

85 

86 # Common arguments 

87 factory = ArgumentParserFactory.parent_parser() 

88 factory.add_student_repo_info_file() 

89 factory.add_gitlab_token() 

90 

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) 

104 

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) 

118 

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) 

130 

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) 

146 

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) 

158 

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) 

173 

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) 

185 

186 return parser.parse_args(arguments[1:]) 

187 

188 

189def main() -> None: 

190 """Main.""" 

191 args = parse_arguments(sys.argv) 

192 args.func(args) 

193 

194 

195if __name__ == "__main__": 

196 main()