forked from JOJ/Joint-Teapot
		
	feat: joj3 auto retry on git push failed
This commit is contained in:
		
							parent
							
								
									0ad1e9540a
								
							
						
					
					
						commit
						a4f6482b21
					
				|  | @ -1,6 +1,7 @@ | ||||||
| import os | import os | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | from time import sleep | ||||||
| from typing import TYPE_CHECKING, List | from typing import TYPE_CHECKING, List | ||||||
| 
 | 
 | ||||||
| from filelock import FileLock | from filelock import FileLock | ||||||
|  | @ -530,7 +531,6 @@ def joj3_all( | ||||||
|         ) |         ) | ||||||
|     if skip_scoreboard and skip_failed_table: |     if skip_scoreboard and skip_failed_table: | ||||||
|         return |         return | ||||||
|     tea.pot.git  # trigger lazy load |  | ||||||
|     lock_file_path = os.path.join( |     lock_file_path = os.path.join( | ||||||
|         settings.repos_dir, repo_name, settings.joj3_lock_file_path |         settings.repos_dir, repo_name, settings.joj3_lock_file_path | ||||||
|     ) |     ) | ||||||
|  | @ -539,54 +539,67 @@ def joj3_all( | ||||||
|         + f"timeout: {settings.joj3_lock_file_timeout}" |         + f"timeout: {settings.joj3_lock_file_timeout}" | ||||||
|     ) |     ) | ||||||
|     with FileLock(lock_file_path, timeout=settings.joj3_lock_file_timeout).acquire(): |     with FileLock(lock_file_path, timeout=settings.joj3_lock_file_timeout).acquire(): | ||||||
|         logger.info("file lock acquired") |         retry_interval = 1 | ||||||
|         repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") |         git_push_ok = False | ||||||
|         repo: Repo = tea.pot.git.get_repo(repo_name) |         while not git_push_ok: | ||||||
|         if "grading" not in repo.remote().refs: |             logger.info("file lock acquired") | ||||||
|             logger.error( |             repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") | ||||||
|                 '"grading" branch not found in remote, create and push it to origin first.' |             repo: Repo = tea.pot.git.get_repo(repo_name) | ||||||
|             ) |             if "grading" not in repo.remote().refs: | ||||||
|             return |                 logger.error( | ||||||
|         if "grading" not in repo.branches: |                     '"grading" branch not found in remote, create and push it to origin first.' | ||||||
|             logger.error('"grading" branch not found in local, create it first.') |                 ) | ||||||
|             return |                 return | ||||||
|         repo.git.reset("--hard", "origin/grading") |             if "grading" not in repo.branches: | ||||||
|         if not skip_scoreboard: |                 logger.error('"grading" branch not found in local, create it first.') | ||||||
|             joj3.generate_scoreboard( |                 return | ||||||
|                 score_file_path, |             repo.git.reset("--hard", "origin/grading") | ||||||
|                 submitter, |             if not skip_scoreboard: | ||||||
|                 os.path.join(repo_path, scoreboard_file_name), |                 joj3.generate_scoreboard( | ||||||
|                 exercise_name, |                     score_file_path, | ||||||
|             ) |                     submitter, | ||||||
|             tea.pot.git.add_commit( |                     os.path.join(repo_path, scoreboard_file_name), | ||||||
|                 repo_name, |                     exercise_name, | ||||||
|                 [scoreboard_file_name], |                 ) | ||||||
|                 ( |                 tea.pot.git.add_commit( | ||||||
|                     f"joj3: update scoreboard for {exercise_name} by @{submitter} in " |                     repo_name, | ||||||
|                     f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" |                     [scoreboard_file_name], | ||||||
|                     f"gitea actions link: {gitea_actions_url}\n" |                     ( | ||||||
|                     f"gitea issue link: {gitea_issue_url}" |                         f"joj3: update scoreboard for {exercise_name} by @{submitter} in " | ||||||
|                 ), |                         f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" | ||||||
|             ) |                         f"gitea actions link: {gitea_actions_url}\n" | ||||||
|         if not skip_failed_table: |                         f"gitea issue link: {gitea_issue_url}" | ||||||
|             joj3.generate_failed_table( |                     ), | ||||||
|                 score_file_path, |                 ) | ||||||
|                 submitter_repo_name, |             if not skip_failed_table: | ||||||
|                 submitter_repo_url, |                 joj3.generate_failed_table( | ||||||
|                 os.path.join(repo_path, failed_table_file_name), |                     score_file_path, | ||||||
|                 gitea_actions_url, |                     submitter_repo_name, | ||||||
|             ) |                     submitter_repo_url, | ||||||
|             tea.pot.git.add_commit( |                     os.path.join(repo_path, failed_table_file_name), | ||||||
|                 repo_name, |                     gitea_actions_url, | ||||||
|                 [failed_table_file_name], |                 ) | ||||||
|                 ( |                 tea.pot.git.add_commit( | ||||||
|                     f"joj3: update failed table for {exercise_name} by @{submitter} in " |                     repo_name, | ||||||
|                     f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" |                     [failed_table_file_name], | ||||||
|                     f"gitea actions link: {gitea_actions_url}" |                     ( | ||||||
|                     f"gitea issue link: {gitea_issue_url}" |                         f"joj3: update failed table for {exercise_name} by @{submitter} in " | ||||||
|                 ), |                         f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" | ||||||
|             ) |                         f"gitea actions link: {gitea_actions_url}" | ||||||
|         tea.pot.git.push(repo_name) |                         f"gitea issue link: {gitea_issue_url}" | ||||||
|  |                     ), | ||||||
|  |                 ) | ||||||
|  |             push_info_list = tea.pot.git.push(repo_name) | ||||||
|  |             git_push_ok = push_info_list.error is None | ||||||
|  |             if not git_push_ok: | ||||||
|  |                 retry_interval *= 2 | ||||||
|  |                 logger.info( | ||||||
|  |                     f"git push failed, retry in {retry_interval} seconds: {push_info_list}" | ||||||
|  |                 ) | ||||||
|  |                 if retry_interval > 64: | ||||||
|  |                     logger.error(f"git push failed too many times") | ||||||
|  |                     return | ||||||
|  |                 sleep(retry_interval) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ current_path = sys.path[0] | ||||||
| sys.path.remove(current_path) | sys.path.remove(current_path) | ||||||
| from git import Repo | from git import Repo | ||||||
| from git.exc import GitCommandError | from git.exc import GitCommandError | ||||||
|  | from git.remote import PushInfoList | ||||||
| 
 | 
 | ||||||
| sys.path.insert(0, current_path) | sys.path.insert(0, current_path) | ||||||
| 
 | 
 | ||||||
|  | @ -117,6 +118,6 @@ class Git: | ||||||
|         if repo.is_dirty(untracked_files=True) or repo.index.diff(None): |         if repo.is_dirty(untracked_files=True) or repo.index.diff(None): | ||||||
|             repo.index.commit(commit_message) |             repo.index.commit(commit_message) | ||||||
| 
 | 
 | ||||||
|     def push(self, repo_name: str) -> None: |     def push(self, repo_name: str) -> PushInfoList: | ||||||
|         repo: Repo = self.get_repo(repo_name) |         repo: Repo = self.get_repo(repo_name) | ||||||
|         repo.remote(name="origin").push() |         return repo.remote(name="origin").push() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user