feat: joj3 auto retry on git push failed

This commit is contained in:
张泊明518370910136 2024-10-30 18:03:16 -04:00
parent 0ad1e9540a
commit a4f6482b21
Signed by untrusted user: 张泊明518370910136
GPG Key ID: CA088E6D9284F870
2 changed files with 65 additions and 51 deletions

View File

@ -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__":

View File

@ -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()